From 545416928514e3db20f068d6d200f1c5e3ae9ff5 Mon Sep 17 00:00:00 2001 From: Tony O Date: Sun, 29 Apr 2018 11:40:16 +0100 Subject: [PATCH 001/118] Initial commit --- .gitignore | 52 ++++++++ LICENSE | 373 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 425 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6127b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a612ad9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 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/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. From 4fde36451222b071df74bee93a08322759eccbb8 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 29 Apr 2018 22:26:14 +0100 Subject: [PATCH 002/118] Registration --- .gitignore | 1 + .gitmodules | 6 + Makefile | 42 + json-c | 1 + libwebsockets | 1 + slack-command.c | 186 +++++ slack-command.h | 6 + slack-config.c | 285 +++++++ slack-config.h | 44 + slack-oauth.c | 233 ++++++ slack-oauth.h | 6 + slack-workspace.c | 142 ++++ slack-workspace.h | 33 + slack.c | 43 + slack.h | 13 + weechat-plugin.h | 2037 +++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 3079 insertions(+) create mode 100644 .gitmodules create mode 100644 Makefile create mode 160000 json-c create mode 160000 libwebsockets create mode 100644 slack-command.c create mode 100644 slack-command.h create mode 100644 slack-config.c create mode 100644 slack-config.h create mode 100644 slack-oauth.c create mode 100644 slack-oauth.h create mode 100644 slack-workspace.c create mode 100644 slack-workspace.h create mode 100644 slack.c create mode 100644 slack.h create mode 100644 weechat-plugin.h diff --git a/.gitignore b/.gitignore index c6127b3..4e9fb6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Prerequisites +.depend *.d # Object files diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..633f768 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "libwebsockets"] + path = libwebsockets + url = https://github.com/warmcat/libwebsockets +[submodule "json-c"] + path = json-c + url = https://github.com/json-c/json-c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0bde5c4 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +CC=clang +CXX=clang++ +RM=rm -f +CFLAGS=-fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -I libwebsockets/include -I json-c +LDFLAGS=-shared -g +LDLIBS=-lssl + +SRCS=slack.c \ + slack-config.c \ + slack-command.c \ + slack-oauth.c \ + slack-workspace.c +OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a + +all: weechat-slack + +weechat-slack: $(OBJS) + $(CC) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) + +libwebsockets/lib/libwebsockets.a: + cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF . + $(MAKE) -C libwebsockets + +json-c/libjson-c.a: + cd json-c && cmake -DCMAKE_C_FLAGS=-fPIC . + $(MAKE) -C json-c json-c-static + +depend: .depend + +.depend: $(SRCS) + $(RM) ./.depend + $(CC) $(CFLAGS) -MM $^>>./.depend; + +clean: + $(RM) $(OBJS) + $(MAKE) -C libwebsockets clean + $(MAKE) -C json-c clean + +distclean: clean + $(RM) *~ .depend + +include .depend diff --git a/json-c b/json-c new file mode 160000 index 0000000..c75ebe8 --- /dev/null +++ b/json-c @@ -0,0 +1 @@ +Subproject commit c75ebe8973b1f03d3b3ef429c114e8d2192dc0c0 diff --git a/libwebsockets b/libwebsockets new file mode 160000 index 0000000..91a47f4 --- /dev/null +++ b/libwebsockets @@ -0,0 +1 @@ +Subproject commit 91a47f4fab4d74f49a341ce22954a563f6544446 diff --git a/slack-command.c b/slack-command.c new file mode 100644 index 0000000..9c940da --- /dev/null +++ b/slack-command.c @@ -0,0 +1,186 @@ +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-command.h" +#include "slack-oauth.h" +#include "slack-workspace.h" + +void slack_command_display_workspace(struct t_slack_workspace *workspace) +{ + int num_channels, num_pv; + + if (workspace->is_connected) + { + num_channels = 0;//slack_workspace_get_channel_count(workspace); + num_pv = 0;//slack_workspace_get_pv_count(workspace); + weechat_printf( + NULL, + " %s %s%s %s[%s%s%s]%s, %d %s, %d pv", + (workspace->is_connected) ? "*" : " ", + weechat_color("chat_workspace"), + workspace->name, + weechat_color("chat_delimiters"), + weechat_color("reset"), + (workspace->is_connected) ? + _("connected") : _("not connected"), + weechat_color("chat_delimiters"), + weechat_color("reset"), + num_channels, + NG_("channel", "channels", num_channels), + num_pv); + } + else + { + weechat_printf( + NULL, + " %s%s%s", + weechat_color("chat_workspace"), + workspace->name, + weechat_color("reset")); + } +} + +void slack_command_workspace_list(int argc, char **argv) +{ + int i, one_workspace_found; + struct t_slack_workspace *ptr_workspace2; + char *workspace_name = NULL; + + for (i = 2; i < argc; i++) + { + if (!workspace_name) + workspace_name = argv[i]; + } + if (!workspace_name) + { + if (slack_workspaces) + { + weechat_printf(NULL, ""); + weechat_printf(NULL, _("All workspaces:")); + for (ptr_workspace2 = slack_workspaces; ptr_workspace2; + ptr_workspace2 = ptr_workspace2->next_workspace) + { + slack_command_display_workspace(ptr_workspace2); + } + } + else + weechat_printf(NULL, _("No workspace")); + } + else + { + one_workspace_found = 0; + for (ptr_workspace2 = slack_workspaces; ptr_workspace2; + ptr_workspace2 = ptr_workspace2->next_workspace) + { + if (weechat_strcasestr(ptr_workspace2->name, workspace_name)) + { + if (!one_workspace_found) + { + weechat_printf(NULL, ""); + weechat_printf(NULL, + _("Servers with \"%s\":"), + workspace_name); + } + one_workspace_found = 1; + slack_command_display_workspace(ptr_workspace2); + } + } + if (!one_workspace_found) + weechat_printf(NULL, + _("No workspace found with \"%s\""), + workspace_name); + } +} + +void slack_command_add_workspace(char *token) +{ + free(token); +} + +void slack_command_workspace_register(int argc, char **argv) +{ + char *code; + + if (argc > 2) + { + code = argv[2]; + + if (weechat_strncasecmp("xoxp", code, 4) == 0) + { + slack_command_add_workspace(strdup(code)); + } + else + { + slack_oauth_request_token(code, &slack_command_add_workspace); + } + } + else + { + weechat_printf(NULL, + _("\n#### Retrieving a Slack token via OAUTH ####\n" + "1) Paste this into a browser: https://slack.com/oauth/authorize?client_id=%s&scope=client\n" + "2) Select the team you wish to access from wee-slack in your browser.\n" + "3) Click \"Authorize\" in the browser **IMPORTANT: the redirect will fail, this is expected**\n" + "4) Copy the \"code\" portion of the URL to your clipboard\n" + "5) Return to weechat and run `/slack register [code]`\n"), + SLACK_CLIENT_ID); + } +} + +void slack_command_workspace_delete(int argc, char **argv) +{ +} + +int slack_command_slack(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) buffer; + + if (argc > 1) + { + if (weechat_strcasecmp(argv[1], "list") == 0) + { + slack_command_workspace_list(argc, argv); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp(argv[1], "register") == 0) + { + slack_command_workspace_register(argc, argv); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp(argv[1], "delete") == 0) + { + slack_command_workspace_delete(argc, argv); + return WEECHAT_RC_OK; + } + + WEECHAT_COMMAND_ERROR; + } + + return WEECHAT_RC_OK; +} + +void slack_command_init() +{ + weechat_hook_command( + "slack", + N_("slack control"), + N_("list" + " || register [token]" + " || delete "), + N_(" list: list workspaces\n" + "register: add a slack workspace\n" + " delete: delete a slack workspace\n"), + "list" + " || register %(slack_token)" + " || delete %(slack_workspace)", + &slack_command_slack, NULL, NULL); +} diff --git a/slack-command.h b/slack-command.h new file mode 100644 index 0000000..66c3434 --- /dev/null +++ b/slack-command.h @@ -0,0 +1,6 @@ +#ifndef _SLACK_COMMAND_H_ +#define _SLACK_COMMAND_H_ + +extern void slack_command_init(); + +#endif /*SLACK_COMMAND_H*/ diff --git a/slack-config.c b/slack-config.c new file mode 100644 index 0000000..a6c59cb --- /dev/null +++ b/slack-config.c @@ -0,0 +1,285 @@ +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-config.h" +#include "slack-workspace.h" + +struct t_config_file *slack_config_file; + +struct t_config_section *slack_config_section_workspace_default; +struct t_config_section *slack_config_section_workspace; + +struct t_config_option *slack_config_workspace_default[SLACK_WORKSPACE_NUM_OPTIONS]; + +int slack_config_workspace_check_value_cb(const void *pointer, void *data, + struct t_config_option *option, + const char *value) +{ + return 1; +} + +void slack_config_workspace_change_cb(const void *pointer, void *data, + struct t_config_option *option) +{ +} + +void slack_config_workspace_default_change_cb(const void *pointer, void *data, + struct t_config_option *option) +{ +} + +struct t_config_option * +slack_config_workspace_new_option (struct t_config_file *config_file, + struct t_config_section *section, + int index_option, + const char *option_name, + const char *default_value, + const char *value, + int null_value_allowed, + int (*callback_check_value)(const void *pointer, + void *data, + struct t_config_option *option, + const char *value), + const void *callback_check_value_pointer, + void *callback_check_value_data, + void (*callback_change)(const void *pointer, + void *data, + struct t_config_option *option), + const void *callback_change_pointer, + void *callback_change_data) +{ + struct t_config_option *new_option; + + new_option = NULL; + + switch (index_option) + { + case SLACK_WORKSPACE_OPTION_TOKEN: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("slack api token"), + 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 SLACK_WORKSPACE_NUM_OPTIONS: + break; + } + + return new_option; +} + +void slack_config_workspace_create_default_options(struct t_config_section *section) +{ + int i; + + for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + { + slack_config_workspace_default[i] = slack_config_workspace_new_option( + slack_config_file, + section, + i, + slack_workspace_options[i][0], + slack_workspace_options[i][1], + slack_workspace_options[i][1], + 0, + &slack_config_workspace_check_value_cb, + slack_workspace_options[i][0], + NULL, + &slack_config_workspace_default_change_cb, + slack_workspace_options[i][0], + NULL); + } +} + +int slack_config_reload (const void *pointer, void *data, + struct t_config_file *config_file) +{ + /* make C compiler happy */ + (void) pointer; + (void) data; + + //weechat_config_section_free_options(slack_config_section_workspace_default); + //weechat_config_section_free_options(slack_config_section_workspace); + //slack_workspace_free_all(); + + return weechat_config_reload(config_file); +} + + + +int slack_config_workspace_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_slack_workspace *ptr_workspace; + int index_option, rc, i; + char *pos_option, *workspace_name; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) config_file; + (void) section; + + rc = WEECHAT_CONFIG_OPTION_SET_ERROR; + + if (option_name) + { + pos_option = strrchr(option_name, '.'); + if (pos_option) + { + workspace_name = weechat_strndup(option_name, + pos_option - option_name); + pos_option++; + if (workspace_name) + { + index_option = slack_workspace_search_option(pos_option); + if (index_option >= 0) + { + ptr_workspace = slack_workspace_search(workspace_name); + if (!ptr_workspace) + ptr_workspace = slack_workspace_alloc(workspace_name); + if (ptr_workspace) + { + if (ptr_workspace->reloading_from_config + && !ptr_workspace->reloaded_from_config) + { + for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + { + weechat_config_option_set( + ptr_workspace->options[i], NULL, 1); + } + ptr_workspace->reloaded_from_config = 1; + } + rc = weechat_config_option_set( + ptr_workspace->options[index_option], value, 1); + } + else + { + weechat_printf( + NULL, + _("%s%s: error adding workspace \"%s\""), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + workspace_name); + } + } + free(workspace_name); + } + } + } + + if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR) + { + weechat_printf( + NULL, + _("%s%s: error creating workspace option \"%s\""), + weechat_prefix("error"), SLACK_PLUGIN_NAME, option_name); + } + + return rc; +} + +int slack_config_workspace_write_cb (const void *pointer, void *data, + struct t_config_file *config_file, + const char *section_name) +{ + struct t_slack_workspace *ptr_workspace; + int i; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + if (!weechat_config_write_line(config_file, section_name, NULL)) + return WEECHAT_CONFIG_WRITE_ERROR; + + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + { + if (!weechat_config_write_option(config_file, + ptr_workspace->options[i])) + return WEECHAT_CONFIG_WRITE_ERROR; + } + } + + return WEECHAT_CONFIG_WRITE_OK; +} + +int slack_config_init() +{ + struct t_config_section *ptr_section; + + slack_config_file = weechat_config_new(SLACK_CONFIG_NAME, + &slack_config_reload, NULL, NULL); + + if(!slack_config_file) + return 0; + + ptr_section = weechat_config_new_section( + slack_config_file, "workspace_default", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + + if (!ptr_section) + { + weechat_config_free(slack_config_file); + slack_config_file = NULL; + return 0; + } + + slack_config_section_workspace_default = ptr_section; + + slack_config_workspace_create_default_options(ptr_section); + + ptr_section = weechat_config_new_section( + slack_config_file, "workspace", + 0, 0, + &slack_config_workspace_read_cb, NULL, NULL, + &slack_config_workspace_write_cb, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + + if (!ptr_section) + { + weechat_config_free(slack_config_file); + slack_config_file = NULL; + return 0; + } + + slack_config_section_workspace = ptr_section; + + return 1; +} + +int slack_config_read() +{ + return 1; +} + +int slack_config_write() +{ + return 1; +} + +void slack_config_free() +{ +} diff --git a/slack-config.h b/slack-config.h new file mode 100644 index 0000000..13e33cb --- /dev/null +++ b/slack-config.h @@ -0,0 +1,44 @@ +#ifndef _SLACK_CONFIG_H_ +#define _SLACK_CONFIG_H_ + +#define SLACK_CONFIG_NAME "slack" + +extern struct t_config_file *slack_config_file; + +extern struct t_config_section *slack_config_section_workspace_default; +extern struct t_config_section *slack_config_section_workspace; + +extern struct t_config_option *slack_config_workspace_default[]; + +int slack_config_workspace_check_value_cb(const void *pointer, void *data, + struct t_config_option *option, + const char *value); + +void slack_config_workspace_change_cb(const void *pointer, void *data, + struct t_config_option *option); + +struct t_config_option *slack_config_workspace_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 slack_config_init(); +extern int slack_config_read(); +extern int slack_config_write(); +extern void slack_config_free(); + +#endif /*SLACK_CONFIG_H*/ diff --git a/slack-oauth.c b/slack-oauth.c new file mode 100644 index 0000000..c18836f --- /dev/null +++ b/slack-oauth.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-oauth.h" + +static void (*weechat_callback)(char *token); + +static const char *const endpoint = "/api/oauth.access?" + "client_id=%s&client_secret=%s&code=%s"; +static char *uri; + +static int n = 0; +static struct lws *client_wsi = NULL; +static struct lws_context *context = NULL; + +static struct t_hook *slack_oauth_hook_timer = NULL; + +static int json_valid(json_object *object) +{ + if (!object) + { + weechat_printf( + NULL, + _("%s%s: Error retrieving token: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return 0; + } + + return 1; +} + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + NULL, + _("%s%s: error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + in ? (char *)in : "(null)"); + client_wsi = NULL; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + NULL, + _("%s%s: Retrieving token... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + char *json_string = weechat_strndup(in, (int)len); + json_object *response, *ok, *error, *token; + + weechat_printf( + NULL, + _("%s%s: Got token: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + token = json_object_object_get(response, "access_token"); + if (!json_valid(token)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + NULL, + _("%s%s: Retrieved token: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_object_get_string(token)); + + weechat_callback(strdup(json_object_get_string(token))); + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + NULL, + _("%s%s: Failed to retrieve token: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + client_wsi = NULL; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + client_wsi = NULL; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +int slack_oauth_timer_cb(const void *pointer, void *data, int remaining_calls) +{ + if (n >= 0 && client_wsi) + { + n = lws_service(context, 0); + } + else if (context) + { + lws_context_destroy(context); + context = NULL; + free(uri); + + if (slack_oauth_hook_timer) + weechat_unhook(slack_oauth_hook_timer); + } + + return WEECHAT_RC_OK; +} + +void slack_oauth_request_token(char *code, void (*callback)(char *token)) +{ + struct lws_context_creation_info info; + struct lws_client_connect_info i; + + size_t urilen = snprintf(NULL, 0, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code) + 1; + uri = malloc(urilen); + snprintf(uri, urilen, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code); + + lws_set_log_level(0, NULL); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.protocols = protocols; + + context = lws_create_context(&info); + if (!context) + { + weechat_printf( + NULL, + _("%s%s: error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + else + { + weechat_printf( + NULL, + _("%s%s: Contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + } + + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + i.context = context; + i.ssl_connection = LCCSCF_USE_SSL; + i.port = 443; + i.address = "slack.com"; + i.path = uri; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + i.protocol = protocols[0].name; + i.pwsi = &client_wsi; + + lws_client_connect_via_info(&i); + + slack_oauth_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, + &slack_oauth_timer_cb, + NULL, NULL); + + weechat_callback = callback; +} diff --git a/slack-oauth.h b/slack-oauth.h new file mode 100644 index 0000000..5d078ea --- /dev/null +++ b/slack-oauth.h @@ -0,0 +1,6 @@ +#ifndef _SLACK_OAUTH_H_ +#define _SLACK_OAUTH_H_ + +extern void slack_oauth_request_token(char *code, void (*callback)(char *token)); + +#endif /*SLACK_OAUTH_H*/ diff --git a/slack-workspace.c b/slack-workspace.c new file mode 100644 index 0000000..e2e3c62 --- /dev/null +++ b/slack-workspace.c @@ -0,0 +1,142 @@ +#include +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-config.h" +#include "slack-workspace.h" + +struct t_slack_workspace *slack_workspaces = NULL; +struct t_slack_workspace *last_slack_workspace = NULL; + +char *slack_workspace_options[SLACK_WORKSPACE_NUM_OPTIONS][2] = +{ { "token", "" }, +}; + +struct t_slack_workspace *slack_workspace_search(const char *workspace_name) +{ + struct t_slack_workspace *ptr_workspace; + + if (!workspace_name) + return NULL; + + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + if (strcmp(ptr_workspace->name, workspace_name) == 0) + return ptr_workspace; + } + + /* workspace not found */ + return NULL; +} + +struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_name) +{ + struct t_slack_workspace *ptr_workspace; + + if (!workspace_name) + return NULL; + + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + if (weechat_strcasecmp (ptr_workspace->name, workspace_name) == 0) + return ptr_workspace; + } + + /* workspace not found */ + return NULL; +} + +int slack_workspace_search_option(const char *option_name) +{ + int i; + + if (!option_name) + return -1; + + for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + { + if (weechat_strcasecmp(slack_workspace_options[i][0], option_name) == 0) + return i; + } + + /* workspace option not found */ + return -1; +} + +struct t_slack_workspace *slack_workspace_alloc(const char *name) +{ + struct t_slack_workspace *new_workspace; + int i, length; + char *option_name; + + if (slack_workspace_casesearch(name)) + return NULL; + + /* alloc memory for new workspace */ + new_workspace = malloc(sizeof(*new_workspace)); + if (!new_workspace) + { + weechat_printf(NULL, + _("%s%s: error when allocating new workspace"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return NULL; + } + + /* add new workspace to queue */ + new_workspace->prev_workspace = last_slack_workspace; + new_workspace->next_workspace = NULL; + if (last_slack_workspace) + last_slack_workspace->next_workspace = new_workspace; + else + slack_workspaces = new_workspace; + last_slack_workspace = new_workspace; + + /* set name */ + new_workspace->name = strdup(name); + + /* internal vars */ + new_workspace->reloading_from_config = 0; + new_workspace->reloaded_from_config = 0; + + new_workspace->is_connected = 0; + + /* create options with null value */ + for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + { + length = strlen(new_workspace->name) + 1 + + strlen(slack_workspace_options[i][0]) + + 512 + /* inherited option name(slack.workspace_default.xxx) */ + 1; + option_name = malloc(length); + if (option_name) + { + snprintf(option_name, length, "%s.%s << slack.workspace_default.%s", + new_workspace->name, + slack_workspace_options[i][0], + slack_workspace_options[i][0]); + new_workspace->options[i] = slack_config_workspace_new_option( + slack_config_file, + slack_config_section_workspace, + i, + option_name, + NULL, + NULL, + 1, + &slack_config_workspace_check_value_cb, + slack_workspace_options[i][0], + NULL, + &slack_config_workspace_change_cb, + slack_workspace_options[i][0], + NULL); + slack_config_workspace_change_cb(slack_workspace_options[i][0], NULL, + new_workspace->options[i]); + free(option_name); + } + } + + return new_workspace; +} diff --git a/slack-workspace.h b/slack-workspace.h new file mode 100644 index 0000000..2b79eb6 --- /dev/null +++ b/slack-workspace.h @@ -0,0 +1,33 @@ +#ifndef _SLACK_WORKSPACE_H_ +#define _SLACK_WORKSPACE_H_ + +extern struct t_slack_workspace *slack_workspaces; +extern struct t_slack_workspace *last_slack_workspace; + +enum t_slack_workspace_option +{ + SLACK_WORKSPACE_OPTION_TOKEN = 0, + SLACK_WORKSPACE_NUM_OPTIONS, +}; + +struct t_slack_workspace +{ + char *name; + struct t_config_option *options[SLACK_WORKSPACE_NUM_OPTIONS]; + + int reloading_from_config; + int reloaded_from_config; + + int is_connected; + + struct t_slack_workspace *prev_workspace; + struct t_slack_workspace *next_workspace; +}; + +extern char *slack_workspace_options[][2]; + +struct t_slack_workspace *slack_workspace_search(const char *workspace_name); +int slack_workspace_search_option(const char *option_name); +struct t_slack_workspace *slack_workspace_alloc(const char *name); + +#endif /*SLACK_WORKSPACE_H*/ diff --git a/slack.c b/slack.c new file mode 100644 index 0000000..f1ba914 --- /dev/null +++ b/slack.c @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-config.h" +#include "slack-command.h" + + +WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME); +WEECHAT_PLUGIN_DESCRIPTION(N_("Slack (slack.com) protocol")); +WEECHAT_PLUGIN_AUTHOR("Tony Olagbaiye "); +WEECHAT_PLUGIN_VERSION(SLACK_PLUGIN_VERSION); +WEECHAT_PLUGIN_LICENSE("MPL2"); +WEECHAT_PLUGIN_PRIORITY(6000); + +struct t_weechat_plugin *weechat_slack_plugin = NULL; + +int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) +{ + (void) argc; + (void) argv; + + weechat_plugin = plugin; + + if (!slack_config_init()) + return WEECHAT_RC_ERROR; + + slack_config_read(); + + slack_command_init(); + + return WEECHAT_RC_OK; +} + +int weechat_plugin_end(struct t_weechat_plugin *plugin) +{ + /* make C compiler happy */ + (void) plugin; + + return WEECHAT_RC_OK; +} diff --git a/slack.h b/slack.h new file mode 100644 index 0000000..21c6b7f --- /dev/null +++ b/slack.h @@ -0,0 +1,13 @@ +#ifndef _SLACK_H_ +#define _SLACK_H_ + +#define weechat_plugin weechat_slack_plugin +#define SLACK_PLUGIN_NAME "slack" +#define SLACK_PLUGIN_VERSION "0.1" + +#define SLACK_CLIENT_ID "2468770254.51917335286" +#define SLACK_CLIENT_SECRET "dcb7fe380a000cba0cca3169a5fe8d70" + +extern struct t_weechat_plugin *weechat_slack_plugin; + +#endif /*SLACK_H*/ diff --git a/weechat-plugin.h b/weechat-plugin.h new file mode 100644 index 0000000..02dc525 --- /dev/null +++ b/weechat-plugin.h @@ -0,0 +1,2037 @@ +/* + * weechat-plugin.h - header to compile WeeChat plugins + * + * Copyright (C) 2003-2018 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#ifndef WEECHAT_WEECHAT_PLUGIN_H +#define WEECHAT_WEECHAT_PLUGIN_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include +#include + +/* some systems like GNU/Hurd do not define PATH_MAX */ +#ifndef PATH_MAX + #define PATH_MAX 4096 +#endif /* PATH_MAX */ + +struct t_config_option; +struct t_config_section; +struct t_config_file; +struct t_gui_window; +struct t_gui_buffer; +struct t_gui_bar; +struct t_gui_bar_item; +struct t_gui_bar_window; +struct t_gui_completion; +struct t_gui_nick; +struct t_gui_nick_group; +struct t_infolist; +struct t_infolist_item; +struct t_upgrade_file; +struct t_weelist; +struct t_weelist_item; +struct t_arraylist; +struct t_hashtable; +struct t_hdata; +struct timeval; + +/* + * IMPORTANT NOTE for WeeChat developers: if you update, add or remove + * some functions in this file, then please update API version below. + */ + +/* + * API version (used to check that plugin has same API and can be loaded): + * please change the date with current one; for a second change at same + * date, increment the 01, otherwise please keep 01. + */ +#define WEECHAT_PLUGIN_API_VERSION "20171223-01" + +/* macros for defining plugin infos */ +#define WEECHAT_PLUGIN_NAME(__name) \ + char weechat_plugin_name[] = __name; \ + char weechat_plugin_api_version[] = WEECHAT_PLUGIN_API_VERSION; +#define WEECHAT_PLUGIN_AUTHOR(__author) \ + char weechat_plugin_author[] = __author; +#define WEECHAT_PLUGIN_DESCRIPTION(__desc) \ + char weechat_plugin_description[] = __desc; +#define WEECHAT_PLUGIN_VERSION(__version) \ + char weechat_plugin_version[] = __version; +#define WEECHAT_PLUGIN_LICENSE(__license) \ + char weechat_plugin_license[] = __license; +#define WEECHAT_PLUGIN_PRIORITY(__priority) \ + int weechat_plugin_priority = __priority; + +/* return codes for plugin functions */ +#define WEECHAT_RC_OK 0 +#define WEECHAT_RC_OK_EAT 1 +#define WEECHAT_RC_ERROR -1 + +/* return codes for config read functions/callbacks */ +#define WEECHAT_CONFIG_READ_OK 0 +#define WEECHAT_CONFIG_READ_MEMORY_ERROR -1 +#define WEECHAT_CONFIG_READ_FILE_NOT_FOUND -2 + +/* return codes for config write functions/callbacks */ +#define WEECHAT_CONFIG_WRITE_OK 0 +#define WEECHAT_CONFIG_WRITE_ERROR -1 +#define WEECHAT_CONFIG_WRITE_MEMORY_ERROR -2 + +/* null value for option */ +#define WEECHAT_CONFIG_OPTION_NULL "null" + +/* return codes for config option set */ +#define WEECHAT_CONFIG_OPTION_SET_OK_CHANGED 2 +#define WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE 1 +#define WEECHAT_CONFIG_OPTION_SET_ERROR 0 +#define WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND -1 + +/* return codes for config option unset */ +#define WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET 0 +#define WEECHAT_CONFIG_OPTION_UNSET_OK_RESET 1 +#define WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED 2 +#define WEECHAT_CONFIG_OPTION_UNSET_ERROR -1 + +/* list management (order of elements) */ +#define WEECHAT_LIST_POS_SORT "sort" +#define WEECHAT_LIST_POS_BEGINNING "beginning" +#define WEECHAT_LIST_POS_END "end" + +/* type for keys and values in hashtable */ +#define WEECHAT_HASHTABLE_INTEGER "integer" +#define WEECHAT_HASHTABLE_STRING "string" +#define WEECHAT_HASHTABLE_POINTER "pointer" +#define WEECHAT_HASHTABLE_BUFFER "buffer" +#define WEECHAT_HASHTABLE_TIME "time" + +/* types for hdata */ +#define WEECHAT_HDATA_OTHER 0 +#define WEECHAT_HDATA_CHAR 1 +#define WEECHAT_HDATA_INTEGER 2 +#define WEECHAT_HDATA_LONG 3 +#define WEECHAT_HDATA_STRING 4 +#define WEECHAT_HDATA_POINTER 5 +#define WEECHAT_HDATA_TIME 6 +#define WEECHAT_HDATA_HASHTABLE 7 +#define WEECHAT_HDATA_SHARED_STRING 8 + +/* flags for hdata lists */ +#define WEECHAT_HDATA_LIST_CHECK_POINTERS 1 + +/* buffer hotlist */ +#define WEECHAT_HOTLIST_LOW "0" +#define WEECHAT_HOTLIST_MESSAGE "1" +#define WEECHAT_HOTLIST_PRIVATE "2" +#define WEECHAT_HOTLIST_HIGHLIGHT "3" + +/* + * process return code (for callback): + * if >= 0, the process ended and it's return code of command + * if -1, the process is still running + * if -2, the process ended with an error + * if -3, the callback is called in the child process (exec of function) + * (note: the return code -3 is NEVER sent to script plugins, + * it can be used only in C API) + */ +#define WEECHAT_HOOK_PROCESS_RUNNING -1 +#define WEECHAT_HOOK_PROCESS_ERROR -2 +#define WEECHAT_HOOK_PROCESS_CHILD -3 + +/* connect status for connection hooked */ +#define WEECHAT_HOOK_CONNECT_OK 0 +#define WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND 1 +#define WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND 2 +#define WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED 3 +#define WEECHAT_HOOK_CONNECT_PROXY_ERROR 4 +#define WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR 5 +#define WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR 6 +#define WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR 7 +#define WEECHAT_HOOK_CONNECT_MEMORY_ERROR 8 +#define WEECHAT_HOOK_CONNECT_TIMEOUT 9 +#define WEECHAT_HOOK_CONNECT_SOCKET_ERROR 10 + +/* action for gnutls callback: verify or set certificate */ +#define WEECHAT_HOOK_CONNECT_GNUTLS_CB_VERIFY_CERT 0 +#define WEECHAT_HOOK_CONNECT_GNUTLS_CB_SET_CERT 1 + +/* type of data for signal hooked */ +#define WEECHAT_HOOK_SIGNAL_STRING "string" +#define WEECHAT_HOOK_SIGNAL_INT "int" +#define WEECHAT_HOOK_SIGNAL_POINTER "pointer" + +/* macro to format string with variable args, using dynamic buffer size */ +#define weechat_va_format(__format) \ + va_list argptr; \ + int vaa_size, vaa_num; \ + char *vbuffer, *vaa_buffer2; \ + vaa_size = 1024; \ + vbuffer = malloc (vaa_size); \ + if (vbuffer) \ + { \ + while (1) \ + { \ + va_start (argptr, __format); \ + vaa_num = vsnprintf (vbuffer, vaa_size, __format, argptr); \ + va_end (argptr); \ + if ((vaa_num >= 0) && (vaa_num < vaa_size)) \ + break; \ + vaa_size = (vaa_num >= 0) ? vaa_num + 1 : vaa_size * 2; \ + vaa_buffer2 = realloc (vbuffer, vaa_size); \ + if (!vaa_buffer2) \ + { \ + free (vbuffer); \ + vbuffer = NULL; \ + break; \ + } \ + vbuffer = vaa_buffer2; \ + } \ + } + +/* + * macro to return error in case of missing arguments in callback of + * hook_command + */ +#define WEECHAT_COMMAND_MIN_ARGS(__min_args, __option) \ + if (argc < __min_args) \ + { \ + weechat_printf_date_tags ( \ + NULL, 0, "no_filter", \ + _("%sToo few arguments for command \"%s%s%s\" " \ + "(help on command: /help %s)"), \ + weechat_prefix ("error"), \ + argv[0], \ + (__option && __option[0]) ? " " : "", \ + (__option && __option[0]) ? __option : "", \ + argv[0] + 1); \ + return WEECHAT_RC_ERROR; \ + } + +/* macro to return error in callback of hook_command */ +#define WEECHAT_COMMAND_ERROR \ + { \ + weechat_printf_date_tags ( \ + NULL, 0, "no_filter", \ + _("%sError with command \"%s\" " \ + "(help on command: /help %s)"), \ + weechat_prefix ("error"), \ + argv_eol[0], \ + argv[0] + 1); \ + return WEECHAT_RC_ERROR; \ + } + +struct t_weechat_plugin +{ + /* plugin variables */ + char *filename; /* name of plugin on disk */ + void *handle; /* handle of plugin (given by dlopen)*/ + char *name; /* short name */ + char *description; /* description */ + char *author; /* author */ + char *version; /* plugin version */ + char *license; /* license */ + char *charset; /* charset used by plugin */ + int priority; /* plugin priority (default is 1000) */ + int initialized; /* plugin initialized? (init called) */ + int debug; /* debug level for plugin (0=off) */ + struct t_hashtable *variables; /* plugin custom variables */ + struct t_weechat_plugin *prev_plugin; /* link to previous plugin */ + struct t_weechat_plugin *next_plugin; /* link to next plugin */ + + /* + * plugin functions (API) + * WeeChat developers: if you add functions in API, update value of + * constant WEECHAT_PLUGIN_API_VERSION + */ + + /* plugins */ + const char *(*plugin_get_name) (struct t_weechat_plugin *plugin); + + /* strings */ + void (*charset_set) (struct t_weechat_plugin *plugin, const char *charset); + char *(*iconv_to_internal) (const char *charset, const char *string); + char *(*iconv_from_internal) (const char *charset, const char *string); + const char *(*gettext) (const char *string); + const char *(*ngettext) (const char *single, const char *plural, int count); + char *(*strndup) (const char *string, int length); + void (*string_tolower) (char *string); + void (*string_toupper) (char *string); + int (*strcasecmp) (const char *string1, const char *string2); + int (*strcasecmp_range) (const char *string1, const char *string2, + int range); + int (*strncasecmp) (const char *string1, const char *string2, int max); + int (*strncasecmp_range) (const char *string1, const char *string2, + int max, int range); + int (*strcmp_ignore_chars) (const char *string1, const char *string2, + const char *chars_ignored, int case_sensitive); + const char *(*strcasestr) (const char *string, const char *search); + int (*strlen_screen) (const char *string); + int (*string_match) (const char *string, const char *mask, + int case_sensitive); + char *(*string_replace) (const char *string, const char *search, + const char *replace); + char *(*string_expand_home) (const char *path); + char *(*string_eval_path_home) (const char *path, + struct t_hashtable *pointers, + struct t_hashtable *extra_vars, + struct t_hashtable *options); + char *(*string_remove_quotes) (const char *string, const char *quotes); + char *(*string_strip) (const char *string, int left, int right, + const char *chars); + char *(*string_convert_escaped_chars) (const char *string); + char *(*string_mask_to_regex) (const char *mask); + const char *(*string_regex_flags) (const char *regex, int default_flags, + int *flags); + int (*string_regcomp) (void *preg, const char *regex, int default_flags); + int (*string_has_highlight) (const char *string, + const char *highlight_words); + int (*string_has_highlight_regex) (const char *string, const char *regex); + char *(*string_replace_regex) (const char *string, void *regex, + const char *replace, + const char reference_char, + char *(*callback)(void *data, + const char *text), + void *callback_data); + char **(*string_split) (const char *string, const char *separators, + int keep_eol, int num_items_max, int *num_items); + char **(*string_split_shell) (const char *string, int *num_items); + void (*string_free_split) (char **split_string); + char *(*string_build_with_split_string) (const char **split_string, + const char *separator); + char **(*string_split_command) (const char *command, char separator); + void (*string_free_split_command) (char **split_command); + char *(*string_format_size) (unsigned long long size); + char *(*string_remove_color) (const char *string, const char *replacement); + void (*string_encode_base64) (const char *from, int length, char *to); + int (*string_decode_base64) (const char *from, char *to); + char *(*string_hex_dump) (const char *data, int data_size, + int bytes_per_line, const char *prefix, + const char *suffix); + int (*string_is_command_char) (const char *string); + const char *(*string_input_for_buffer) (const char *string); + char *(*string_eval_expression )(const char *expr, + struct t_hashtable *pointers, + struct t_hashtable *extra_vars, + struct t_hashtable *options); + char **(*string_dyn_alloc) (int size_alloc); + int (*string_dyn_copy) (char **string, const char *new_string); + int (*string_dyn_concat) (char **string, const char *add); + char *(*string_dyn_free) (char **string, int free_string); + + /* UTF-8 strings */ + int (*utf8_has_8bits) (const char *string); + int (*utf8_is_valid) (const char *string, int length, char **error); + void (*utf8_normalize) (char *string, char replacement); + const char *(*utf8_prev_char) (const char *string_start, + const char *string); + const char *(*utf8_next_char) (const char *string); + int (*utf8_char_int) (const char *string); + int (*utf8_char_size) (const char *string); + int (*utf8_strlen) (const char *string); + int (*utf8_strnlen) (const char *string, int bytes); + int (*utf8_strlen_screen) (const char *string); + int (*utf8_charcmp) (const char *string1, const char *string2); + int (*utf8_charcasecmp) (const char *string1, const char *string2); + int (*utf8_char_size_screen) (const char *string); + const char *(*utf8_add_offset) (const char *string, int offset); + int (*utf8_real_pos) (const char *string, int pos); + int (*utf8_pos) (const char *string, int real_pos); + char *(*utf8_strndup) (const char *string, int length); + + /* directories/files */ + int (*mkdir_home) (const char *directory, int mode); + int (*mkdir) (const char *directory, int mode); + int (*mkdir_parents) (const char *directory, int mode); + void (*exec_on_files) (const char *directory, int recurse_subdirs, + int hidden_files, + void (*callback)(void *data, const char *filename), + void *callback_data); + char *(*file_get_content) (const char *filename); + + /* util */ + int (*util_timeval_cmp) (struct timeval *tv1, struct timeval *tv2); + long long (*util_timeval_diff) (struct timeval *tv1, struct timeval *tv2); + void (*util_timeval_add) (struct timeval *tv, long long interval); + const char *(*util_get_time_string) (const time_t *date); + int (*util_version_number) (const char *version); + + /* sorted lists */ + struct t_weelist *(*list_new) (); + struct t_weelist_item *(*list_add) (struct t_weelist *weelist, + const char *data, + const char *where, + void *user_data); + struct t_weelist_item *(*list_search) (struct t_weelist *weelist, + const char *data); + int (*list_search_pos) (struct t_weelist *weelist, + const char *data); + struct t_weelist_item *(*list_casesearch) (struct t_weelist *weelist, + const char *data); + int (*list_casesearch_pos) (struct t_weelist *weelist, + const char *data); + struct t_weelist_item *(*list_get) (struct t_weelist *weelist, + int position); + void (*list_set) (struct t_weelist_item *item, const char *value); + struct t_weelist_item *(*list_next) (struct t_weelist_item *item); + struct t_weelist_item *(*list_prev) (struct t_weelist_item *item); + const char *(*list_string) (struct t_weelist_item *item); + int (*list_size) (struct t_weelist *weelist); + void (*list_remove) (struct t_weelist *weelist, + struct t_weelist_item *item); + void (*list_remove_all) (struct t_weelist *weelist); + void (*list_free) (struct t_weelist *weelist); + + /* array lists */ + struct t_arraylist *(*arraylist_new) (int initial_size, + int sorted, + int allow_duplicates, + int (*callback_cmp)(void *data, + struct t_arraylist *arraylist, + void *pointer1, + void *pointer2), + void *callback_cmp_data, + void (*callback_free)(void *data, + struct t_arraylist *arraylist, + void *pointer), + void *callback_free_data); + int (*arraylist_size) (struct t_arraylist *arraylist); + void *(*arraylist_get) (struct t_arraylist *arraylist, int index); + void *(*arraylist_search) (struct t_arraylist *arraylist, void *pointer, + int *index, int *index_insert); + int (*arraylist_insert) (struct t_arraylist *arraylist, int index, + void *pointer); + int (*arraylist_add) (struct t_arraylist *arraylist, void *pointer); + int (*arraylist_remove) (struct t_arraylist *arraylist, int index); + int (*arraylist_clear) (struct t_arraylist *arraylist); + void (*arraylist_free) (struct t_arraylist *arraylist); + + /* hash tables */ + struct t_hashtable *(*hashtable_new) (int size, + const char *type_keys, + const char *type_values, + unsigned long long (*callback_hash_key)(struct t_hashtable *hashtable, + const void *key), + int (*callback_keycmp)(struct t_hashtable *hashtable, + const void *key1, + const void *key2)); + struct t_hashtable_item *(*hashtable_set_with_size) (struct t_hashtable *hashtable, + const void *key, + int key_size, + const void *value, + int value_size); + struct t_hashtable_item *(*hashtable_set) (struct t_hashtable *hashtable, + const void *key, + const void *value); + void *(*hashtable_get) (struct t_hashtable *hashtable, const void *key); + int (*hashtable_has_key) (struct t_hashtable *hashtable, const void *key); + void (*hashtable_map) (struct t_hashtable *hashtable, + void (*callback_map) (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value), + void *callback_map_data); + void (*hashtable_map_string) (struct t_hashtable *hashtable, + void (*callback_map) (void *data, + struct t_hashtable *hashtable, + const char *key, + const char *value), + void *callback_map_data); + struct t_hashtable *(*hashtable_dup) (struct t_hashtable *hashtable); + int (*hashtable_get_integer) (struct t_hashtable *hashtable, + const char *property); + const char *(*hashtable_get_string) (struct t_hashtable *hashtable, + const char *property); + void (*hashtable_set_pointer) (struct t_hashtable *hashtable, + const char *property, + void *pointer); + int (*hashtable_add_to_infolist) (struct t_hashtable *hashtable, + struct t_infolist_item *infolist_item, + const char *prefix); + void (*hashtable_remove) (struct t_hashtable *hashtable, const void *key); + void (*hashtable_remove_all) (struct t_hashtable *hashtable); + void (*hashtable_free) (struct t_hashtable *hashtable); + + /* config files */ + struct t_config_file *(*config_new) (struct t_weechat_plugin *plugin, + const char *name, + int (*callback_reload)(const void *pointer, + void *data, + struct t_config_file *config_file), + const void *callback_reload_pointer, + void *callback_reload_data); + struct t_config_section *(*config_new_section) (struct t_config_file *config_file, + const char *name, + int user_can_add_options, + int user_can_delete_options, + int (*callback_read)(const void *pointer, + void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value), + const void *callback_read_pointer, + void *callback_read_data, + int (*callback_write)(const void *pointer, + void *data, + struct t_config_file *config_file, + const char *section_name), + const void *callback_write_pointer, + void *callback_write_data, + int (*callback_write_default)(const void *pointer, + void *data, + struct t_config_file *config_file, + const char *section_name), + const void *callback_write_default_pointer, + void *callback_write_default_data, + int (*callback_create_option)(const void *pointer, + void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value), + const void *callback_create_option_pointer, + void *callback_create_option_data, + int (*callback_delete_option)(const void *pointer, + void *data, + struct t_config_file *config_file, + struct t_config_section *section, + struct t_config_option *option), + const void *callback_delete_option_pointer, + void *callback_delete_option_data); + struct t_config_section *(*config_search_section) (struct t_config_file *config_file, + const char *section_name); + struct t_config_option *(*config_new_option) (struct t_config_file *config_file, + struct t_config_section *section, + const char *name, + const char *type, + const char *description, + const char *string_values, + int min, + int max, + 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, + void (*callback_delete)(const void *pointer, + void *data, + struct t_config_option *option), + const void *callback_delete_pointer, + void *callback_delete_data); + struct t_config_option *(*config_search_option) (struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name); + void (*config_search_section_option) (struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + struct t_config_section **section_found, + struct t_config_option **option_found); + void (*config_search_with_string) (const char *option_name, + struct t_config_file **config_file, + struct t_config_section **section, + struct t_config_option **option, + char **pos_option_name); + int (*config_string_to_boolean) (const char *text); + int (*config_option_reset) (struct t_config_option *option, + int run_callback); + int (*config_option_set) (struct t_config_option *option, + const char *value, int run_callback); + int (*config_option_set_null) (struct t_config_option *option, + int run_callback); + int (*config_option_unset) (struct t_config_option *option); + void (*config_option_rename) (struct t_config_option *option, + const char *new_name); + const char *(*config_option_get_string) (struct t_config_option *option, + const char *property); + void *(*config_option_get_pointer) (struct t_config_option *option, + const char *property); + int (*config_option_is_null) (struct t_config_option *option); + int (*config_option_default_is_null) (struct t_config_option *option); + int (*config_boolean) (struct t_config_option *option); + int (*config_boolean_default) (struct t_config_option *option); + int (*config_integer) (struct t_config_option *option); + int (*config_integer_default) (struct t_config_option *option); + const char *(*config_string) (struct t_config_option *option); + const char *(*config_string_default) (struct t_config_option *option); + const char *(*config_color) (struct t_config_option *option); + const char *(*config_color_default) (struct t_config_option *option); + int (*config_write_option) (struct t_config_file *config_file, + struct t_config_option *option); + int (*config_write_line) (struct t_config_file *config_file, + const char *option_name, + const char *value, ...); + int (*config_write) (struct t_config_file *config_file); + int (*config_read) (struct t_config_file *config_file); + int (*config_reload) (struct t_config_file *config_file); + void (*config_option_free) (struct t_config_option *option); + void (*config_section_free_options) (struct t_config_section *section); + void (*config_section_free) (struct t_config_section *section); + void (*config_free) (struct t_config_file *config_file); + struct t_config_option *(*config_get) (const char *option_name); + const char *(*config_get_plugin) (struct t_weechat_plugin *plugin, + const char *option_name); + int (*config_is_set_plugin) (struct t_weechat_plugin *plugin, + const char *option_name); + int (*config_set_plugin) (struct t_weechat_plugin *plugin, + const char *option_name, const char *value); + void (*config_set_desc_plugin) (struct t_weechat_plugin *plugin, + const char *option_name, + const char *description); + int (*config_unset_plugin) (struct t_weechat_plugin *plugin, + const char *option_name); + + /* key bindings */ + int (*key_bind) (const char *context, struct t_hashtable *keys); + int (*key_unbind) (const char *context, const char *key); + + /* display */ + const char *(*prefix) (const char *prefix); + const char *(*color) (const char *color_name); + void (*printf_date_tags) (struct t_gui_buffer *buffer, time_t date, + const char *tags, const char *message, ...); + void (*printf_y) (struct t_gui_buffer *buffer, int y, + const char *message, ...); + void (*log_printf) (const char *message, ...); + + /* hooks */ + struct t_hook *(*hook_command) (struct t_weechat_plugin *plugin, + const char *command, + const char *description, + const char *args, + const char *args_description, + const char *completion, + int (*callback)(const void *pointer, + void *data, + struct t_gui_buffer *buffer, + int argc, char **argv, + char **argv_eol), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_command_run) (struct t_weechat_plugin *plugin, + const char *command, + int (*callback)(const void *pointer, + void *data, + struct t_gui_buffer *buffer, + const char *command), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_timer) (struct t_weechat_plugin *plugin, + long interval, + int align_second, + int max_calls, + int (*callback)(const void *pointer, + void *data, + int remaining_calls), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_fd) (struct t_weechat_plugin *plugin, + int fd, + int flag_read, + int flag_write, + int flag_exception, + int (*callback)(const void *pointer, + void *data, + int fd), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_process) (struct t_weechat_plugin *plugin, + const char *command, + int timeout, + int (*callback)(const void *pointer, + void *data, + const char *command, + int return_code, + const char *out, + const char *err), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_process_hashtable) (struct t_weechat_plugin *plugin, + const char *command, + struct t_hashtable *options, + int timeout, + int (*callback)(const void *pointer, + void *data, + const char *command, + int return_code, + const char *out, + const char *err), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_connect) (struct t_weechat_plugin *plugin, + const char *proxy, + const char *address, + int port, + int ipv6, + int retry, + void *gnutls_sess, void *gnutls_cb, + int gnutls_dhkey_size, + const char *gnutls_priorities, + const char *local_hostname, + int (*callback)(const void *pointer, + void *data, + int status, + int gnutls_rc, + int sock, + const char *error, + const char *ip_address), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_print) (struct t_weechat_plugin *plugin, + struct t_gui_buffer *buffer, + const char *tags, + const char *message, + int strip_colors, + int (*callback)(const void *pointer, + void *data, + struct t_gui_buffer *buffer, + time_t date, + int tags_count, + const char **tags, + int displayed, + int highlight, + const char *prefix, + const char *message), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_signal) (struct t_weechat_plugin *plugin, + const char *signal, + int (*callback)(const void *pointer, + void *data, + const char *signal, + const char *type_data, + void *signal_data), + const void *callback_pointer, + void *callback_data); + int (*hook_signal_send) (const char *signal, const char *type_data, + void *signal_data); + struct t_hook *(*hook_hsignal) (struct t_weechat_plugin *plugin, + const char *signal, + int (*callback)(const void *pointer, + void *data, + const char *signal, + struct t_hashtable *hashtable), + const void *callback_pointer, + void *callback_data); + int (*hook_hsignal_send) (const char *signal, + struct t_hashtable *hashtable); + struct t_hook *(*hook_config) (struct t_weechat_plugin *plugin, + const char *option, + int (*callback)(const void *pointer, + void *data, + const char *option, + const char *value), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_completion) (struct t_weechat_plugin *plugin, + const char *completion_item, + const char *description, + int (*callback)(const void *pointer, + void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion), + const void *callback_pointer, + void *callback_data); + const char *(*hook_completion_get_string) (struct t_gui_completion *completion, + const char *property); + void (*hook_completion_list_add) (struct t_gui_completion *completion, + const char *word, + int nick_completion, + const char *where); + struct t_hook *(*hook_modifier) (struct t_weechat_plugin *plugin, + const char *modifier, + char *(*callback)(const void *pointer, + void *data, + const char *modifier, + const char *modifier_data, + const char *string), + const void *callback_pointer, + void *callback_data); + char *(*hook_modifier_exec) (struct t_weechat_plugin *plugin, + const char *modifier, + const char *modifier_data, + const char *string); + struct t_hook *(*hook_info) (struct t_weechat_plugin *plugin, + const char *info_name, + const char *description, + const char *args_description, + const char *(*callback)(const void *pointer, + void *data, + const char *info_name, + const char *arguments), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_info_hashtable) (struct t_weechat_plugin *plugin, + const char *info_name, + const char *description, + const char *args_description, + const char *output_description, + struct t_hashtable *(*callback)(const void *pointer, + void *data, + const char *info_name, + struct t_hashtable *hashtable), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_infolist) (struct t_weechat_plugin *plugin, + const char *infolist_name, + const char *description, + const char *pointer_description, + const char *args_description, + struct t_infolist *(*callback)(const void *cb_pointer, + void *data, + const char *infolist_name, + void *obj_pointer, + const char *arguments), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_hdata) (struct t_weechat_plugin *plugin, + const char *hdata_name, + const char *description, + struct t_hdata *(*callback)(const void *pointer, + void *data, + const char *hdata_name), + const void *callback_pointer, + void *callback_data); + struct t_hook *(*hook_focus) (struct t_weechat_plugin *plugin, + const char *area, + struct t_hashtable *(*callback)(const void *pointer, + void *data, + struct t_hashtable *info), + const void *callback_pointer, + void *callback_data); + void (*hook_set) (struct t_hook *hook, const char *property, + const char *value); + void (*unhook) (struct t_hook *hook); + void (*unhook_all) (struct t_weechat_plugin *plugin, + const char *subplugin); + + /* buffers */ + struct t_gui_buffer *(*buffer_new) (struct t_weechat_plugin *plugin, + const char *name, + int (*input_callback)(const void *pointer, + void *data, + struct t_gui_buffer *buffer, + const char *input_data), + const void *input_callback_pointer, + void *input_callback_data, + int (*close_callback)(const void *pointer, + void *data, + struct t_gui_buffer *buffer), + const void *close_callback_pointer, + void *close_callback_data); + struct t_gui_buffer *(*buffer_search) (const char *plugin, const char *name); + struct t_gui_buffer *(*buffer_search_main) (); + void (*buffer_clear) (struct t_gui_buffer *buffer); + void (*buffer_close) (struct t_gui_buffer *buffer); + void (*buffer_merge) (struct t_gui_buffer *buffer, + struct t_gui_buffer *target_buffer); + void (*buffer_unmerge) (struct t_gui_buffer *buffer, int number); + int (*buffer_get_integer) (struct t_gui_buffer *buffer, + const char *property); + const char *(*buffer_get_string) (struct t_gui_buffer *buffer, + const char *property); + void *(*buffer_get_pointer) (struct t_gui_buffer *buffer, + const char *property); + void (*buffer_set) (struct t_gui_buffer *buffer, const char *property, + const char *value); + void (*buffer_set_pointer) (struct t_gui_buffer *buffer, + const char *property, void *pointer); + char *(*buffer_string_replace_local_var) (struct t_gui_buffer *buffer, + const char *string); + int (*buffer_match_list) (struct t_gui_buffer *buffer, const char *string); + + /* windows */ + struct t_gui_window *(*window_search_with_buffer) (struct t_gui_buffer *buffer); + int (*window_get_integer) (struct t_gui_window *window, + const char *property); + const char *(*window_get_string) (struct t_gui_window *window, + const char *property); + void *(*window_get_pointer) (struct t_gui_window *window, + const char *property); + void (*window_set_title) (const char *title); + + /* nicklist */ + struct t_gui_nick_group *(*nicklist_add_group) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *parent_group, + const char *name, + const char *color, + int visible); + struct t_gui_nick_group *(*nicklist_search_group) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *from_group, + const char *name); + struct t_gui_nick *(*nicklist_add_nick) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group, + const char *name, + const char *color, + const char *prefix, + const char *prefix_color, + int visible); + struct t_gui_nick *(*nicklist_search_nick) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *from_group, + const char *name); + void (*nicklist_remove_group) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group); + void (*nicklist_remove_nick) (struct t_gui_buffer *buffer, + struct t_gui_nick *nick); + void (*nicklist_remove_all) (struct t_gui_buffer *buffer); + void (*nicklist_get_next_item) (struct t_gui_buffer *buffer, + struct t_gui_nick_group **group, + struct t_gui_nick **nick); + int (*nicklist_group_get_integer) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group, + const char *property); + const char *(*nicklist_group_get_string) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group, + const char *property); + void *(*nicklist_group_get_pointer) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group, + const char *property); + void (*nicklist_group_set) (struct t_gui_buffer *buffer, + struct t_gui_nick_group *group, + const char *property, const char *value); + int (*nicklist_nick_get_integer) (struct t_gui_buffer *buffer, + struct t_gui_nick *nick, + const char *property); + const char *(*nicklist_nick_get_string) (struct t_gui_buffer *buffer, + struct t_gui_nick *nick, + const char *property); + void *(*nicklist_nick_get_pointer) (struct t_gui_buffer *buffer, + struct t_gui_nick *nick, + const char *property); + void (*nicklist_nick_set) (struct t_gui_buffer *buffer, + struct t_gui_nick *nick, + const char *property, const char *value); + + /* bars */ + struct t_gui_bar_item *(*bar_item_search) (const char *name); + struct t_gui_bar_item *(*bar_item_new) (struct t_weechat_plugin *plugin, + const char *name, + char *(*build_callback)(const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info), + const void *build_callback_pointer, + void *build_callback_data); + void (*bar_item_update) (const char *name); + void (*bar_item_remove) (struct t_gui_bar_item *item); + struct t_gui_bar *(*bar_search) (const char *name); + struct t_gui_bar *(*bar_new) (const char *name, + const char *hidden, + const char *priority, + const char *type, + const char *condition, + const char *position, + const char *filling_top_bottom, + const char *filling_left_right, + const char *size, + const char *size_max, + const char *color_fg, + const char *color_delim, + const char *color_bg, + const char *separator, + const char *items); + int (*bar_set) (struct t_gui_bar *bar, const char *property, + const char *value); + void (*bar_update) (const char *name); + void (*bar_remove) (struct t_gui_bar *bar); + + /* command */ + int (*command) (struct t_weechat_plugin *plugin, + struct t_gui_buffer *buffer, const char *command); + + /* network */ + int (*network_pass_proxy) (const char *proxy, int sock, + const char *address, int port); + int (*network_connect_to) (const char *proxy, + struct sockaddr *address, + socklen_t address_length); + + /* infos */ + const char *(*info_get) (struct t_weechat_plugin *plugin, + const char *info_name, + const char *arguments); + struct t_hashtable *(*info_get_hashtable) (struct t_weechat_plugin *plugin, + const char *info_name, + struct t_hashtable *hashtable); + + /* infolists */ + struct t_infolist *(*infolist_new) (struct t_weechat_plugin *plugin); + struct t_infolist_item *(*infolist_new_item) (struct t_infolist *infolist); + struct t_infolist_var *(*infolist_new_var_integer) (struct t_infolist_item *item, + const char *name, + int value); + struct t_infolist_var *(*infolist_new_var_string) (struct t_infolist_item *item, + const char *name, + const char *value); + struct t_infolist_var *(*infolist_new_var_pointer) (struct t_infolist_item *item, + const char *name, + void *pointer); + struct t_infolist_var *(*infolist_new_var_buffer) (struct t_infolist_item *item, + const char *name, + void *pointer, + int size); + struct t_infolist_var *(*infolist_new_var_time) (struct t_infolist_item *item, + const char *name, + time_t time); + struct t_infolist_var *(*infolist_search_var) (struct t_infolist *infolist, + const char *name); + struct t_infolist *(*infolist_get) (struct t_weechat_plugin *plugin, + const char *infolist_name, + void *pointer, + const char *arguments); + int (*infolist_next) (struct t_infolist *infolist); + int (*infolist_prev) (struct t_infolist *infolist); + void (*infolist_reset_item_cursor) (struct t_infolist *infolist); + const char *(*infolist_fields) (struct t_infolist *infolist); + int (*infolist_integer) (struct t_infolist *infolist, const char *var); + const char *(*infolist_string) (struct t_infolist *infolist, const char *var); + void *(*infolist_pointer) (struct t_infolist *infolist, const char *var); + void *(*infolist_buffer) (struct t_infolist *infolist, const char *var, + int *size); + time_t (*infolist_time) (struct t_infolist *infolist, const char *var); + void (*infolist_free) (struct t_infolist *infolist); + + /* hdata */ + struct t_hdata *(*hdata_new) (struct t_weechat_plugin *plugin, + const char *hdata_name, const char *var_prev, + const char *var_next, + int create_allowed, int delete_allowed, + int (*callback_update)(void *data, + struct t_hdata *hdata, + void *pointer, + struct t_hashtable *hashtable), + void *callback_update_data); + void (*hdata_new_var) (struct t_hdata *hdata, const char *name, int offset, + int type, int update_allowed, const char *array_size, + const char *hdata_name); + void (*hdata_new_list) (struct t_hdata *hdata, const char *name, + void *pointer, int flags); + struct t_hdata *(*hdata_get) (struct t_weechat_plugin *plugin, + const char *hdata_name); + int (*hdata_get_var_offset) (struct t_hdata *hdata, const char *name); + int (*hdata_get_var_type) (struct t_hdata *hdata, const char *name); + const char *(*hdata_get_var_type_string) (struct t_hdata *hdata, + const char *name); + int (*hdata_get_var_array_size) (struct t_hdata *hdata, void *pointer, + const char *name); + const char *(*hdata_get_var_array_size_string) (struct t_hdata *hdata, + void *pointer, + const char *name); + const char *(*hdata_get_var_hdata) (struct t_hdata *hdata, + const char *name); + void *(*hdata_get_var) (struct t_hdata *hdata, void *pointer, + const char *name); + void *(*hdata_get_var_at_offset) (struct t_hdata *hdata, void *pointer, + int offset); + void *(*hdata_get_list) (struct t_hdata *hdata, const char *name); + int (*hdata_check_pointer) (struct t_hdata *hdata, void *list, + void *pointer); + void *(*hdata_move) (struct t_hdata *hdata, void *pointer, int count); + void *(*hdata_search) (struct t_hdata *hdata, void *pointer, + const char *search, int move); + char (*hdata_char) (struct t_hdata *hdata, void *pointer, + const char *name); + int (*hdata_integer) (struct t_hdata *hdata, void *pointer, + const char *name); + long (*hdata_long) (struct t_hdata *hdata, void *pointer, + const char *name); + const char *(*hdata_string) (struct t_hdata *hdata, void *pointer, + const char *name); + void *(*hdata_pointer) (struct t_hdata *hdata, void *pointer, + const char *name); + time_t (*hdata_time) (struct t_hdata *hdata, void *pointer, + const char *name); + struct t_hashtable *(*hdata_hashtable) (struct t_hdata *hdata, + void *pointer, const char *name); + int (*hdata_compare) (struct t_hdata *hdata, + void *pointer1, void *pointer2, const char *name, + int case_sensitive); + int (*hdata_set) (struct t_hdata *hdata, void *pointer, const char *name, + const char *value); + int (*hdata_update) (struct t_hdata *hdata, void *pointer, + struct t_hashtable *hashtable); + const char *(*hdata_get_string) (struct t_hdata *hdata, + const char *property); + + /* upgrade */ + struct t_upgrade_file *(*upgrade_new) (const char *filename, + int (*callback_read)(const void *pointer, + void *data, + struct t_upgrade_file *upgrade_file, + int object_id, + struct t_infolist *infolist), + const void *callback_read_pointer, + void *callback_read_data); + int (*upgrade_write_object) (struct t_upgrade_file *upgrade_file, + int object_id, + struct t_infolist *infolist); + int (*upgrade_read) (struct t_upgrade_file *upgrade_file); + void (*upgrade_close) (struct t_upgrade_file *upgrade_file); +}; + +extern int weechat_plugin_init (struct t_weechat_plugin *plugin, + int argc, char *argv[]); +extern int weechat_plugin_end (struct t_weechat_plugin *plugin); + +/* macros for easy call to plugin API */ + +/* plugins */ +#define weechat_plugin_get_name(__plugin) \ + (weechat_plugin->plugin_get_name)(__plugin) + +/* strings */ +#define weechat_charset_set(__charset) \ + (weechat_plugin->charset_set)(weechat_plugin, __charset) +#define weechat_iconv_to_internal(__charset, __string) \ + (weechat_plugin->iconv_to_internal)(__charset, __string) +#define weechat_iconv_from_internal(__charset, __string) \ + (weechat_plugin->iconv_from_internal)(__charset, __string) +#ifndef WEECHAT_H +#ifndef _ +#define _(string) (weechat_plugin->gettext)(string) +#endif /* _ */ +#ifndef N_ +#define N_(string) (string) +#endif /* N_ */ +#ifndef NG_ +#define NG_(single,plural,number) \ + (weechat_plugin->ngettext)(single, plural, number) +#endif /* NG_ */ +#endif /* WEECHAT_H */ +#define weechat_gettext(string) (weechat_plugin->gettext)(string) +#define weechat_ngettext(single,plural,number) \ + (weechat_plugin->ngettext)(single, plural, number) +#define weechat_strndup(__string, __length) \ + (weechat_plugin->strndup)(__string, __length) +#define weechat_string_tolower(__string) \ + (weechat_plugin->string_tolower)(__string) +#define weechat_string_toupper(__string) \ + (weechat_plugin->string_toupper)(__string) +#define weechat_strcasecmp(__string1, __string2) \ + (weechat_plugin->strcasecmp)(__string1, __string2) +#define weechat_strcasecmp_range(__string1, __string2, __range) \ + (weechat_plugin->strcasecmp_range)(__string1, __string2, __range) +#define weechat_strncasecmp(__string1, __string2, __max) \ + (weechat_plugin->strncasecmp)(__string1, __string2, __max) +#define weechat_strncasecmp_range(__string1, __string2, __max, __range) \ + (weechat_plugin->strncasecmp_range)(__string1, __string2, __max, \ + __range) +#define weechat_strcmp_ignore_chars(__string1, __string2, \ + __chars_ignored, __case_sensitive) \ + (weechat_plugin->strcmp_ignore_chars)(__string1, __string2, \ + __chars_ignored, \ + __case_sensitive) +#define weechat_strcasestr(__string, __search) \ + (weechat_plugin->strcasestr)(__string, __search) +#define weechat_strlen_screen(__string) \ + (weechat_plugin->strlen_screen)(__string) +#define weechat_string_match(__string, __mask, __case_sensitive) \ + (weechat_plugin->string_match)(__string, __mask, __case_sensitive) +#define weechat_string_replace(__string, __search, __replace) \ + (weechat_plugin->string_replace)(__string, __search, __replace) +#define weechat_string_expand_home(__path) \ + (weechat_plugin->string_expand_home)(__path) +#define weechat_string_eval_path_home(__path, __pointers, \ + __extra_vars, __options) \ + (weechat_plugin->string_eval_path_home)(__path, __pointers, \ + __extra_vars, __options) +#define weechat_string_remove_quotes(__string, __quotes) \ + (weechat_plugin->string_remove_quotes)(__string, __quotes) +#define weechat_string_strip(__string, __left, __right, __chars) \ + (weechat_plugin->string_strip)(__string, __left, __right, __chars) +#define weechat_string_convert_escaped_chars(__string) \ + (weechat_plugin->string_convert_escaped_chars)(__string) +#define weechat_string_mask_to_regex(__mask) \ + (weechat_plugin->string_mask_to_regex)(__mask) +#define weechat_string_regex_flags(__regex, __default_flags, __flags) \ + (weechat_plugin->string_regex_flags)(__regex, __default_flags, \ + __flags) +#define weechat_string_regcomp(__preg, __regex, __default_flags) \ + (weechat_plugin->string_regcomp)(__preg, __regex, __default_flags) +#define weechat_string_has_highlight(__string, __highlight_words) \ + (weechat_plugin->string_has_highlight)(__string, __highlight_words) +#define weechat_string_has_highlight_regex(__string, __regex) \ + (weechat_plugin->string_has_highlight_regex)(__string, __regex) +#define weechat_string_replace_regex(__string, __regex, __replace, \ + __reference_char, __callback, \ + __callback_data) \ + (weechat_plugin->string_replace_regex)(__string, __regex, \ + __replace, \ + __reference_char, \ + __callback, \ + __callback_data) +#define weechat_string_split(__string, __separator, __eol, __max, \ + __num_items) \ + (weechat_plugin->string_split)(__string, __separator, __eol, \ + __max, __num_items) +#define weechat_string_split_shell(__string, __num_items) \ + (weechat_plugin->string_split_shell)(__string, __num_items) +#define weechat_string_free_split(__split_string) \ + (weechat_plugin->string_free_split)(__split_string) +#define weechat_string_build_with_split_string(__split_string, \ + __separator) \ + (weechat_plugin->string_build_with_split_string)(__split_string, \ + __separator) +#define weechat_string_split_command(__command, __separator) \ + (weechat_plugin->string_split_command)(__command, __separator) +#define weechat_string_free_split_command(__split_command) \ + (weechat_plugin->string_free_split_command)(__split_command) +#define weechat_string_format_size(__size) \ + (weechat_plugin->string_format_size)(__size) +#define weechat_string_remove_color(__string, __replacement) \ + (weechat_plugin->string_remove_color)(__string, __replacement) +#define weechat_string_encode_base64(__from, __length, __to) \ + (weechat_plugin->string_encode_base64)(__from, __length, __to) +#define weechat_string_decode_base64(__from, __to) \ + (weechat_plugin->string_decode_base64)(__from, __to) +#define weechat_string_hex_dump(__data, __data_size, __bytes_per_line, \ + __prefix, __suffix) \ + (weechat_plugin->string_hex_dump)(__data, __data_size, \ + __bytes_per_line, __prefix, \ + __suffix) +#define weechat_string_is_command_char(__string) \ + (weechat_plugin->string_is_command_char)(__string) +#define weechat_string_input_for_buffer(__string) \ + (weechat_plugin->string_input_for_buffer)(__string) +#define weechat_string_eval_expression(__expr, __pointers, \ + __extra_vars, __options) \ + (weechat_plugin->string_eval_expression)(__expr, __pointers, \ + __extra_vars, __options) +#define weechat_string_dyn_alloc(__size_alloc) \ + (weechat_plugin->string_dyn_alloc)(__size_alloc) +#define weechat_string_dyn_copy(__string, __new_string) \ + (weechat_plugin->string_dyn_copy)(__string, __new_string) +#define weechat_string_dyn_concat(__string, __add) \ + (weechat_plugin->string_dyn_concat)(__string, __add) +#define weechat_string_dyn_free(__string, __free_string) \ + (weechat_plugin->string_dyn_free)(__string, __free_string) + +/* UTF-8 strings */ +#define weechat_utf8_has_8bits(__string) \ + (weechat_plugin->utf8_has_8bits)(__string) +#define weechat_utf8_is_valid(__string, __length, __error) \ + (weechat_plugin->utf8_is_valid)(__string, __length, __error) +#define weechat_utf8_normalize(__string, __char) \ + (weechat_plugin->utf8_normalize)(__string, __char) +#define weechat_utf8_prev_char(__start, __string) \ + (weechat_plugin->utf8_prev_char)(__start, __string) +#define weechat_utf8_next_char(__string) \ + (weechat_plugin->utf8_next_char)(__string) +#define weechat_utf8_char_int(__string) \ + (weechat_plugin->utf8_char_int)(__string) +#define weechat_utf8_char_size(__string) \ + (weechat_plugin->utf8_char_size)(__string) +#define weechat_utf8_strlen(__string) \ + (weechat_plugin->utf8_strlen)(__string) +#define weechat_utf8_strnlen(__string, __bytes) \ + (weechat_plugin->utf8_strnlen)(__string, __bytes) +#define weechat_utf8_strlen_screen(__string) \ + (weechat_plugin->utf8_strlen_screen)(__string) +#define weechat_utf8_charcmp(__string1, __string2) \ + (weechat_plugin->utf8_charcmp)(__string1, __string2) +#define weechat_utf8_charcasecmp(__string1, __string2) \ + (weechat_plugin->utf8_charcasecmp)(__string1, __string2) +#define weechat_utf8_char_size_screen(__string) \ + (weechat_plugin->utf8_char_size_screen)(__string) +#define weechat_utf8_add_offset(__string, __offset) \ + (weechat_plugin->utf8_add_offset)(__string, __offset) +#define weechat_utf8_real_pos(__string, __pos) \ + (weechat_plugin->utf8_real_pos)(__string, __pos) +#define weechat_utf8_pos(__string, __real_pos) \ + (weechat_plugin->utf8_pos)(__string, __real_pos) +#define weechat_utf8_strndup(__string, __length) \ + (weechat_plugin->utf8_strndup)(__string, __length) + +/* directories */ +#define weechat_mkdir_home(__directory, __mode) \ + (weechat_plugin->mkdir_home)(__directory, __mode) +#define weechat_mkdir(__directory, __mode) \ + (weechat_plugin->mkdir)(__directory, __mode) +#define weechat_mkdir_parents(__directory, __mode) \ + (weechat_plugin->mkdir_parents)(__directory, __mode) +#define weechat_exec_on_files(__directory, __recurse_subdirs, \ + __hidden_files, __callback, \ + __callback_data) \ + (weechat_plugin->exec_on_files)(__directory, __recurse_subdirs, \ + __hidden_files, \ + __callback, __callback_data) +#define weechat_file_get_content(__filename) \ + (weechat_plugin->file_get_content)(__filename) + +/* util */ +#define weechat_util_timeval_cmp(__time1, __time2) \ + (weechat_plugin->util_timeval_cmp)(__time1, __time2) +#define weechat_util_timeval_diff(__time1, __time2) \ + (weechat_plugin->util_timeval_diff)(__time1, __time2) +#define weechat_util_timeval_add(__time, __interval) \ + (weechat_plugin->util_timeval_add)(__time, __interval) +#define weechat_util_get_time_string(__date) \ + (weechat_plugin->util_get_time_string)(__date) +#define weechat_util_version_number(__version) \ + (weechat_plugin->util_version_number)(__version) + +/* sorted list */ +#define weechat_list_new() \ + (weechat_plugin->list_new)() +#define weechat_list_add(__list, __string, __where, __user_data) \ + (weechat_plugin->list_add)(__list, __string, __where, __user_data) +#define weechat_list_search(__list, __string) \ + (weechat_plugin->list_search)(__list, __string) +#define weechat_list_search_pos(__list, __string) \ + (weechat_plugin->list_search_pos)(__list, __string) +#define weechat_list_casesearch(__list, __string) \ + (weechat_plugin->list_casesearch)(__list, __string) +#define weechat_list_casesearch_pos(__list, __string) \ + (weechat_plugin->list_casesearch_pos)(__list, __string) +#define weechat_list_get(__list, __index) \ + (weechat_plugin->list_get)(__list, __index) +#define weechat_list_set(__item, __value) \ + (weechat_plugin->list_set)(__item, __value) +#define weechat_list_next(__item) \ + (weechat_plugin->list_next)(__item) +#define weechat_list_prev(__item) \ + (weechat_plugin->list_prev)(__item) +#define weechat_list_string(__item) \ + (weechat_plugin->list_string)(__item) +#define weechat_list_size(__list) \ + (weechat_plugin->list_size)(__list) +#define weechat_list_remove(__list, __item) \ + (weechat_plugin->list_remove)(__list, __item) +#define weechat_list_remove_all(__list) \ + (weechat_plugin->list_remove_all)(__list) +#define weechat_list_free(__list) \ + (weechat_plugin->list_free)(__list) + +/* array lists */ +#define weechat_arraylist_new(__initial_size, __sorted, \ + __allow_duplicates, __callback_cmp, \ + __callback_cmp_data, __callback_free, \ + __callback_free_data) \ + (weechat_plugin->arraylist_new)(__initial_size, __sorted, \ + __allow_duplicates, __callback_cmp, \ + __callback_cmp_data, __callback_free, \ + __callback_free_data) +#define weechat_arraylist_size(__arraylist) \ + (weechat_plugin->arraylist_size)(__arraylist) +#define weechat_arraylist_get(__arraylist, __index) \ + (weechat_plugin->arraylist_get)(__arraylist, __index) +#define weechat_arraylist_search(__arraylist, __pointer, __index, \ + __index_insert) \ + (weechat_plugin->arraylist_search)(__arraylist, __pointer, __index, \ + __index_insert) +#define weechat_arraylist_insert(__arraylist, __index, __pointer) \ + (weechat_plugin->arraylist_insert)(__arraylist, __index, __pointer) +#define weechat_arraylist_add(__arraylist, __pointer) \ + (weechat_plugin->arraylist_add)(__arraylist, __pointer) +#define weechat_arraylist_remove(__arraylist, __index) \ + (weechat_plugin->arraylist_remove)(__arraylist, __index) +#define weechat_arraylist_clear(__arraylist) \ + (weechat_plugin->arraylist_clear)(__arraylist) +#define weechat_arraylist_free(__arraylist) \ + (weechat_plugin->arraylist_free)(__arraylist) + +/* hash tables */ +#define weechat_hashtable_new(__size, __type_keys, __type_values, \ + __callback_hash_key, __callback_keycmp) \ + (weechat_plugin->hashtable_new)(__size, __type_keys, __type_values, \ + __callback_hash_key, \ + __callback_keycmp) +#define weechat_hashtable_set_with_size(__hashtable, __key, __key_size, \ + __value, __value_size) \ + (weechat_plugin->hashtable_set_with_size)(__hashtable, __key, \ + __key_size, __value, \ + __value_size) +#define weechat_hashtable_set(__hashtable, __key, __value) \ + (weechat_plugin->hashtable_set)(__hashtable, __key, __value) +#define weechat_hashtable_get(__hashtable, __key) \ + (weechat_plugin->hashtable_get)(__hashtable, __key) +#define weechat_hashtable_has_key(__hashtable, __key) \ + (weechat_plugin->hashtable_has_key)(__hashtable, __key) +#define weechat_hashtable_map(__hashtable, __cb_map, __cb_map_data) \ + (weechat_plugin->hashtable_map)(__hashtable, __cb_map, \ + __cb_map_data) +#define weechat_hashtable_map_string(__hashtable, __cb_map, \ + __cb_map_data) \ + (weechat_plugin->hashtable_map_string)(__hashtable, __cb_map, \ + __cb_map_data) +#define weechat_hashtable_dup(__hashtable) \ + (weechat_plugin->hashtable_dup)(__hashtable) +#define weechat_hashtable_get_integer(__hashtable, __property) \ + (weechat_plugin->hashtable_get_integer)(__hashtable, __property) +#define weechat_hashtable_get_string(__hashtable, __property) \ + (weechat_plugin->hashtable_get_string)(__hashtable, __property) +#define weechat_hashtable_set_pointer(__hashtable, __property, \ + __pointer) \ + (weechat_plugin->hashtable_set_pointer)(__hashtable, __property, \ + __pointer) +#define weechat_hashtable_add_to_infolist(__hashtable, __infolist_item, \ + __prefix) \ + (weechat_plugin->hashtable_add_to_infolist)(__hashtable, \ + __infolist_item, \ + __prefix) +#define weechat_hashtable_remove(__hashtable, __key) \ + (weechat_plugin->hashtable_remove)(__hashtable, __key) +#define weechat_hashtable_remove_all(__hashtable) \ + (weechat_plugin->hashtable_remove_all)(__hashtable) +#define weechat_hashtable_free(__hashtable) \ + (weechat_plugin->hashtable_free)(__hashtable) + +/* config files */ +#define weechat_config_new(__name, __callback_reload, \ + __callback_reload_pointer, \ + __callback_reload_data) \ + (weechat_plugin->config_new)(weechat_plugin, __name, \ + __callback_reload, \ + __callback_reload_pointer, \ + __callback_reload_data) +#define weechat_config_new_section(__config, __name, \ + __user_can_add_options, \ + __user_can_delete_options, \ + __cb_read, \ + __cb_read_pointer, \ + __cb_read_data, \ + __cb_write_std, \ + __cb_write_std_pointer, \ + __cb_write_std_data, \ + __cb_write_def, \ + __cb_write_def_pointer, \ + __cb_write_def_data, \ + __cb_create_option, \ + __cb_create_option_pointer, \ + __cb_create_option_data, \ + __cb_delete_option, \ + __cb_delete_option_pointer, \ + __cb_delete_option_data) \ + (weechat_plugin->config_new_section)(__config, __name, \ + __user_can_add_options, \ + __user_can_delete_options, \ + __cb_read, \ + __cb_read_pointer, \ + __cb_read_data, \ + __cb_write_std, \ + __cb_write_std_pointer, \ + __cb_write_std_data, \ + __cb_write_def, \ + __cb_write_def_pointer, \ + __cb_write_def_data, \ + __cb_create_option, \ + __cb_create_option_pointer, \ + __cb_create_option_data, \ + __cb_delete_option, \ + __cb_delete_option_pointer, \ + __cb_delete_option_data) +#define weechat_config_search_section(__config, __name) \ + (weechat_plugin->config_search_section)(__config, __name) +#define weechat_config_new_option(__config, __section, __name, __type, \ + __desc, __string_values, __min, \ + __max, __default, __value, \ + __null_value_allowed, \ + __callback_check, \ + __callback_check_pointer, \ + __callback_check_data, \ + __callback_change, \ + __callback_change_pointer, \ + __callback_change_data, \ + __callback_delete, \ + __callback_delete_pointer, \ + __callback_delete_data) \ + (weechat_plugin->config_new_option)(__config, __section, __name, \ + __type, __desc, \ + __string_values, \ + __min, __max, __default, \ + __value, \ + __null_value_allowed, \ + __callback_check, \ + __callback_check_pointer, \ + __callback_check_data, \ + __callback_change, \ + __callback_change_pointer, \ + __callback_change_data, \ + __callback_delete, \ + __callback_delete_pointer, \ + __callback_delete_data) +#define weechat_config_search_option(__config, __section, __name) \ + (weechat_plugin->config_search_option)(__config, __section, __name) +#define weechat_config_search_section_option(__config, __section, \ + __name, __section_found, \ + __option_found) \ + (weechat_plugin->config_search_section_option)(__config, __section, \ + __name, \ + __section_found, \ + __option_found); +#define weechat_config_search_with_string(__name, __config, __section, \ + __option, __pos_option) \ + (weechat_plugin->config_search_with_string)(__name, __config, \ + __section, __option, \ + __pos_option); +#define weechat_config_string_to_boolean(__string) \ + (weechat_plugin->config_string_to_boolean)(__string) +#define weechat_config_option_reset(__option, __run_callback) \ + (weechat_plugin->config_option_reset)(__option, __run_callback) +#define weechat_config_option_set(__option, __value, __run_callback) \ + (weechat_plugin->config_option_set)(__option, __value, \ + __run_callback) +#define weechat_config_option_set_null(__option, __run_callback) \ + (weechat_plugin->config_option_set_null)(__option, __run_callback) +#define weechat_config_option_unset(__option) \ + (weechat_plugin->config_option_unset)(__option) +#define weechat_config_option_rename(__option, __new_name) \ + (weechat_plugin->config_option_rename)(__option, __new_name) +#define weechat_config_option_get_string(__option, __property) \ + (weechat_plugin->config_option_get_string)(__option, __property) +#define weechat_config_option_get_pointer(__option, __property) \ + (weechat_plugin->config_option_get_pointer)(__option, __property) +#define weechat_config_option_is_null(__option) \ + (weechat_plugin->config_option_is_null)(__option) +#define weechat_config_option_default_is_null(__option) \ + (weechat_plugin->config_option_default_is_null)(__option) +#define weechat_config_boolean(__option) \ + (weechat_plugin->config_boolean)(__option) +#define weechat_config_boolean_default(__option) \ + (weechat_plugin->config_boolean_default)(__option) +#define weechat_config_integer(__option) \ + (weechat_plugin->config_integer)(__option) +#define weechat_config_integer_default(__option) \ + (weechat_plugin->config_integer_default)(__option) +#define weechat_config_string(__option) \ + (weechat_plugin->config_string)(__option) +#define weechat_config_string_default(__option) \ + (weechat_plugin->config_string_default)(__option) +#define weechat_config_color(__option) \ + (weechat_plugin->config_color)(__option) +#define weechat_config_color_default(__option) \ + (weechat_plugin->config_color_default)(__option) +#define weechat_config_write_option(__config, __option) \ + (weechat_plugin->config_write_option)(__config, __option) +#define weechat_config_write_line(__config, __option, __value...) \ + (weechat_plugin->config_write_line)(__config, __option, ##__value) +#define weechat_config_write(__config) \ + (weechat_plugin->config_write)(__config) +#define weechat_config_read(__config) \ + (weechat_plugin->config_read)(__config) +#define weechat_config_reload(__config) \ + (weechat_plugin->config_reload)(__config) +#define weechat_config_option_free(__option) \ + (weechat_plugin->config_option_free)(__option) +#define weechat_config_section_free_options(__section) \ + (weechat_plugin->config_section_free_options)(__section) +#define weechat_config_section_free(__section) \ + (weechat_plugin->config_section_free)(__section) +#define weechat_config_free(__config) \ + (weechat_plugin->config_free)(__config) +#define weechat_config_get(__option) \ + (weechat_plugin->config_get)(__option) +#define weechat_config_get_plugin(__option) \ + (weechat_plugin->config_get_plugin)(weechat_plugin, __option) +#define weechat_config_is_set_plugin(__option) \ + (weechat_plugin->config_is_set_plugin)(weechat_plugin, __option) +#define weechat_config_set_plugin(__option, __value) \ + (weechat_plugin->config_set_plugin)(weechat_plugin, __option, \ + __value) +#define weechat_config_set_desc_plugin(__option, __description) \ + (weechat_plugin->config_set_desc_plugin)(weechat_plugin, __option, \ + __description) +#define weechat_config_unset_plugin(__option) \ + (weechat_plugin->config_unset_plugin)(weechat_plugin, __option) + +/* key bindings */ +#define weechat_key_bind(__context, __keys) \ + (weechat_plugin->key_bind)(__context, __keys) +#define weechat_key_unbind(__context, __key) \ + (weechat_plugin->key_unbind)(__context, __key) + +/* display */ +#define weechat_prefix(__prefix) \ + (weechat_plugin->prefix)(__prefix) +#define weechat_color(__color_name) \ + (weechat_plugin->color)(__color_name) +#define weechat_printf(__buffer, __message, __argz...) \ + (weechat_plugin->printf_date_tags)(__buffer, 0, NULL, __message, \ + ##__argz) +#define weechat_printf_date_tags(__buffer, __date, __tags, __message, \ + __argz...) \ + (weechat_plugin->printf_date_tags)(__buffer, __date, __tags, \ + __message, ##__argz) +#define weechat_printf_y(__buffer, __y, __message, __argz...) \ + (weechat_plugin->printf_y)(__buffer, __y, __message, ##__argz) +#define weechat_log_printf(__message, __argz...) \ + (weechat_plugin->log_printf)(__message, ##__argz) + +/* hooks */ +#define weechat_hook_command(__command, __description, __args, \ + __args_desc, __completion, __callback, \ + __pointer, __data) \ + (weechat_plugin->hook_command)(weechat_plugin, __command, \ + __description, __args, __args_desc, \ + __completion, __callback, __pointer, \ + __data) +#define weechat_hook_command_run(__command, __callback, __pointer, \ + __data) \ + (weechat_plugin->hook_command_run)(weechat_plugin, __command, \ + __callback, __pointer, __data) +#define weechat_hook_timer(__interval, __align_second, __max_calls, \ + __callback, __pointer, __data) \ + (weechat_plugin->hook_timer)(weechat_plugin, __interval, \ + __align_second, __max_calls, \ + __callback, __pointer, __data) +#define weechat_hook_fd(__fd, __flag_read, __flag_write, \ + __flag_exception, __callback, __pointer, \ + __data) \ + (weechat_plugin->hook_fd)(weechat_plugin, __fd, __flag_read, \ + __flag_write, __flag_exception, \ + __callback, __pointer, __data) +#define weechat_hook_process(__command, __timeout, __callback, \ + __callback_pointer, __callback_data) \ + (weechat_plugin->hook_process)(weechat_plugin, __command, \ + __timeout, __callback, \ + __callback_pointer, __callback_data) +#define weechat_hook_process_hashtable(__command, __options, __timeout, \ + __callback, __callback_pointer, \ + __callback_data) \ + (weechat_plugin->hook_process_hashtable)(weechat_plugin, __command, \ + __options, __timeout, \ + __callback, \ + __callback_pointer, \ + __callback_data) +#define weechat_hook_connect(__proxy, __address, __port, __ipv6, \ + __retry, __gnutls_sess, __gnutls_cb, \ + __gnutls_dhkey_size, __gnutls_priorities, \ + __local_hostname, __callback, __pointer, \ + __data) \ + (weechat_plugin->hook_connect)(weechat_plugin, __proxy, __address, \ + __port, __ipv6, __retry, \ + __gnutls_sess, __gnutls_cb, \ + __gnutls_dhkey_size, \ + __gnutls_priorities, \ + __local_hostname, \ + __callback, __pointer, __data) +#define weechat_hook_print(__buffer, __tags, __msg, __strip__colors, \ + __callback, __pointer, __data) \ + (weechat_plugin->hook_print)(weechat_plugin, __buffer, __tags, \ + __msg, __strip__colors, __callback, \ + __pointer, __data) +#define weechat_hook_signal(__signal, __callback, __pointer, __data) \ + (weechat_plugin->hook_signal)(weechat_plugin, __signal, __callback, \ + __pointer, __data) +#define weechat_hook_signal_send(__signal, __type_data, __signal_data) \ + (weechat_plugin->hook_signal_send)(__signal, __type_data, \ + __signal_data) +#define weechat_hook_hsignal(__signal, __callback, __pointer, __data) \ + (weechat_plugin->hook_hsignal)(weechat_plugin, __signal, \ + __callback, __pointer, __data) +#define weechat_hook_hsignal_send(__signal, __hashtable) \ + (weechat_plugin->hook_hsignal_send)(__signal, __hashtable) +#define weechat_hook_config(__option, __callback, __pointer, __data) \ + (weechat_plugin->hook_config)(weechat_plugin, __option, __callback, \ + __pointer, __data) +#define weechat_hook_completion(__completion, __description, \ + __callback, __pointer, __data) \ + (weechat_plugin->hook_completion)(weechat_plugin, __completion, \ + __description, __callback, \ + __pointer, __data) +#define weechat_hook_completion_get_string(__completion, __property) \ + (weechat_plugin->hook_completion_get_string)(__completion, \ + __property) +#define weechat_hook_completion_list_add(__completion, __word, \ + __nick_completion, __where) \ + (weechat_plugin->hook_completion_list_add)(__completion, __word, \ + __nick_completion, \ + __where) +#define weechat_hook_modifier(__modifier, __callback, __pointer, \ + __data) \ + (weechat_plugin->hook_modifier)(weechat_plugin, __modifier, \ + __callback, __pointer, __data) +#define weechat_hook_modifier_exec(__modifier, __modifier_data, \ + __string) \ + (weechat_plugin->hook_modifier_exec)(weechat_plugin, __modifier, \ + __modifier_data, __string) +#define weechat_hook_info(__info_name, __description, \ + __args_description, __callback, __pointer, \ + __data) \ + (weechat_plugin->hook_info)(weechat_plugin, __info_name, \ + __description, __args_description, \ + __callback, __pointer, __data) +#define weechat_hook_info_hashtable(__info_name, __description, \ + __args_description, \ + __output_description, \ + __callback, \ + __pointer, \ + __data) \ + (weechat_plugin->hook_info_hashtable)(weechat_plugin, __info_name, \ + __description, \ + __args_description, \ + __output_description, \ + __callback, __pointer, \ + __data) +#define weechat_hook_infolist(__infolist_name, __description, \ + __pointer_description, \ + __args_description, __callback, \ + __pointer, __data) \ + (weechat_plugin->hook_infolist)(weechat_plugin, __infolist_name, \ + __description, \ + __pointer_description, \ + __args_description, __callback, \ + __pointer, __data) +#define weechat_hook_hdata(__hdata_name, __description, __callback, \ + __pointer, __data) \ + (weechat_plugin->hook_hdata)(weechat_plugin, __hdata_name, \ + __description, __callback, __pointer, \ + __data) +#define weechat_hook_focus(__area, __callback, __pointer, __data) \ + (weechat_plugin->hook_focus)(weechat_plugin, __area, __callback, \ + __pointer, __data) +#define weechat_hook_set(__hook, __property, __value) \ + (weechat_plugin->hook_set)(__hook, __property, __value) +#define weechat_unhook(__hook) \ + (weechat_plugin->unhook)( __hook) +#define weechat_unhook_all(__subplugin) \ + (weechat_plugin->unhook_all)(weechat_plugin, __subplugin) + +/* buffers */ +#define weechat_buffer_new(__name, __input_callback, \ + __input_callback_pointer, \ + __input_callback_data, \ + __close_callback, \ + __close_callback_pointer, \ + __close_callback_data) \ + (weechat_plugin->buffer_new)(weechat_plugin, __name, \ + __input_callback, \ + __input_callback_pointer, \ + __input_callback_data, \ + __close_callback, \ + __close_callback_pointer, \ + __close_callback_data) +#define weechat_buffer_search(__plugin, __name) \ + (weechat_plugin->buffer_search)(__plugin, __name) +#define weechat_buffer_search_main() \ + (weechat_plugin->buffer_search_main)() +#define weechat_current_buffer() \ + (weechat_plugin->buffer_search)(NULL, NULL) +#define weechat_buffer_clear(__buffer) \ + (weechat_plugin->buffer_clear)(__buffer) +#define weechat_buffer_close(__buffer) \ + (weechat_plugin->buffer_close)(__buffer) +#define weechat_buffer_merge(__buffer, __target_buffer) \ + (weechat_plugin->buffer_merge)(__buffer, __target_buffer) +#define weechat_buffer_unmerge(__buffer, __number) \ + (weechat_plugin->buffer_unmerge)(__buffer, __number) +#define weechat_buffer_get_integer(__buffer, __property) \ + (weechat_plugin->buffer_get_integer)(__buffer, __property) +#define weechat_buffer_get_string(__buffer, __property) \ + (weechat_plugin->buffer_get_string)(__buffer, __property) +#define weechat_buffer_get_pointer(__buffer, __property) \ + (weechat_plugin->buffer_get_pointer)(__buffer, __property) +#define weechat_buffer_set(__buffer, __property, __value) \ + (weechat_plugin->buffer_set)(__buffer, __property, __value) +#define weechat_buffer_set_pointer(__buffer, __property, __pointer) \ + (weechat_plugin->buffer_set_pointer)(__buffer, __property, \ + __pointer) +#define weechat_buffer_string_replace_local_var(__buffer, __string) \ + (weechat_plugin->buffer_string_replace_local_var)(__buffer, \ + __string) +#define weechat_buffer_match_list(__buffer, __string) \ + (weechat_plugin->buffer_match_list)(__buffer, __string) + +/* windows */ +#define weechat_window_search_with_buffer(__buffer) \ + (weechat_plugin->window_search_with_buffer)(__buffer) +#define weechat_window_get_integer(__window, __property) \ + (weechat_plugin->window_get_integer)(__window, __property) +#define weechat_window_get_string(__window, __property) \ + (weechat_plugin->window_get_string)(__window, __property) +#define weechat_window_get_pointer(__window, __property) \ + (weechat_plugin->window_get_pointer)(__window, __property) +#define weechat_current_window() \ + (weechat_plugin->window_get_pointer)(NULL, "current") +#define weechat_window_set_title(__title) \ + (weechat_plugin->window_set_title)(__title) + +/* nicklist */ +#define weechat_nicklist_add_group(__buffer, __parent_group, __name, \ + __color, __visible) \ + (weechat_plugin->nicklist_add_group)(__buffer, __parent_group, \ + __name, __color, __visible) +#define weechat_nicklist_search_group(__buffer, __from_group, __name) \ + (weechat_plugin->nicklist_search_group)(__buffer, __from_group, \ + __name) +#define weechat_nicklist_add_nick(__buffer, __group, __name, __color, \ + __prefix, __prefix_color, __visible) \ + (weechat_plugin->nicklist_add_nick)(__buffer, __group, __name, \ + __color, __prefix, \ + __prefix_color, __visible) +#define weechat_nicklist_search_nick(__buffer, __from_group, __name) \ + (weechat_plugin->nicklist_search_nick)(__buffer, __from_group, \ + __name) +#define weechat_nicklist_remove_group(__buffer, __group) \ + (weechat_plugin->nicklist_remove_group)(__buffer, __group) +#define weechat_nicklist_remove_nick(__buffer, __nick) \ + (weechat_plugin->nicklist_remove_nick)(__buffer, __nick) +#define weechat_nicklist_remove_all(__buffer) \ + (weechat_plugin->nicklist_remove_all)(__buffer) +#define weechat_nicklist_get_next_item(__buffer, __group, __nick) \ + (weechat_plugin->nicklist_get_next_item)(__buffer, __group, __nick) +#define weechat_nicklist_group_get_integer(__buffer, __group, \ + __property) \ + (weechat_plugin->nicklist_group_get_integer)(__buffer, __group, \ + __property) +#define weechat_nicklist_group_get_string(__buffer, __group, \ + __property) \ + (weechat_plugin->nicklist_group_get_string)(__buffer, __group, \ + __property) +#define weechat_nicklist_group_get_pointer(__buffer, __group, \ + __property) \ + (weechat_plugin->nicklist_group_get_pointer)(__buffer, __group, \ + __property) +#define weechat_nicklist_group_set(__buffer, __group, __property, \ + __value) \ + (weechat_plugin->nicklist_group_set)(__buffer, __group, __property, \ + __value) +#define weechat_nicklist_nick_get_integer(__buffer, __nick, __property) \ + (weechat_plugin->nicklist_nick_get_integer)(__buffer, __nick, \ + __property) +#define weechat_nicklist_nick_get_string(__buffer, __nick, __property) \ + (weechat_plugin->nicklist_nick_get_string)(__buffer, __nick, \ + __property) +#define weechat_nicklist_nick_get_pointer(__buffer, __nick, __property) \ + (weechat_plugin->nicklist_nick_get_pointer)(__buffer, __nick, \ + __property) +#define weechat_nicklist_nick_set(__buffer, __nick, __property, \ + __value) \ + (weechat_plugin->nicklist_nick_set)(__buffer, __nick, __property, \ + __value) + +/* bars */ +#define weechat_bar_item_search(__name) \ + (weechat_plugin->bar_item_search)(__name) +#define weechat_bar_item_new(__name, __build_callback, \ + __build_callback_pointer, \ + __build_callback_data) \ + (weechat_plugin->bar_item_new)(weechat_plugin, __name, \ + __build_callback, \ + __build_callback_pointer, \ + __build_callback_data) +#define weechat_bar_item_update(__name) \ + (weechat_plugin->bar_item_update)(__name) +#define weechat_bar_item_remove(__item) \ + (weechat_plugin->bar_item_remove)(__item) +#define weechat_bar_search(__name) \ + (weechat_plugin->bar_search)(__name) +#define weechat_bar_new(__name, __hidden, __priority, __type, \ + __condition, __position, __filling_top_bottom, \ + __filling_left_right, __size, __size_max, \ + __color_fg, __color_delim, __color_bg, \ + __separator, __items) \ + (weechat_plugin->bar_new)(__name, __hidden, __priority, __type, \ + __condition, __position, \ + __filling_top_bottom, \ + __filling_left_right, \ + __size, __size_max, __color_fg, \ + __color_delim, __color_bg, __separator, \ + __items) +#define weechat_bar_set(__bar, __property, __value) \ + (weechat_plugin->bar_set)(__bar, __property, __value) +#define weechat_bar_update(__name) \ + (weechat_plugin->bar_update)(__name) +#define weechat_bar_remove(__bar) \ + (weechat_plugin->bar_remove)(__bar) + +/* command */ +#define weechat_command(__buffer, __command) \ + (weechat_plugin->command)(weechat_plugin, __buffer, __command) + +/* network */ +#define weechat_network_pass_proxy(__proxy, __sock, __address, __port) \ + (weechat_plugin->network_pass_proxy)(__proxy, __sock, __address, \ + __port) +#define weechat_network_connect_to(__proxy, __address, \ + __address_length) \ + (weechat_plugin->network_connect_to)(__proxy, __address, \ + __address_length) + +/* infos */ +#define weechat_info_get(__info_name, __arguments) \ + (weechat_plugin->info_get)(weechat_plugin, __info_name, \ + __arguments) +#define weechat_info_get_hashtable(__info_name, __hashtable) \ + (weechat_plugin->info_get_hashtable)(weechat_plugin, __info_name, \ + __hashtable) + +/* infolists */ +#define weechat_infolist_new() \ + (weechat_plugin->infolist_new)(weechat_plugin) +#define weechat_infolist_new_item(__list) \ + (weechat_plugin->infolist_new_item)(__list) +#define weechat_infolist_new_var_integer(__item, __name, __value) \ + (weechat_plugin->infolist_new_var_integer)(__item, __name, __value) +#define weechat_infolist_new_var_string(__item, __name, __value) \ + (weechat_plugin->infolist_new_var_string)(__item, __name, __value) +#define weechat_infolist_new_var_pointer(__item, __name, __pointer) \ + (weechat_plugin->infolist_new_var_pointer)(__item, __name, \ + __pointer) +#define weechat_infolist_new_var_buffer(__item, __name, __buffer, \ + __size) \ + (weechat_plugin->infolist_new_var_buffer)(__item, __name, __buffer, \ + __size) +#define weechat_infolist_new_var_time(__item, __name, __time) \ + (weechat_plugin->infolist_new_var_time)(__item, __name, __time) +#define weechat_infolist_search_var(__list, __name) \ + (weechat_plugin->infolist_search_var)(__list, __name) +#define weechat_infolist_get(__infolist_name, __pointer, __arguments) \ + (weechat_plugin->infolist_get)(weechat_plugin, __infolist_name, \ + __pointer, __arguments) +#define weechat_infolist_next(__list) \ + (weechat_plugin->infolist_next)(__list) +#define weechat_infolist_prev(__list) \ + (weechat_plugin->infolist_prev)(__list) +#define weechat_infolist_reset_item_cursor(__list) \ + (weechat_plugin->infolist_reset_item_cursor)(__list) +#define weechat_infolist_fields(__list) \ + (weechat_plugin->infolist_fields)(__list) +#define weechat_infolist_integer(__item, __var) \ + (weechat_plugin->infolist_integer)(__item, __var) +#define weechat_infolist_string(__item, __var) \ + (weechat_plugin->infolist_string)(__item, __var) +#define weechat_infolist_pointer(__item, __var) \ + (weechat_plugin->infolist_pointer)(__item, __var) +#define weechat_infolist_buffer(__item, __var, __size) \ + (weechat_plugin->infolist_buffer)(__item, __var, __size) +#define weechat_infolist_time(__item, __var) \ + (weechat_plugin->infolist_time)(__item, __var) +#define weechat_infolist_free(__list) \ + (weechat_plugin->infolist_free)(__list) + +/* hdata */ +#define weechat_hdata_new(__hdata_name, __var_prev, __var_next, \ + __create_allowed, __delete_allowed, \ + __callback_update, __callback_update_data) \ + (weechat_plugin->hdata_new)(weechat_plugin, __hdata_name, \ + __var_prev, __var_next, \ + __create_allowed, __delete_allowed, \ + __callback_update, \ + __callback_update_data) +#define weechat_hdata_new_var(__hdata, __name, __offset, __type, \ + __update_allowed, __array_size, \ + __hdata_name) \ + (weechat_plugin->hdata_new_var)(__hdata, __name, __offset, __type, \ + __update_allowed, __array_size, \ + __hdata_name) +#define WEECHAT_HDATA_VAR(__struct, __name, __type, __update_allowed, \ + __array_size, __hdata_name) \ + weechat_hdata_new_var (hdata, #__name, offsetof (__struct, __name), \ + WEECHAT_HDATA_##__type, __update_allowed, \ + __array_size, __hdata_name) +#define weechat_hdata_new_list(__hdata, __name, __pointer, __flags) \ + (weechat_plugin->hdata_new_list)(__hdata, __name, __pointer, \ + __flags) +#define WEECHAT_HDATA_LIST(__name, __flags) \ + weechat_hdata_new_list (hdata, #__name, &(__name), __flags); +#define weechat_hdata_get(__hdata_name) \ + (weechat_plugin->hdata_get)(weechat_plugin, __hdata_name) +#define weechat_hdata_get_var_offset(__hdata, __name) \ + (weechat_plugin->hdata_get_var_offset)(__hdata, __name) +#define weechat_hdata_get_var_type(__hdata, __name) \ + (weechat_plugin->hdata_get_var_type)(__hdata, __name) +#define weechat_hdata_get_var_type_string(__hdata, __name) \ + (weechat_plugin->hdata_get_var_type_string)(__hdata, __name) +#define weechat_hdata_get_var_array_size(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_get_var_array_size)(__hdata, __pointer, \ + __name) +#define weechat_hdata_get_var_array_size_string(__hdata, __pointer, \ + __name) \ + (weechat_plugin->hdata_get_var_array_size_string)(__hdata, \ + __pointer, \ + __name) +#define weechat_hdata_get_var_hdata(__hdata, __name) \ + (weechat_plugin->hdata_get_var_hdata)(__hdata, __name) +#define weechat_hdata_get_var(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_get_var)(__hdata, __pointer, __name) +#define weechat_hdata_get_var_at_offset(__hdata, __pointer, __offset) \ + (weechat_plugin->hdata_get_var_at_offset)(__hdata, __pointer, \ + __offset) +#define weechat_hdata_get_list(__hdata, __name) \ + (weechat_plugin->hdata_get_list)(__hdata, __name) +#define weechat_hdata_check_pointer(__hdata, __list, __pointer) \ + (weechat_plugin->hdata_check_pointer)(__hdata, __list, __pointer) +#define weechat_hdata_move(__hdata, __pointer, __count) \ + (weechat_plugin->hdata_move)(__hdata, __pointer, __count) +#define weechat_hdata_search(__hdata, __pointer, __search, __move) \ + (weechat_plugin->hdata_search)(__hdata, __pointer, __search, \ + __move) +#define weechat_hdata_char(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_char)(__hdata, __pointer, __name) +#define weechat_hdata_integer(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_integer)(__hdata, __pointer, __name) +#define weechat_hdata_long(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_long)(__hdata, __pointer, __name) +#define weechat_hdata_string(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_string)(__hdata, __pointer, __name) +#define weechat_hdata_pointer(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_pointer)(__hdata, __pointer, __name) +#define weechat_hdata_time(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_time)(__hdata, __pointer, __name) +#define weechat_hdata_hashtable(__hdata, __pointer, __name) \ + (weechat_plugin->hdata_hashtable)(__hdata, __pointer, __name) +#define weechat_hdata_compare(__hdata, __pointer1, __pointer2, __name, \ + __case_sensitive) \ + (weechat_plugin->hdata_compare)(__hdata, __pointer1, __pointer2, \ + __name, __case_sensitive) +#define weechat_hdata_set(__hdata, __pointer, __name, __value) \ + (weechat_plugin->hdata_set)(__hdata, __pointer, __name, __value) +#define weechat_hdata_update(__hdata, __pointer, __hashtable) \ + (weechat_plugin->hdata_update)(__hdata, __pointer, __hashtable) +#define weechat_hdata_get_string(__hdata, __property) \ + (weechat_plugin->hdata_get_string)(__hdata, __property) + +/* upgrade */ +#define weechat_upgrade_new(__filename, __callback_read, \ + __callback_read_pointer, \ + __callback_read_data) \ + (weechat_plugin->upgrade_new)(__filename, __callback_read, \ + __callback_read_pointer, \ + __callback_read_data) +#define weechat_upgrade_write_object(__upgrade_file, __object_id, \ + __infolist) \ + (weechat_plugin->upgrade_write_object)(__upgrade_file, __object_id, \ + __infolist) +#define weechat_upgrade_read(__upgrade_file) \ + (weechat_plugin->upgrade_read)(__upgrade_file) +#define weechat_upgrade_close(__upgrade_file) \ + (weechat_plugin->upgrade_close)(__upgrade_file) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* WEECHAT_WEECHAT_PLUGIN_H */ From 47a8e86a34ff4e775e393cd8929ea1bcbb99ae23 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Tue, 1 May 2018 11:23:37 +0100 Subject: [PATCH 003/118] Server buffer creation --- Makefile | 10 +- libwebsockets | 2 +- slack-api.c | 158 +++++++++++ slack-api.h | 6 + slack-buffer.c | 73 +++++ slack-buffer.h | 7 + slack-command.c | 200 ++++++++++++-- slack-config.c | 34 ++- slack-input.c | 20 ++ slack-input.h | 8 + slack-oauth.c | 33 ++- slack-teaminfo.c | 342 +++++++++++++++++++++++ slack-teaminfo.h | 16 ++ slack-workspace.c | 671 +++++++++++++++++++++++++++++++++++++++++++++- slack-workspace.h | 34 ++- slack.c | 34 +++ 16 files changed, 1591 insertions(+), 57 deletions(-) create mode 100644 slack-api.c create mode 100644 slack-api.h create mode 100644 slack-buffer.c create mode 100644 slack-buffer.h create mode 100644 slack-input.c create mode 100644 slack-input.h create mode 100644 slack-teaminfo.c create mode 100644 slack-teaminfo.h diff --git a/Makefile b/Makefile index 0bde5c4..fda87ab 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,28 @@ CC=clang CXX=clang++ RM=rm -f -CFLAGS=-fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -I libwebsockets/include -I json-c +CFLAGS=-fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c LDFLAGS=-shared -g LDLIBS=-lssl SRCS=slack.c \ + slack-api.c \ + slack-buffer.c \ slack-config.c \ slack-command.c \ + slack-input.c \ slack-oauth.c \ + slack-teaminfo.c \ slack-workspace.c OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a -all: weechat-slack +all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack weechat-slack: $(OBJS) $(CC) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) libwebsockets/lib/libwebsockets.a: - cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF . + cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . $(MAKE) -C libwebsockets json-c/libjson-c.a: diff --git a/libwebsockets b/libwebsockets index 91a47f4..f1c56bc 160000 --- a/libwebsockets +++ b/libwebsockets @@ -1 +1 @@ -Subproject commit 91a47f4fab4d74f49a341ce22954a563f6544446 +Subproject commit f1c56bc233a5f05c01c93a5c250a31b4d309ecac diff --git a/slack-api.c b/slack-api.c new file mode 100644 index 0000000..0cd3b78 --- /dev/null +++ b/slack-api.c @@ -0,0 +1,158 @@ +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-workspace.h" +#include "slack-api.h" + +static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, + void *user, void* in, size_t len) +{ + struct t_slack_workspace *workspace = (struct t_slack_workspace *)user; + + (void) wsi; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + in ? (char *)in : "(null)"); + workspace->client_wsi = NULL; + break; + + case LWS_CALLBACK_CLIENT_ESTABLISHED: + weechat_printf( + workspace->buffer, + _("%s%s: waiting for hello..."), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_CLIENT_RECEIVE: + weechat_printf( + workspace->buffer, + _("%s%s: received data: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + (const char *)in); + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (workspace->json_chunks) + { + for (last_chunk = workspace->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + workspace->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_CLIENT_WRITEABLE: + weechat_printf( + workspace->buffer, + _("%s%s: websocket is writeable"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + break; + + case LWS_CALLBACK_CLOSED: + workspace->client_wsi = NULL; + workspace->disconnected = 1; + /* start reconnect timer */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "default", + callback_ws, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +void slack_api_connect(struct t_slack_workspace *workspace) +{ + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + const char *url_protocol, *url_path; + char path[512]; + + memset(&ctxinfo, 0, sizeof(ctxinfo)); + memset(&ccinfo, 0, sizeof(ccinfo)); + + ccinfo.port = 443; + + if (lws_parse_uri(workspace->ws_url, + &url_protocol, &ccinfo.address, + &ccinfo.port, &url_path)) + { + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: bad websocket uri"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + + path[0] = '/'; + strncpy(path + 1, url_path, sizeof(path) - 2); + path[sizeof(path) - 1] = '\0'; + + ccinfo.path = path; + + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; + ctxinfo.protocols = protocols; + ctxinfo.uid = -1; + ctxinfo.gid = -1; + + workspace->context = lws_create_context(&ctxinfo); + if (!workspace->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: connecting to %s://%s:%d%s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + url_protocol, ccinfo.address, ccinfo.port, path); + } + + ccinfo.context = workspace->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.ietf_version_or_minus_one = -1; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &workspace->client_wsi; + ccinfo.userdata = workspace; + + lws_client_connect_via_info(&ccinfo); +} diff --git a/slack-api.h b/slack-api.h new file mode 100644 index 0000000..6a0281b --- /dev/null +++ b/slack-api.h @@ -0,0 +1,6 @@ +#ifndef _SLACK_API_H_ +#define _SLACK_API_H_ + +void slack_api_connect(struct t_slack_workspace *workspace); + +#endif /*SLACK_API_H*/ diff --git a/slack-buffer.c b/slack-buffer.c new file mode 100644 index 0000000..8fceb3d --- /dev/null +++ b/slack-buffer.c @@ -0,0 +1,73 @@ +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-buffer.h" +#include "slack-workspace.h" + +void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, + struct t_slack_workspace **workspace)//, + //struct t_slack_channel **channel) +{ + struct t_slack_workspace *ptr_workspace; + //struct t_slack_channel *ptr_channel; + + if (!buffer) + return; + + /* look for a workspace or channel using this buffer */ + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + if (ptr_workspace->buffer == buffer) + { + if (workspace) + *workspace = ptr_workspace; + return; + } + + /* + for (ptr_channel = ptr_workspace->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + if (ptr_channel->buffer == buffer) + { + if (workspace) + *workspace = ptr_workspace; + if (channel) + *channel = ptr_channel; + return; + } + } + */ + } + + /* no workspace or channel found */ +} + +int slack_buffer_close_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer) +{ + struct t_weechat_plugin *buffer_plugin = NULL; + struct t_slack_workspace *ptr_workspace = NULL; + + buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin"); + if (buffer_plugin == weechat_slack_plugin) + slack_buffer_get_workspace_and_channel(buffer, + &ptr_workspace);//, &ptr_channel); + + (void) pointer; + (void) data; + (void) buffer; + + if (ptr_workspace) + { + if (!ptr_workspace->disconnected) + { + //slack_command_quit_workspace(ptr_workspace, NULL); + slack_workspace_disconnect(ptr_workspace, 0, 0); + } + + ptr_workspace->buffer = NULL; + } + + return WEECHAT_RC_OK; +} diff --git a/slack-buffer.h b/slack-buffer.h new file mode 100644 index 0000000..8ba6a03 --- /dev/null +++ b/slack-buffer.h @@ -0,0 +1,7 @@ +#ifndef _SLACK_BUFFER_H_ +#define _SLACK_BUFFER_H_ + +int slack_buffer_close_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer); + +#endif /*SLACK_BUFFER_H*/ diff --git a/slack-command.c b/slack-command.c index 9c940da..0d7f4b8 100644 --- a/slack-command.c +++ b/slack-command.c @@ -5,6 +5,7 @@ #include "slack.h" #include "slack-command.h" #include "slack-oauth.h" +#include "slack-teaminfo.h" #include "slack-workspace.h" void slack_command_display_workspace(struct t_slack_workspace *workspace) @@ -17,10 +18,15 @@ void slack_command_display_workspace(struct t_slack_workspace *workspace) num_pv = 0;//slack_workspace_get_pv_count(workspace); weechat_printf( NULL, - " %s %s%s %s[%s%s%s]%s, %d %s, %d pv", + " %s %s%s%s.slack.com %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv", (workspace->is_connected) ? "*" : " ", - weechat_color("chat_workspace"), - workspace->name, + weechat_color("chat_server"), + workspace->domain, + weechat_color("reset"), + weechat_color("chat_delimiters"), + weechat_color("chat_server"), + (workspace->name) ? + workspace->name : "???", weechat_color("chat_delimiters"), weechat_color("reset"), (workspace->is_connected) ? @@ -35,9 +41,15 @@ void slack_command_display_workspace(struct t_slack_workspace *workspace) { weechat_printf( NULL, - " %s%s%s", - weechat_color("chat_workspace"), - workspace->name, + " %s%s%s.slack.com %s(%s%s%s)%s", + weechat_color("chat_server"), + workspace->domain, + weechat_color("reset"), + weechat_color("chat_delimiters"), + weechat_color("chat_server"), + (workspace->name) ? + workspace->name : "???", + weechat_color("chat_delimiters"), weechat_color("reset")); } } @@ -94,8 +106,56 @@ void slack_command_workspace_list(int argc, char **argv) } } -void slack_command_add_workspace(char *token) +void slack_command_add_workspace(struct t_slack_teaminfo *slack_teaminfo) { + struct t_slack_workspace *workspace; + + workspace = slack_workspace_casesearch(slack_teaminfo->domain); + if (workspace) + { + weechat_printf( + NULL, + _("%s%s: workspace \"%s\" already exists, can't add it!"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + slack_teaminfo->domain); + return; + } + + workspace = slack_workspace_alloc(slack_teaminfo->domain); + if (!workspace) + { + weechat_printf( + NULL, + _("%s%s: unable to add workspace"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + + workspace->id = strdup(slack_teaminfo->id); + workspace->name = strdup(slack_teaminfo->name); + weechat_config_option_set(workspace->options[SLACK_WORKSPACE_OPTION_TOKEN], + slack_teaminfo->token, 1); + + weechat_printf ( + NULL, + _("%s: workspace %s%s%s.slack.com %s(%s%s%s)%s added"), + SLACK_PLUGIN_NAME, + weechat_color("chat_server"), + workspace->domain, + weechat_color("reset"), + weechat_color("chat_delimiters"), + weechat_color("chat_server"), + workspace->name, + weechat_color("chat_delimiters"), + weechat_color("reset")); + + free_teaminfo(slack_teaminfo); +} + +void slack_command_fetch_workspace(char *token) +{ + slack_teaminfo_fetch(token, &slack_command_add_workspace); + free(token); } @@ -107,13 +167,13 @@ void slack_command_workspace_register(int argc, char **argv) { code = argv[2]; - if (weechat_strncasecmp("xoxp", code, 4) == 0) + if (strncmp("xoxp", code, 4) == 0) { - slack_command_add_workspace(strdup(code)); + slack_command_fetch_workspace(strdup(code)); } else { - slack_oauth_request_token(code, &slack_command_add_workspace); + slack_oauth_request_token(code, &slack_command_fetch_workspace); } } else @@ -121,7 +181,7 @@ void slack_command_workspace_register(int argc, char **argv) weechat_printf(NULL, _("\n#### Retrieving a Slack token via OAUTH ####\n" "1) Paste this into a browser: https://slack.com/oauth/authorize?client_id=%s&scope=client\n" - "2) Select the team you wish to access from wee-slack in your browser.\n" + "2) Select the team you wish to access from weechat in your browser.\n" "3) Click \"Authorize\" in the browser **IMPORTANT: the redirect will fail, this is expected**\n" "4) Copy the \"code\" portion of the URL to your clipboard\n" "5) Return to weechat and run `/slack register [code]`\n"), @@ -129,8 +189,109 @@ void slack_command_workspace_register(int argc, char **argv) } } +int slack_command_connect_workspace(struct t_slack_workspace *workspace) +{ + if (!workspace) + return 0; + + if (workspace->is_connected) + { + weechat_printf( + NULL, + _("%s%s: already connected to workspace \"%s\"!"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + workspace->domain); + } + + slack_workspace_connect(workspace); + + return 1; +} + +int slack_command_workspace_connect(int argc, char **argv) +{ + int i, nb_connect, connect_ok; + struct t_slack_workspace *ptr_workspace; + + (void) argc; + (void) argv; + + connect_ok = 1; + + nb_connect = 0; + for (i = 2; i < argc; i++) + { + nb_connect++; + ptr_workspace = slack_workspace_search(argv[i]); + if (ptr_workspace) + { + if (!slack_command_connect_workspace(ptr_workspace)) + { + connect_ok = 0; + } + } + else + { + weechat_printf( + NULL, + _("%s%s: workspace not found \"%s\" " + "(register first with: /slack register)"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + argv[i]); + } + } + + return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; +} + void slack_command_workspace_delete(int argc, char **argv) { + struct t_slack_workspace *workspace; + char *workspace_domain; + + if (argc < 3) + { + weechat_printf( + NULL, + _("%sToo few arguments for command\"%s %s\" " + "(help on command: /help %s)"), + weechat_prefix("error"), + argv[0], argv[1], argv[0] + 1); + return; + } + + workspace = slack_workspace_search(argv[2]); + if (!workspace) + { + weechat_printf( + NULL, + _("%s%s: workspace \"%s\" not found for \"%s\" command"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + argv[2], "slack delete"); + return; + } + if (workspace->is_connected) + { + weechat_printf( + NULL, + _("%s%s: you cannot delete workspace \"%s\" because you" + "are connected. Try \"/slack disconnect %s\" first."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + argv[2], argv[2]); + return; + } + + workspace_domain = strdup(workspace->domain); + slack_workspace_free(workspace); + weechat_printf ( + NULL, + _("%s: workspace %s%s%s has been deleted"), + SLACK_PLUGIN_NAME, + weechat_color("chat_server"), + (workspace_domain) ? workspace_domain : "???", + weechat_color("reset")); + if (workspace_domain) + free(workspace_domain); } int slack_command_slack(const void *pointer, void *data, @@ -142,17 +303,23 @@ int slack_command_slack(const void *pointer, void *data, (void) data; (void) buffer; + if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) + { + slack_command_workspace_list(argc, argv); + return WEECHAT_RC_OK; + } + if (argc > 1) { - if (weechat_strcasecmp(argv[1], "list") == 0) + if (weechat_strcasecmp(argv[1], "register") == 0) { - slack_command_workspace_list(argc, argv); + slack_command_workspace_register(argc, argv); return WEECHAT_RC_OK; } - if (weechat_strcasecmp(argv[1], "register") == 0) + if (weechat_strcasecmp(argv[1], "connect") == 0) { - slack_command_workspace_register(argc, argv); + slack_command_workspace_connect(argc, argv); return WEECHAT_RC_OK; } @@ -175,12 +342,15 @@ void slack_command_init() N_("slack control"), N_("list" " || register [token]" + " || connect " " || delete "), N_(" list: list workspaces\n" "register: add a slack workspace\n" + " connect: connect to a slack workspace\n" " delete: delete a slack workspace\n"), "list" " || register %(slack_token)" + " || connect %(slack_workspace)" " || delete %(slack_workspace)", &slack_command_slack, NULL, NULL); } diff --git a/slack-config.c b/slack-config.c index a6c59cb..f6a8f2c 100644 --- a/slack-config.c +++ b/slack-config.c @@ -17,17 +17,27 @@ int slack_config_workspace_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 slack_config_workspace_change_cb(const void *pointer, void *data, struct t_config_option *option) { + (void) pointer; + (void) data; + (void) option; } void slack_config_workspace_default_change_cb(const void *pointer, void *data, struct t_config_option *option) { + (void) pointer; + (void) data; + (void) option; } struct t_config_option * @@ -125,7 +135,7 @@ int slack_config_workspace_read_cb (const void *pointer, void *data, { struct t_slack_workspace *ptr_workspace; int index_option, rc, i; - char *pos_option, *workspace_name; + char *pos_option, *workspace_domain; /* make C compiler happy */ (void) pointer; @@ -140,17 +150,17 @@ int slack_config_workspace_read_cb (const void *pointer, void *data, pos_option = strrchr(option_name, '.'); if (pos_option) { - workspace_name = weechat_strndup(option_name, - pos_option - option_name); + workspace_domain = weechat_strndup(option_name, + pos_option - option_name); pos_option++; - if (workspace_name) + if (workspace_domain) { index_option = slack_workspace_search_option(pos_option); if (index_option >= 0) { - ptr_workspace = slack_workspace_search(workspace_name); + ptr_workspace = slack_workspace_search(workspace_domain); if (!ptr_workspace) - ptr_workspace = slack_workspace_alloc(workspace_name); + ptr_workspace = slack_workspace_alloc(workspace_domain); if (ptr_workspace) { if (ptr_workspace->reloading_from_config @@ -172,10 +182,10 @@ int slack_config_workspace_read_cb (const void *pointer, void *data, NULL, _("%s%s: error adding workspace \"%s\""), weechat_prefix("error"), SLACK_PLUGIN_NAME, - workspace_name); + workspace_domain); } } - free(workspace_name); + free(workspace_domain); } } } @@ -272,12 +282,16 @@ int slack_config_init() int slack_config_read() { - return 1; + int rc; + + rc = weechat_config_read(slack_config_file); + + return rc; } int slack_config_write() { - return 1; + return weechat_config_write(slack_config_file); } void slack_config_free() diff --git a/slack-input.c b/slack-input.c new file mode 100644 index 0000000..ec36d5d --- /dev/null +++ b/slack-input.c @@ -0,0 +1,20 @@ +#include "weechat-plugin.h" +#include "slack-input.h" + +int slack_input_data(struct t_gui_buffer *buffer, const char *input_data) +{ + (void) buffer; + (void) input_data; + + return WEECHAT_RC_OK; +} + +int slack_input_data_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *input_data) +{ + (void) pointer; + (void) data; + + return slack_input_data(buffer, input_data); +} diff --git a/slack-input.h b/slack-input.h new file mode 100644 index 0000000..e3ac745 --- /dev/null +++ b/slack-input.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_INPUT_H_ +#define _SLACK_INPUT_H_ + +int slack_input_data_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *input_data); + +#endif /*SLACK_INPUT_H*/ diff --git a/slack-oauth.c b/slack-oauth.c index c18836f..ca46285 100644 --- a/slack-oauth.c +++ b/slack-oauth.c @@ -19,13 +19,13 @@ static struct lws_context *context = NULL; static struct t_hook *slack_oauth_hook_timer = NULL; -static int json_valid(json_object *object) +static inline int json_valid(json_object *object) { if (!object) { weechat_printf( NULL, - _("%s%s: Error retrieving token: unexpected response from server"), + _("%s%s: error retrieving token: unexpected response from server"), weechat_prefix("error"), SLACK_PLUGIN_NAME); return 0; } @@ -54,7 +54,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, status = lws_http_client_http_response(wsi); weechat_printf( NULL, - _("%s%s: Retrieving token... (%d)"), + _("%s%s: retrieving token... (%d)"), weechat_prefix("network"), SLACK_PLUGIN_NAME, status); break; @@ -67,7 +67,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( NULL, - _("%s%s: Got token: %s"), + _("%s%s: got response: %s"), weechat_prefix("network"), SLACK_PLUGIN_NAME, json_string); @@ -92,7 +92,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( NULL, - _("%s%s: Retrieved token: %s"), + _("%s%s: retrieved token: %s"), weechat_prefix("network"), SLACK_PLUGIN_NAME, json_object_get_string(token)); @@ -110,7 +110,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( NULL, - _("%s%s: Failed to retrieve token: %s"), + _("%s%s: failed to retrieve token: %s"), weechat_prefix("error"), SLACK_PLUGIN_NAME, json_object_get_string(error)); } @@ -133,10 +133,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, return 0; /* don't passthru */ case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - client_wsi = NULL; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ - break; - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: client_wsi = NULL; lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ @@ -161,6 +157,10 @@ static const struct lws_protocols protocols[] = { int slack_oauth_timer_cb(const void *pointer, void *data, int remaining_calls) { + (void) pointer; + (void) data; + (void) remaining_calls; + if (n >= 0 && client_wsi) { n = lws_service(context, 0); @@ -183,12 +183,19 @@ void slack_oauth_request_token(char *code, void (*callback)(char *token)) struct lws_context_creation_info info; struct lws_client_connect_info i; + if (client_wsi) + { + weechat_printf( + NULL, + _("%s%s: error: a registration is already in progress"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + size_t urilen = snprintf(NULL, 0, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code) + 1; uri = malloc(urilen); snprintf(uri, urilen, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code); - lws_set_log_level(0, NULL); - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ @@ -207,7 +214,7 @@ void slack_oauth_request_token(char *code, void (*callback)(char *token)) { weechat_printf( NULL, - _("%s%s: Contacting slack.com:443"), + _("%s%s: contacting slack.com:443"), weechat_prefix("network"), SLACK_PLUGIN_NAME); } diff --git a/slack-teaminfo.c b/slack-teaminfo.c new file mode 100644 index 0000000..e8185ad --- /dev/null +++ b/slack-teaminfo.c @@ -0,0 +1,342 @@ +#include +#include +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-teaminfo.h" + +static void (*weechat_callback)(struct t_slack_teaminfo *slack_teaminfo); + +static const char *const endpoint = "/api/team.info?" + "token=%s"; +static char *uri; + +static int n = 0; +static struct lws *client_wsi = NULL; +static struct lws_context *context = NULL; + +static struct t_hook *slack_teaminfo_hook_timer = NULL; + +struct t_json_chunk +{ + char *data; + struct t_json_chunk *next; +}; + +static struct t_json_chunk *slack_teaminfo_chunks = NULL; +static struct t_slack_teaminfo slack_teaminfo; + +static inline int json_valid(json_object *object) +{ + if (!object) + { + weechat_printf( + NULL, + _("%s%s: Error retrieving workspace info: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return 0; + } + + return 1; +} + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + NULL, + _("%s%s: error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + in ? (char *)in : "(null)"); + client_wsi = NULL; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + NULL, + _("%s%s: retrieving workspace details... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (slack_teaminfo_chunks) + { + for (last_chunk = slack_teaminfo_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + slack_teaminfo_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error, *team; + json_object *id, *name, *domain, *email_domain; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (slack_teaminfo_chunks) + { + chunk_count++; + for (chunk_ptr = slack_teaminfo_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = slack_teaminfo_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(slack_teaminfo_chunks->data); + free(slack_teaminfo_chunks); + slack_teaminfo_chunks = chunk_ptr; + } + + weechat_printf( + NULL, + _("%s%s: got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + team = json_object_object_get(response, "team"); + if (!json_valid(team)) + { + json_object_put(response); + free(json_string); + return 0; + } + + id = json_object_object_get(team, "id"); + if (!json_valid(id)) + { + json_object_put(response); + free(json_string); + return 0; + } + + name = json_object_object_get(team, "name"); + if (!json_valid(name)) + { + json_object_put(response); + free(json_string); + return 0; + } + + domain = json_object_object_get(team, "domain"); + if (!json_valid(domain)) + { + json_object_put(response); + free(json_string); + return 0; + } + + email_domain = json_object_object_get(team, "email_domain"); + if (!json_valid(email_domain)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + NULL, + _("%s%s: retrieved workspace details for %s@%s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_object_get_string(name), json_object_get_string(domain)); + + slack_teaminfo.id = json_object_get_string(id); + slack_teaminfo.name = json_object_get_string(name); + slack_teaminfo.domain = json_object_get_string(domain); + slack_teaminfo.email_domain = json_object_get_string(email_domain); + + weechat_callback(&slack_teaminfo); + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + NULL, + _("%s%s: failed to retrieve workspace details: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + client_wsi = NULL; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +int slack_teaminfo_timer_cb(const void *pointer, void *data, int remaining_calls) +{ + (void) pointer; + (void) data; + (void) remaining_calls; + + if (n >= 0 && client_wsi) + { + n = lws_service(context, 0); + } + else if (context) + { + lws_context_destroy(context); + context = NULL; + free(uri); + + if (slack_teaminfo_hook_timer) + weechat_unhook(slack_teaminfo_hook_timer); + } + + return WEECHAT_RC_OK; +} + +void slack_teaminfo_fetch(char *token, void (*callback)(struct t_slack_teaminfo *slack_teaminfo)) +{ + struct lws_context_creation_info info; + struct lws_client_connect_info i; + + if (client_wsi) + { + weechat_printf( + NULL, + _("%s%s: error: a registration is already in progress"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + + slack_teaminfo.token = strdup(token); + + size_t urilen = snprintf(NULL, 0, endpoint, token) + 1; + uri = malloc(urilen); + snprintf(uri, urilen, endpoint, token); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.protocols = protocols; + + context = lws_create_context(&info); + if (!context) + { + weechat_printf( + NULL, + _("%s%s: error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + else + { + weechat_printf( + NULL, + _("%s%s: contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + } + + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + i.context = context; + i.ssl_connection = LCCSCF_USE_SSL; + i.port = 443; + i.address = "slack.com"; + i.path = uri; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + i.protocol = protocols[0].name; + i.pwsi = &client_wsi; + + lws_client_connect_via_info(&i); + + slack_teaminfo_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, + &slack_teaminfo_timer_cb, + NULL, NULL); + + weechat_callback = callback; +} + +void free_teaminfo(struct t_slack_teaminfo *teaminfo) +{ + free(teaminfo->token); +} diff --git a/slack-teaminfo.h b/slack-teaminfo.h new file mode 100644 index 0000000..cf37fe9 --- /dev/null +++ b/slack-teaminfo.h @@ -0,0 +1,16 @@ +#ifndef _SLACK_TEAMINFO_H_ +#define _SLACK_TEAMINFO_H_ + +struct t_slack_teaminfo +{ + const char *id; + const char *name; + const char *domain; + const char *email_domain; + char *token; +}; + +extern void slack_teaminfo_fetch(char *token, void (*callback)(struct t_slack_teaminfo *slack_teaminfo)); +extern void free_teaminfo(struct t_slack_teaminfo *teaminfo); + +#endif /*SLACK_TEAMINFO_H*/ diff --git a/slack-workspace.c b/slack-workspace.c index e2e3c62..da55346 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -1,11 +1,17 @@ +#include +#include #include #include #include +#include #include "weechat-plugin.h" #include "slack.h" +#include "slack-buffer.h" #include "slack-config.h" +#include "slack-input.h" #include "slack-workspace.h" +#include "slack-api.h" struct t_slack_workspace *slack_workspaces = NULL; struct t_slack_workspace *last_slack_workspace = NULL; @@ -14,17 +20,264 @@ char *slack_workspace_options[SLACK_WORKSPACE_NUM_OPTIONS][2] = { { "token", "" }, }; -struct t_slack_workspace *slack_workspace_search(const char *workspace_name) +static const char *const endpoint = "/api/rtm.connect?" + "token=%s&batch_presence_aware=true&presence_sub=false"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: Error requesting websocket: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return 0; + } + + return 1; +} + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_workspace *workspace = (struct t_slack_workspace *)user; + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + in ? (char *)in : "(null)"); + workspace->client_wsi = NULL; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + workspace->buffer, + _("%s%s: requesting a websocket... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (workspace->json_chunks) + { + for (last_chunk = workspace->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + workspace->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error, *self, *team, *url; + json_object *id, *name, *domain; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (workspace->json_chunks) + { + chunk_count++; + for (chunk_ptr = workspace->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = workspace->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(workspace->json_chunks->data); + free(workspace->json_chunks); + workspace->json_chunks = chunk_ptr; + } + + weechat_printf( + workspace->buffer, + _("%s%s: got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + self = json_object_object_get(response, "self"); + if (!json_valid(self, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + else + { + id = json_object_object_get(self, "id"); + if (!json_valid(id, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + workspace->user = strdup(json_object_get_string(id)); + + name = json_object_object_get(self, "name"); + if (!json_valid(name, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + workspace->nick = strdup(json_object_get_string(name)); + } + + team = json_object_object_get(response, "team"); + if (!json_valid(team, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + else + { + domain = json_object_object_get(team, "domain"); + if (!json_valid(domain, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + id = json_object_object_get(team, "id"); + if (!json_valid(id, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + workspace->id = strdup(json_object_get_string(id)); + + name = json_object_object_get(team, "name"); + if (!json_valid(name, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + workspace->name = strdup(json_object_get_string(name)); + } + + url = json_object_object_get(response, "url"); + if (!json_valid(url, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + workspace->ws_url = strdup(json_object_get_string(url)); + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + workspace->buffer, + _("%s%s: failed to request websocket: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + workspace->client_wsi = NULL; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_workspace *slack_workspace_search(const char *workspace_domain) { struct t_slack_workspace *ptr_workspace; - if (!workspace_name) + if (!workspace_domain) return NULL; for (ptr_workspace = slack_workspaces; ptr_workspace; ptr_workspace = ptr_workspace->next_workspace) { - if (strcmp(ptr_workspace->name, workspace_name) == 0) + if (strcmp(ptr_workspace->domain, workspace_domain) == 0) return ptr_workspace; } @@ -32,17 +285,17 @@ struct t_slack_workspace *slack_workspace_search(const char *workspace_name) return NULL; } -struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_name) +struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_domain) { struct t_slack_workspace *ptr_workspace; - if (!workspace_name) + if (!workspace_domain) return NULL; for (ptr_workspace = slack_workspaces; ptr_workspace; ptr_workspace = ptr_workspace->next_workspace) { - if (weechat_strcasecmp (ptr_workspace->name, workspace_name) == 0) + if (weechat_strcasecmp (ptr_workspace->domain, workspace_domain) == 0) return ptr_workspace; } @@ -67,13 +320,13 @@ int slack_workspace_search_option(const char *option_name) return -1; } -struct t_slack_workspace *slack_workspace_alloc(const char *name) +struct t_slack_workspace *slack_workspace_alloc(const char *domain) { struct t_slack_workspace *new_workspace; int i, length; char *option_name; - if (slack_workspace_casesearch(name)) + if (slack_workspace_casesearch(domain)) return NULL; /* alloc memory for new workspace */ @@ -81,8 +334,8 @@ struct t_slack_workspace *slack_workspace_alloc(const char *name) if (!new_workspace) { weechat_printf(NULL, - _("%s%s: error when allocating new workspace"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); + _("%s%s: error when allocating new workspace"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); return NULL; } @@ -95,19 +348,36 @@ struct t_slack_workspace *slack_workspace_alloc(const char *name) slack_workspaces = new_workspace; last_slack_workspace = new_workspace; + /* set properties */ + new_workspace->id = NULL; + new_workspace->name = NULL; + /* set name */ - new_workspace->name = strdup(name); + new_workspace->domain = strdup(domain); /* internal vars */ new_workspace->reloading_from_config = 0; new_workspace->reloaded_from_config = 0; new_workspace->is_connected = 0; + new_workspace->disconnected = 0; + + new_workspace->uri = NULL; + new_workspace->ws_url = NULL; + new_workspace->client_wsi = NULL; + new_workspace->context = NULL; + new_workspace->json_chunks = NULL; + + new_workspace->user = NULL; + new_workspace->nick = NULL; + + new_workspace->buffer = NULL; + new_workspace->buffer_as_string = NULL; /* create options with null value */ for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) { - length = strlen(new_workspace->name) + 1 + + length = strlen(new_workspace->domain) + 1 + strlen(slack_workspace_options[i][0]) + 512 + /* inherited option name(slack.workspace_default.xxx) */ 1; @@ -115,7 +385,7 @@ struct t_slack_workspace *slack_workspace_alloc(const char *name) if (option_name) { snprintf(option_name, length, "%s.%s << slack.workspace_default.%s", - new_workspace->name, + new_workspace->domain, slack_workspace_options[i][0], slack_workspace_options[i][0]); new_workspace->options[i] = slack_config_workspace_new_option( @@ -140,3 +410,378 @@ struct t_slack_workspace *slack_workspace_alloc(const char *name) return new_workspace; } + +void slack_workspace_free_data(struct t_slack_workspace *workspace) +{ + int i; + + if (!workspace) + return; + + /* free linked lists */ + /* + for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) + { + slack_workspace_outqueue_free_all(workspace, i); + } + slack_redirect_free_all(workspace); + slack_notify_free_all(workspace); + slack_channel_free_all(workspace); + */ + + /* free hashtables */ + /* + weechat_hashtable_free(workspace->join_manual); + weechat_hashtable_free(workspace->join_channel_key); + weechat_hashtable_free(workspace->join_noswitch); + */ + + /* free workspace data */ + for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + { + if (workspace->options[i]) + weechat_config_option_free(workspace->options[i]); + } + if (workspace->id) + free(workspace->id); + if (workspace->name) + free(workspace->name); + if (workspace->domain) + free(workspace->domain); + + if (workspace->uri) + free(workspace->uri); + if (workspace->ws_url) + free(workspace->ws_url); + if (workspace->client_wsi) + free(workspace->client_wsi); + if (workspace->context) + free(workspace->context); + while (workspace->json_chunks) + { + struct t_json_chunk *chunk_ptr = workspace->json_chunks->next; + + free(workspace->json_chunks->data); + free(workspace->json_chunks); + workspace->json_chunks = chunk_ptr; + } + + if (workspace->user) + free(workspace->user); + if (workspace->nick) + free(workspace->nick); + + if (workspace->buffer_as_string) + free(workspace->buffer_as_string); +} + +void slack_workspace_free(struct t_slack_workspace *workspace) +{ + struct t_slack_workspace *new_slack_workspaces; + + if (!workspace) + return; + + /* + * close workspace buffer (and all channels/privates) + * (only if we are not in a /upgrade, because during upgrade we want to + * keep connections and closing workspace buffer would disconnect from workspace) + */ + if (workspace->buffer) + weechat_buffer_close(workspace->buffer); + + /* remove workspace from queue */ + if (last_slack_workspace == workspace) + last_slack_workspace = workspace->prev_workspace; + if (workspace->prev_workspace) + { + (workspace->prev_workspace)->next_workspace = workspace->next_workspace; + new_slack_workspaces = slack_workspaces; + } + else + new_slack_workspaces = workspace->next_workspace; + + if (workspace->next_workspace) + (workspace->next_workspace)->prev_workspace = workspace->prev_workspace; + + slack_workspace_free_data(workspace); + free(workspace); + slack_workspaces = new_slack_workspaces; +} + +void slack_workspace_free_all() +{ + /* for each workspace in memory, remove it */ + while (slack_workspaces) + { + slack_workspace_free(slack_workspaces); + } +} + +void slack_workspace_disconnect(struct t_slack_workspace *workspace, + int switch_address, int reconnect) +{ + (void) switch_address; + (void) reconnect; + + struct t_slack_channel *ptr_channel; + (void) ptr_channel; + + if (workspace->is_connected) + { + /* + * remove all nicks and write disconnection message on each + * channel/private buffer + */ + /* + for (ptr_channel = workspace->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + slack_nick_free_all(workspace, ptr_channel); + if (ptr_channel->hook_autorejoin) + { + weechat_unhook(ptr_channel->hook_autorejoin); + ptr_channel->hook_autorejoin = NULL; + } + weechat_buffer_set(ptr_channel->buffer, "localvar_del_away", ""); + weechat_printf( + ptr_channel->buffer, + _("%s%s: disconnected from workspace"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + } + */ + /* remove away status on workspace buffer */ + //weechat_buffer_set(workspace->buffer, "localvar_del_away", ""); + } + + /* + slack_workspace_close_connection(workspace); + + if (workspace->buffer) + { + weechat_printf( + workspace->buffer, + _("%s%s: disconnected from workspace"), + weechat_prefix ("network"), SLACK_PLUGIN_NAME); + } + + workspace->current_retry = 0; + + if (switch_address) + slack_workspace_switch_address(workspace, 0); + else + slack_workspace_set_index_current_address(workspace, 0); + + if (workspace->nick_modes) + { + free (workspace->nick_modes); + workspace->nick_modes = NULL; + weechat_bar_item_update ("input_prompt"); + weechat_bar_item_update ("slack_nick_modes"); + } + workspace->cap_away_notify = 0; + workspace->cap_account_notify = 0; + workspace->cap_extended_join = 0; + workspace->is_away = 0; + workspace->away_time = 0; + workspace->lag = 0; + workspace->lag_displayed = -1; + workspace->lag_check_time.tv_sec = 0; + workspace->lag_check_time.tv_usec = 0; + workspace->lag_next_check = time (NULL) + + weechat_config_integer (slack_config_network_lag_check); + workspace->lag_last_refresh = 0; + slack_workspace_set_lag (workspace); + workspace->monitor = 0; + workspace->monitor_time = 0; + + if (reconnect + && IRC_SERVER_OPTION_BOOLEAN(workspace, IRC_SERVER_OPTION_AUTORECONNECT)) + slack_workspace_reconnect_schedule(workspace); + else + { + workspace->reconnect_delay = 0; + workspace->reconnect_start = 0; + } + */ + + /* discard current nick if no reconnection asked */ + /* + if (!reconnect && workspace->nick) + slack_workspace_set_nick(workspace, NULL); + + slack_workspace_set_buffer_title(workspace); + + workspace->disconnected = 1; + */ + + /* send signal "slack_workspace_disconnected" with workspace name */ + /* + (void) weechat_hook_signal_send("slack_workspace_disconnected", + WEECHAT_HOOK_SIGNAL_STRING, workspace->name); + */ +} + +void slack_workspace_disconnect_all() +{ + struct t_slack_workspace *ptr_workspace; + + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + slack_workspace_disconnect(ptr_workspace, 0, 0); + } +} + +struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *workspace) +{ + char buffer_name[256], charset_modifier[256]; + + snprintf(buffer_name, sizeof(buffer_name), + "slack.%s", workspace->domain); + workspace->buffer = weechat_buffer_new(buffer_name, + &slack_input_data_cb, NULL, NULL, + &slack_buffer_close_cb, NULL, NULL); + if (!workspace->buffer) + return NULL; + + if (!weechat_buffer_get_integer(workspace->buffer, "short_name_is_set")) + weechat_buffer_set(workspace->buffer, "short_name", workspace->domain); + weechat_buffer_set(workspace->buffer, "localvar_set_type", "server"); + weechat_buffer_set(workspace->buffer, "localvar_set_server", workspace->domain); + weechat_buffer_set(workspace->buffer, "localvar_set_channel", workspace->domain); + snprintf(charset_modifier, sizeof (charset_modifier), + "slack.%s", workspace->domain); + weechat_buffer_set(workspace->buffer, "localvar_set_charset_modifier", + charset_modifier); + weechat_buffer_set(workspace->buffer, "title", + (workspace->name) ? workspace->name : ""); + + return workspace->buffer; +} + +void slack_workspace_close_connection(struct t_slack_workspace *workspace) +{ + workspace->is_connected = 0; + workspace->client_wsi = NULL; + workspace->context = NULL; +} + +void slack_workspace_websocket_create(struct t_slack_workspace *workspace) +{ + struct lws_context_creation_info info; + struct lws_client_connect_info i; + const char *token; + + if (workspace->client_wsi) + { + weechat_printf( + workspace->buffer, + _("%s%s: error: a websocket already exists"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + + token = weechat_config_string(workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]); + + size_t urilen = snprintf(NULL, 0, endpoint, token) + 1; + workspace->uri = malloc(urilen); + snprintf(workspace->uri, urilen, endpoint, token); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.protocols = protocols; + + workspace->context = lws_create_context(&info); + if (!workspace->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + } + + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + i.context = workspace->context; + i.ssl_connection = LCCSCF_USE_SSL; + i.port = 443; + i.address = "slack.com"; + i.path = workspace->uri; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + i.protocol = protocols[0].name; + i.pwsi = &workspace->client_wsi; + i.userdata = workspace; + + lws_client_connect_via_info(&i); + + workspace->is_connected = 1; +} + +int slack_workspace_connect(struct t_slack_workspace *workspace) +{ + workspace->disconnected = 0; + + if (!workspace->buffer) + { + if (!slack_workspace_create_buffer(workspace)) + return 0; + weechat_buffer_set(workspace->buffer, "display", "auto"); + } + + slack_workspace_close_connection(workspace); + + slack_workspace_websocket_create(workspace); + + return 1; +} + +int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls) +{ + struct t_slack_workspace *ptr_workspace; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) remaining_calls; + + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + if (!ptr_workspace->is_connected) + continue; + + if (ptr_workspace->client_wsi) + { + lws_service(ptr_workspace->context, 0); + } + else if (ptr_workspace->context) + { + lws_context_destroy(ptr_workspace->context); + ptr_workspace->context = NULL; + if (ptr_workspace->uri) + { + free(ptr_workspace->uri); + ptr_workspace->uri = NULL; + } + if (ptr_workspace->ws_url) + { + slack_api_connect(ptr_workspace); + free(ptr_workspace->ws_url); + ptr_workspace->ws_url = NULL; + } + } + } + + return WEECHAT_RC_OK; +} diff --git a/slack-workspace.h b/slack-workspace.h index 2b79eb6..216eeb7 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -10,24 +10,54 @@ enum t_slack_workspace_option SLACK_WORKSPACE_NUM_OPTIONS, }; +struct t_json_chunk +{ + char *data; + struct t_json_chunk *next; +}; + struct t_slack_workspace { + char *id; char *name; + char *domain; struct t_config_option *options[SLACK_WORKSPACE_NUM_OPTIONS]; int reloading_from_config; int reloaded_from_config; int is_connected; + int disconnected; + + char *uri; + char *ws_url; + struct lws *client_wsi; + struct lws_context *context; + struct t_json_chunk *json_chunks; + + char *user; + char *nick; + struct t_gui_buffer *buffer; + char *buffer_as_string; struct t_slack_workspace *prev_workspace; struct t_slack_workspace *next_workspace; }; extern char *slack_workspace_options[][2]; -struct t_slack_workspace *slack_workspace_search(const char *workspace_name); +struct t_slack_workspace *slack_workspace_search(const char *workspace_domain); +struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_domain); int slack_workspace_search_option(const char *option_name); -struct t_slack_workspace *slack_workspace_alloc(const char *name); +struct t_slack_workspace *slack_workspace_alloc(const char *domain); +void slack_workspace_free_data(struct t_slack_workspace *workspace); +void slack_workspace_free(struct t_slack_workspace *workspace); +void slack_workspace_free_all(); +void slack_workspace_disconnect(struct t_slack_workspace *workspace, + int switch_address, int reconnect); +void slack_workspace_disconnect_all(); +void slack_workspace_close_connection(struct t_slack_workspace *workspace); +int slack_workspace_connect(struct t_slack_workspace *workspace); +int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls); #endif /*SLACK_WORKSPACE_H*/ diff --git a/slack.c b/slack.c index f1ba914..528e4b1 100644 --- a/slack.c +++ b/slack.c @@ -1,11 +1,13 @@ #include #include #include +#include #include "weechat-plugin.h" #include "slack.h" #include "slack-config.h" #include "slack-command.h" +#include "slack-workspace.h" WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME); @@ -17,6 +19,20 @@ WEECHAT_PLUGIN_PRIORITY(6000); struct t_weechat_plugin *weechat_slack_plugin = NULL; +struct t_hook *slack_hook_timer = NULL; + +void slack_lwsl_emit_weechat(int level, const char *line) +{ + char buf[50]; + lwsl_timestamp(level, buf, sizeof(buf)); + + weechat_printf( + NULL, + _("%s%s: %s%s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + buf, line); +} + int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { (void) argc; @@ -24,6 +40,11 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_plugin = plugin; + lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO | LLL_DEBUG + | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT + | LLL_LATENCY | LLL_USER | LLL_COUNT, + slack_lwsl_emit_weechat); + if (!slack_config_init()) return WEECHAT_RC_ERROR; @@ -31,6 +52,10 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) slack_command_init(); + slack_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, + &slack_workspace_timer_cb, + NULL, NULL); + return WEECHAT_RC_OK; } @@ -39,5 +64,14 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) /* make C compiler happy */ (void) plugin; + if (slack_hook_timer) + weechat_unhook(slack_hook_timer); + + slack_config_write(); + + slack_workspace_disconnect_all(); + + slack_workspace_free_all(); + return WEECHAT_RC_OK; } From b87ddd7a6c71ae14777bc30374da65cdb77ac546 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Tue, 1 May 2018 13:32:51 +0100 Subject: [PATCH 004/118] switch to gnutls to avoid gcrypt state corruption --- Makefile | 2 +- slack-api.c | 33 +++++++++++++++++---------------- slack-teaminfo.c | 2 +- slack-workspace.c | 2 +- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index fda87ab..cb2b6a2 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX=clang++ RM=rm -f CFLAGS=-fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c LDFLAGS=-shared -g -LDLIBS=-lssl +LDLIBS=-lgnutls SRCS=slack.c \ slack-api.c \ diff --git a/slack-api.c b/slack-api.c index 0cd3b78..b9510fa 100644 --- a/slack-api.c +++ b/slack-api.c @@ -1,4 +1,5 @@ #include +#include #include #include "weechat-plugin.h" @@ -32,7 +33,7 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, weechat_prefix("network"), SLACK_PLUGIN_NAME); break; - /* chunks of chunked content, with header removed */ + /* data is never chunked */ case LWS_CALLBACK_CLIENT_RECEIVE: weechat_printf( workspace->buffer, @@ -40,25 +41,25 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, weechat_prefix("network"), SLACK_PLUGIN_NAME, (const char *)in); { - struct t_json_chunk *new_chunk, *last_chunk; + char *json_string; + json_object *response, *type; - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; + json_string = strdup((const char *)in); - strncat(new_chunk->data, in, (int)len); - - if (workspace->json_chunks) - { - for (last_chunk = workspace->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else + response = json_tokener_parse(json_string); + type = json_object_object_get(response, "type"); + if (!type) { - workspace->json_chunks = new_chunk; + weechat_printf( + workspace->buffer, + _("%s%s: unexpected data received from websocket: closing"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + json_object_put(response); + free(json_string); + return -1; } + + free(json_string); } return 0; /* don't passthru */ diff --git a/slack-teaminfo.c b/slack-teaminfo.c index e8185ad..431bfd7 100644 --- a/slack-teaminfo.c +++ b/slack-teaminfo.c @@ -34,7 +34,7 @@ static inline int json_valid(json_object *object) { weechat_printf( NULL, - _("%s%s: Error retrieving workspace info: unexpected response from server"), + _("%s%s: error retrieving workspace info: unexpected response from server"), weechat_prefix("error"), SLACK_PLUGIN_NAME); return 0; } diff --git a/slack-workspace.c b/slack-workspace.c index da55346..32fcf30 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -29,7 +29,7 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work { weechat_printf( workspace->buffer, - _("%s%s: Error requesting websocket: unexpected response from server"), + _("%s%s: error requesting websocket: unexpected response from server"), weechat_prefix("error"), SLACK_PLUGIN_NAME); return 0; } From 42b32148e3bc5570b0c7fd15dcdf822f938a4ff6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 2 May 2018 08:11:57 +0100 Subject: [PATCH 005/118] Channels and users --- Makefile | 9 +- api/slack-api-error.c | 59 +++++ api/slack-api-error.h | 7 + api/slack-api-hello.c | 43 ++++ api/slack-api-hello.h | 7 + request/slack-request-channels-list.c | 292 ++++++++++++++++++++++++ request/slack-request-channels-list.h | 8 + request/slack-request-users-list.c | 282 +++++++++++++++++++++++ request/slack-request-users-list.h | 8 + slack-api.c | 61 +++++ slack-api.h | 5 + slack-buffer.c | 36 ++- slack-buffer.h | 5 + slack-channel.c | 311 ++++++++++++++++++++++++++ slack-channel.h | 80 +++++++ slack-request.c | 22 ++ slack-request.h | 19 ++ slack-user.c | 151 +++++++++++++ slack-user.h | 55 +++++ slack-workspace.c | 64 +++++- slack-workspace.h | 7 + slack.c | 6 +- 22 files changed, 1522 insertions(+), 15 deletions(-) create mode 100644 api/slack-api-error.c create mode 100644 api/slack-api-error.h create mode 100644 api/slack-api-hello.c create mode 100644 api/slack-api-hello.h create mode 100644 request/slack-request-channels-list.c create mode 100644 request/slack-request-channels-list.h create mode 100644 request/slack-request-users-list.c create mode 100644 request/slack-request-users-list.h create mode 100644 slack-channel.c create mode 100644 slack-channel.h create mode 100644 slack-request.c create mode 100644 slack-request.h create mode 100644 slack-user.c create mode 100644 slack-user.h diff --git a/Makefile b/Makefile index cb2b6a2..1098b37 100644 --- a/Makefile +++ b/Makefile @@ -8,12 +8,19 @@ LDLIBS=-lgnutls SRCS=slack.c \ slack-api.c \ slack-buffer.c \ + slack-channel.c \ slack-config.c \ slack-command.c \ slack-input.c \ slack-oauth.c \ + slack-request.c \ slack-teaminfo.c \ - slack-workspace.c + slack-user.c \ + slack-workspace.c \ + api/slack-api-hello.c \ + api/slack-api-error.c \ + request/slack-request-channels-list.c \ + request/slack-request-users-list.c OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack diff --git a/api/slack-api-error.c b/api/slack-api-error.c new file mode 100644 index 0000000..6fe75bc --- /dev/null +++ b/api/slack-api-error.c @@ -0,0 +1,59 @@ +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-api.h" +#include "slack-api-error.h" + +static const char *type = "error"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %s%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), type, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_error_handle(struct t_slack_workspace *workspace, + int code, const char *msg) +{ + weechat_printf( + workspace->buffer, + _("%s%s: error %d: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + code, msg); + + return 0; +} + +int slack_api_error(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *error, *code, *msg; + + error = json_object_object_get(message, "error"); + if (!json_valid(error, workspace)) + return 0; + + code = json_object_object_get(error, "code"); + if (!json_valid(code, workspace)) + return 0; + + msg = json_object_object_get(error, "msg"); + if (!json_valid(msg, workspace)) + return 0; + + return slack_api_error_handle(workspace, + json_object_get_int(code), + json_object_get_string(msg)); +} diff --git a/api/slack-api-error.h b/api/slack-api-error.h new file mode 100644 index 0000000..19afd9d --- /dev/null +++ b/api/slack-api-error.h @@ -0,0 +1,7 @@ +#ifndef _SLACK_API_ERROR_H_ +#define _SLACK_API_ERROR_H_ + +int slack_api_error(struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_ERROR_H*/ diff --git a/api/slack-api-hello.c b/api/slack-api-hello.c new file mode 100644 index 0000000..406cbd3 --- /dev/null +++ b/api/slack-api-hello.c @@ -0,0 +1,43 @@ +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-api.h" +#include "slack-api-hello.h" +#include "../request/slack-request-channels-list.h" +#include "../request/slack-request-users-list.h" + +int slack_api_hello_handle(struct t_slack_workspace *workspace) +{ + struct t_slack_request *request; + + weechat_printf( + workspace->buffer, + _("%s%s: connected!"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + + request = slack_request_users_list(workspace, + weechat_config_string( + workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + ""); + if (request) + slack_workspace_register_request(workspace, request); + + request = slack_request_channels_list(workspace, + weechat_config_string( + workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + ""); + if (request) + slack_workspace_register_request(workspace, request); + + return 1; +} + +int slack_api_hello(struct t_slack_workspace *workspace, + json_object *message) +{ + (void) message; + + return slack_api_hello_handle(workspace); +} diff --git a/api/slack-api-hello.h b/api/slack-api-hello.h new file mode 100644 index 0000000..08432f3 --- /dev/null +++ b/api/slack-api-hello.h @@ -0,0 +1,7 @@ +#ifndef _SLACK_API_HELLO_H_ +#define _SLACK_API_HELLO_H_ + +int slack_api_hello(struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_HELLO_H*/ diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c new file mode 100644 index 0000000..d5c948c --- /dev/null +++ b/request/slack-request-channels-list.c @@ -0,0 +1,292 @@ +#include +#include +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-request.h" +#include "../slack-channel.h" +#include "../request/slack-request-channels-list.h" + +static const char *const endpoint = "/api/channels.list?" + "token=%s&cursor=%s&" + "exclude_archived=false&exclude_members=true&limit=0"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error retrieving channels: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + __asm__("int3"); + return 0; + } + + return 1; +} + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + in ? (char *)in : "(null)"); + request->client_wsi = NULL; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: retrieving channels... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error, *channels; + json_object *channel, *id, *name, *topic; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + channels = json_object_object_get(response, "channels"); + if (!json_valid(channels, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + for (i = json_object_array_length(channels); i > 0; i--) + { + struct t_slack_channel *new_channel; + + channel = json_object_array_get_idx(channels, i - 1); + if (!json_valid(channel, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + id = json_object_object_get(channel, "id"); + if (!json_valid(id, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + name = json_object_object_get(channel, "name"); + if (!json_valid(name, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + topic = json_object_object_get(channel, "topic"); + if (!json_valid(topic, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + new_channel = slack_channel_new( + request->workspace, + SLACK_CHANNEL_TYPE_CHANNEL, + json_object_get_string(id), + json_object_get_string(name)); + } + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: failed to retrieve channels: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_channels_list( + struct t_slack_workspace *workspace, + const char *token, const char *cursor) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + + size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token, cursor); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-channels-list.h b/request/slack-request-channels-list.h new file mode 100644 index 0000000..e41545a --- /dev/null +++ b/request/slack-request-channels-list.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_REQUEST_CHANNELS_LIST_H_ +#define _SLACK_REQUEST_CHANNELS_LIST_H_ + +struct t_slack_request *slack_request_channels_list( + struct t_slack_workspace *workspace, + const char *token, const char *cursor); + +#endif /*SLACK_REQUEST_CHANNELS_LIST_H*/ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c new file mode 100644 index 0000000..3b85506 --- /dev/null +++ b/request/slack-request-users-list.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-request.h" +#include "../request/slack-request-users-list.h" + +static const char *const endpoint = "/api/users.list?" + "token=%s&cursor=%s&" + "exclude_archived=false&exclude_members=true&limit=0"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error retrieving users: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + __asm__("int3"); + return 0; + } + + return 1; +} + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + in ? (char *)in : "(null)"); + request->client_wsi = NULL; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: retrieving users... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error, *members; + json_object *user, *id, *name; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + members = json_object_object_get(response, "members"); + if (!json_valid(members, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + for (i = json_object_array_length(members); i > 0; i--) + { + user = json_object_array_get_idx(members, i - 1); + if (!json_valid(user, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + id = json_object_object_get(user, "id"); + if (!json_valid(id, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + name = json_object_object_get(user, "name"); + if (!json_valid(name, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: got user: %s (%s)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, + json_object_get_string(name), + json_object_get_string(id)); + } + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: failed to retrieve users: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_users_list( + struct t_slack_workspace *workspace, + const char *token, const char *cursor) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + + size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token, cursor); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-users-list.h b/request/slack-request-users-list.h new file mode 100644 index 0000000..4623c4b --- /dev/null +++ b/request/slack-request-users-list.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_REQUEST_USERS_LIST_H_ +#define _SLACK_REQUEST_USERS_LIST_H_ + +struct t_slack_request *slack_request_users_list( + struct t_slack_workspace *workspace, + const char *token, const char *cursor); + +#endif /*SLACK_REQUEST_USERS_LIST_H*/ diff --git a/slack-api.c b/slack-api.c index b9510fa..ff92721 100644 --- a/slack-api.c +++ b/slack-api.c @@ -1,11 +1,37 @@ #include #include +#include #include #include "weechat-plugin.h" #include "slack.h" #include "slack-workspace.h" #include "slack-api.h" +#include "api/slack-api-hello.h" +#include "api/slack-api-error.h" + +struct stringcase +{ + const char *string; + int (*func)(struct t_slack_workspace *workspace, + json_object *message); +}; + +struct stringcase cases[] = +{ { "hello", slack_api_hello } +, { "error", slack_api_error } +}; + +static int stringcase_cmp(const void *p1, const void *p2) +{ + return strcasecmp(((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string); +} + +void slack_api_init() +{ + size_t case_count = sizeof(cases) / sizeof(cases[0]); + qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); +} static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, void *user, void* in, size_t len) @@ -59,6 +85,15 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, return -1; } + if (!slack_api_route_message(workspace, + json_object_get_string(type), response)) + { + json_object_put(response); + free(json_string); + return -1; + } + + json_object_put(response); free(json_string); } return 0; /* don't passthru */ @@ -157,3 +192,29 @@ void slack_api_connect(struct t_slack_workspace *workspace) lws_client_connect_via_info(&ccinfo); } + +int slack_api_route_message(struct t_slack_workspace *workspace, + const char *type, json_object *message) +{ + struct stringcase key; + key.string = type; + + size_t case_count = sizeof(cases) / sizeof(cases[0]); + void *entry_ptr = bsearch(&key, cases, case_count, + sizeof(struct stringcase), stringcase_cmp); + + if (entry_ptr) + { + struct stringcase *entry = (struct stringcase *)entry_ptr; + return (*entry->func)(workspace, message); + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: got unhandled message of type: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + type); + return 1; + } +} diff --git a/slack-api.h b/slack-api.h index 6a0281b..249f975 100644 --- a/slack-api.h +++ b/slack-api.h @@ -1,6 +1,11 @@ #ifndef _SLACK_API_H_ #define _SLACK_API_H_ +void slack_api_init(); + void slack_api_connect(struct t_slack_workspace *workspace); +int slack_api_route_message(struct t_slack_workspace *workspace, + const char *type, json_object *message); + #endif /*SLACK_API_H*/ diff --git a/slack-buffer.c b/slack-buffer.c index 8fceb3d..40d49c0 100644 --- a/slack-buffer.c +++ b/slack-buffer.c @@ -2,13 +2,14 @@ #include "slack.h" #include "slack-buffer.h" #include "slack-workspace.h" +#include "slack-channel.h" void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, - struct t_slack_workspace **workspace)//, - //struct t_slack_channel **channel) + struct t_slack_workspace **workspace, + struct t_slack_channel **channel) { struct t_slack_workspace *ptr_workspace; - //struct t_slack_channel *ptr_channel; + struct t_slack_channel *ptr_channel; if (!buffer) return; @@ -24,7 +25,6 @@ void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, return; } - /* for (ptr_channel = ptr_workspace->channels; ptr_channel; ptr_channel = ptr_channel->next_channel) { @@ -37,22 +37,46 @@ void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, return; } } - */ } /* no workspace or channel found */ } +int slack_buffer_nickcmp_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *nick1, + const char *nick2) +{ + struct t_slack_workspace *workspace; + + (void) data; + + if (pointer) + workspace = (struct t_slack_workspace *)pointer; + else + slack_buffer_get_workspace_and_channel(buffer, &workspace, NULL); + + if (workspace) + { + return weechat_strcasecmp(nick1, nick2); + } + else + { + return weechat_strcasecmp(nick1, nick2); + } +} + int slack_buffer_close_cb(const void *pointer, void *data, struct t_gui_buffer *buffer) { struct t_weechat_plugin *buffer_plugin = NULL; struct t_slack_workspace *ptr_workspace = NULL; + struct t_slack_channel *ptr_channel = NULL; buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin"); if (buffer_plugin == weechat_slack_plugin) slack_buffer_get_workspace_and_channel(buffer, - &ptr_workspace);//, &ptr_channel); + &ptr_workspace, &ptr_channel); (void) pointer; (void) data; diff --git a/slack-buffer.h b/slack-buffer.h index 8ba6a03..7410ab2 100644 --- a/slack-buffer.h +++ b/slack-buffer.h @@ -1,6 +1,11 @@ #ifndef _SLACK_BUFFER_H_ #define _SLACK_BUFFER_H_ +int slack_buffer_nickcmp_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *nick1, + const char *nick2); + int slack_buffer_close_cb(const void *pointer, void *data, struct t_gui_buffer *buffer); diff --git a/slack-channel.c b/slack-channel.c new file mode 100644 index 0000000..4b855d6 --- /dev/null +++ b/slack-channel.c @@ -0,0 +1,311 @@ +#include +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-workspace.h" +#include "slack-channel.h" +#include "slack-input.h" +#include "slack-buffer.h" + +struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace, + const char *id) +{ + struct t_slack_channel *ptr_channel; + + if (!workspace || !id) + return NULL; + + for (ptr_channel = workspace->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + if (weechat_strcasecmp(ptr_channel->id, id) == 0) + return ptr_channel; + } + + return NULL; +} + +struct t_gui_buffer *slack_channel_search_buffer(struct t_slack_workspace *workspace, + enum t_slack_channel_type type, + const char *name) +{ + struct t_hdata *hdata_buffer; + struct t_gui_buffer *ptr_buffer; + const char *ptr_type, *ptr_workspace_name, *ptr_channel_name; + + hdata_buffer = weechat_hdata_get("buffer"); + ptr_buffer = weechat_hdata_get_list(hdata_buffer, "gui_buffers"); + + while (ptr_buffer) + { + if (weechat_buffer_get_pointer(ptr_buffer, "plugin") == weechat_slack_plugin) + { + ptr_type = weechat_buffer_get_string(ptr_buffer, "localvar_type"); + ptr_workspace_name = weechat_buffer_get_string(ptr_buffer, + "localvar_server"); + ptr_channel_name = weechat_buffer_get_string(ptr_buffer, + "localvar_channel"); + if (ptr_type && ptr_type[0] + && ptr_workspace_name && ptr_workspace_name[0] + && ptr_channel_name && ptr_channel_name[0] + && ( (( (type == SLACK_CHANNEL_TYPE_CHANNEL) + || (type == SLACK_CHANNEL_TYPE_GROUP)) + && (strcmp(ptr_type, "channel") == 0)) + || (( (type == SLACK_CHANNEL_TYPE_MPIM) + || (type == SLACK_CHANNEL_TYPE_IM)) + && (strcmp(ptr_type, "private") == 0))) + && (strcmp(ptr_workspace_name, workspace->domain) == 0) + && (weechat_strcasecmp(ptr_channel_name, name) == 0)) + { + return ptr_buffer; + } + } + ptr_buffer = weechat_hdata_move(hdata_buffer, ptr_buffer, 1); + } + + return NULL; +} + +struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *workspace, + enum t_slack_channel_type type, + const char *name) +{ + struct t_gui_buffer *ptr_buffer; + int buffer_created, current_buffer_number; + const char *short_name, *localvar_channel; + char buffer_name[256]; + + buffer_created = 0; + + snprintf(buffer_name, sizeof(buffer_name), + "%s.%s", workspace->domain, name); + + ptr_buffer = slack_channel_search_buffer(workspace, type, name); + if (ptr_buffer) + { + weechat_nicklist_remove_all(ptr_buffer); + } + else + { + current_buffer_number = weechat_buffer_get_integer( + weechat_current_buffer(), "number"); + + ptr_buffer = weechat_buffer_new(buffer_name, + &slack_input_data_cb, NULL, NULL, + &slack_buffer_close_cb, NULL, NULL); + if (!ptr_buffer) + return NULL; + + buffer_created = 1; + } + + if (buffer_created) + { + if (!weechat_buffer_get_integer(ptr_buffer, "short_name_is_set")) + weechat_buffer_set(ptr_buffer, "short_name", name); + } + else + { + short_name = weechat_buffer_get_string (ptr_buffer, "short_name"); + localvar_channel = weechat_buffer_get_string (ptr_buffer, + "localvar_channel"); + + if (!short_name || + (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) + { + weechat_buffer_set (ptr_buffer, "short_name", name); + } + } + + weechat_buffer_set(ptr_buffer, "name", buffer_name); + weechat_buffer_set(ptr_buffer, "localvar_set_type", + (type == SLACK_CHANNEL_TYPE_IM || + type == SLACK_CHANNEL_TYPE_MPIM) ? "private" : "channel"); + weechat_buffer_set(ptr_buffer, "localvar_set_nick", workspace->nick); + weechat_buffer_set(ptr_buffer, "localvar_set_server", workspace->domain); + weechat_buffer_set(ptr_buffer, "localvar_set_channel", name); + + if (buffer_created) + { + (void) weechat_hook_signal_send ("logger_backlog", + WEECHAT_HOOK_SIGNAL_POINTER, + ptr_buffer); + weechat_buffer_set(ptr_buffer, "input_get_unknown_commands", "1"); + if (type != SLACK_CHANNEL_TYPE_IM) + { + weechat_buffer_set(ptr_buffer, "nicklist", "1"); + weechat_buffer_set(ptr_buffer, "nicklist_display_groups", "0"); + weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback", + &slack_buffer_nickcmp_cb); + weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback_pointer", + workspace); + } + + weechat_buffer_set(ptr_buffer, "highlight_words_add", + workspace->nick); + weechat_buffer_set(ptr_buffer, "highlight_tags_restrict", + "slack_message"); + } + + return ptr_buffer; +} + +struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, + enum t_slack_channel_type type, + const char *id, const char *name) +{ + struct t_slack_channel *new_channel, *ptr_channel; + struct t_gui_buffer *ptr_buffer; + + if (!workspace || !id) + return NULL; + + ptr_channel = slack_channel_search(workspace, id); + if (ptr_channel) + { + return ptr_channel; + } + + ptr_buffer = slack_channel_create_buffer(workspace, type, name); + if (!ptr_buffer) + return NULL; + + if ((new_channel = malloc(sizeof(*new_channel))) == NULL) + return NULL; + + new_channel->type = type; + new_channel->id = strdup(id); + new_channel->name = strdup(name); + new_channel->created = 0; + + new_channel->is_general = 0; + new_channel->name_normalized = NULL; + new_channel->is_shared = 0; + new_channel->is_org_shared = 0; + new_channel->is_member = 0; + + new_channel->topic.value = NULL; + new_channel->topic.creator = NULL; + new_channel->topic.last_set = 0; + new_channel->purpose.value = NULL; + new_channel->purpose.creator = NULL; + new_channel->purpose.last_set = 0; + new_channel->is_archived = 0; + + new_channel->creator = NULL; + new_channel->last_read = 0.0; + new_channel->unread_count = 0; + new_channel->unread_count_display = 0; + + new_channel->is_user_deleted = 0; + + new_channel->members = NULL; + new_channel->last_member = NULL; + new_channel->buffer = ptr_buffer; + new_channel->buffer_as_string = NULL; + + new_channel->prev_channel = NULL; + new_channel->next_channel = NULL; + + new_channel->prev_channel = workspace->last_channel; + if (workspace->last_channel) + (workspace->last_channel)->next_channel = new_channel; + workspace->last_channel = new_channel; + + return new_channel; +} + +void slack_channel_member_free(struct t_slack_channel *channel, + struct t_slack_channel_member *member) +{ + struct t_slack_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); + + free(member); + + channel->members = new_members; +} + +void slack_channel_member_free_all(struct t_slack_channel *channel) +{ + while (channel->members) + slack_channel_member_free(channel, channel->members); +} + +void slack_channel_free(struct t_slack_workspace *workspace, + struct t_slack_channel *channel) +{ + struct t_slack_channel *new_channels; + + if (!workspace || !channel) + return; + + /* remove channel from channels list */ + if (workspace->last_channel == channel) + workspace->last_channel = channel->prev_channel; + if (channel->prev_channel) + { + (channel->prev_channel)->next_channel = channel->next_channel; + new_channels = workspace->channels; + } + else + new_channels = channel->next_channel; + + if (channel->next_channel) + (channel->next_channel)->prev_channel = channel->prev_channel; + + /* free linked lists */ + slack_channel_member_free_all(channel); + + /* free channel data */ + if (channel->id) + free(channel->id); + if (channel->name) + free(channel->name); + if (channel->name_normalized) + free(channel->name_normalized); + if (channel->topic.value) + free(channel->topic.value); + if (channel->topic.creator) + free(channel->topic.creator); + if (channel->purpose.value) + free(channel->purpose.value); + if (channel->purpose.creator) + free(channel->purpose.creator); + if (channel->creator) + free(channel->creator); + if (channel->buffer_as_string) + free (channel->buffer_as_string); + + free(channel); + + workspace->channels = new_channels; +} + +void slack_channel_free_all(struct t_slack_workspace *workspace) +{ + while (workspace->channels) + slack_channel_free(workspace, workspace->channels); +} diff --git a/slack-channel.h b/slack-channel.h new file mode 100644 index 0000000..b9b46b5 --- /dev/null +++ b/slack-channel.h @@ -0,0 +1,80 @@ +#ifndef _SLACK_CHANNEL_H_ +#define _SLACK_CHANNEL_H_ + +enum t_slack_channel_type +{ + SLACK_CHANNEL_TYPE_CHANNEL, + SLACK_CHANNEL_TYPE_GROUP, + SLACK_CHANNEL_TYPE_MPIM, + SLACK_CHANNEL_TYPE_IM, +}; + +struct t_slack_channel_member +{ + char *id; + + struct t_slack_channel_member *prev_member; + struct t_slack_channel_member *next_member; +}; + +struct t_slack_channel_topic +{ + char *value; + char *creator; + int last_set; +}; + +struct t_slack_channel_purpose +{ + char *value; + char *creator; + int last_set; +}; + +struct t_slack_channel +{ + enum t_slack_channel_type type; + char *id; + char *name; + int created; + + /* channel */ + int is_general; + char *name_normalized; + int is_shared; + int is_org_shared; + int is_member; + + /* group */ + struct t_slack_channel_topic topic; + struct t_slack_channel_purpose purpose; + int is_archived; + + /* mpim */ + char *creator; + double last_read; + int unread_count; + int unread_count_display; + + /* im */ + int is_user_deleted; + + struct t_slack_channel_member *members; + struct t_slack_channel_member *last_member; + struct t_gui_buffer *buffer; + char *buffer_as_string; + + struct t_slack_channel *prev_channel; + struct t_slack_channel *next_channel; +}; + +struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace, + const char *id); + +struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, + enum t_slack_channel_type type, + const char *id, const char *name); + +void slack_user_free_all(struct t_slack_workspace *workspace); + +#endif /*SLACK_CHANNEL_H*/ diff --git a/slack-request.c b/slack-request.c new file mode 100644 index 0000000..6db1816 --- /dev/null +++ b/slack-request.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-workspace.h" +#include "slack-request.h" + +struct t_slack_request *slack_request_alloc( + struct t_slack_workspace *workspace) +{ + struct t_slack_request *request; + + request = malloc(sizeof(struct t_slack_request)); + memset(request, 0, sizeof(struct t_slack_request)); + + request->workspace = workspace; + + return request; +} diff --git a/slack-request.h b/slack-request.h new file mode 100644 index 0000000..21abf8b --- /dev/null +++ b/slack-request.h @@ -0,0 +1,19 @@ +#ifndef _SLACK_REQUEST_H_ +#define _SLACK_REQUEST_H_ + +struct t_slack_request +{ + struct t_slack_workspace *workspace; + + char *uri; + struct lws *client_wsi; + struct lws_context *context; + struct t_json_chunk *json_chunks; + + struct t_slack_request *next; +}; + +struct t_slack_request *slack_request_alloc( + struct t_slack_workspace *workspace); + +#endif /*SLACK_REQUEST_H*/ diff --git a/slack-user.c b/slack-user.c new file mode 100644 index 0000000..c093b97 --- /dev/null +++ b/slack-user.c @@ -0,0 +1,151 @@ +#include +#include + +#include "weechat-plugin.h" +#include "slack.h" +#include "slack-workspace.h" +#include "slack-user.h" + +struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, + const char *id) +{ + struct t_slack_user *ptr_user; + + if (!workspace || !id) + return NULL; + + for (ptr_user = workspace->users; ptr_user; + ptr_user = ptr_user->next_user) + { + if (weechat_strcasecmp(ptr_user->id, id) == 0) + return ptr_user; + } + + return NULL; +} + +struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, + const char *id) +{ + struct t_slack_user *new_user, *ptr_user; + + if (!workspace || !id) + return NULL; + + ptr_user = slack_user_search(workspace, id); + if (ptr_user) + { + return ptr_user; + } + + if ((new_user = malloc(sizeof(*new_user))) == NULL) + return NULL; + + new_user->prev_user = workspace->last_user; + (workspace->last_user)->next_user = new_user; + workspace->last_user = new_user; + + new_user->id = strdup(id); + new_user->name = NULL; + new_user->team_id = NULL; + new_user->real_name = NULL; + new_user->colour = NULL; + new_user->deleted = 0; + + new_user->tz = NULL; + new_user->tz_label = NULL; + new_user->tz_offset = 0; + new_user->locale = NULL; + + new_user->profile.avatar_hash = NULL; + new_user->profile.status_text = NULL; + new_user->profile.status_emoji = NULL; + new_user->profile.real_name = NULL; + new_user->profile.display_name = NULL; + new_user->profile.real_name_normalized = NULL; + new_user->profile.email = NULL; + new_user->profile.team = NULL; + new_user->updated = 0; + + new_user->is_admin = 0; + new_user->is_owner = 0; + new_user->is_primary_owner = 0; + new_user->is_restricted = 0; + new_user->is_ultra_restricted = 0; + new_user->is_bot = 0; + new_user->is_stranger = 0; + new_user->is_app_user = 0; + new_user->has_2fa = 0; + + new_user->prev_user = NULL; + new_user->next_user = NULL; + + return new_user; +} + +void slack_user_free(struct t_slack_workspace *workspace, + struct t_slack_user *user) +{ + struct t_slack_user *new_users; + + if (!workspace || !user) + return; + + /* remove user from users list */ + if (workspace->last_user == user) + workspace->last_user = user->prev_user; + if (user->prev_user) + { + (user->prev_user)->next_user = user->next_user; + new_users = workspace->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->team_id) + free(user->team_id); + if (user->real_name) + free(user->real_name); + if (user->colour) + free(user->colour); + if (user->tz) + free(user->tz); + if (user->tz_label) + free(user->tz_label); + if (user->locale) + free(user->locale); + if (user->profile.avatar_hash) + free(user->profile.avatar_hash); + if (user->profile.status_text) + free(user->profile.status_text); + if (user->profile.status_emoji) + free(user->profile.status_emoji); + if (user->profile.real_name) + free(user->profile.real_name); + if (user->profile.display_name) + free(user->profile.display_name); + if (user->profile.real_name_normalized) + free(user->profile.real_name_normalized); + if (user->profile.email) + free(user->profile.email); + if (user->profile.team) + free(user->profile.team); + + free(user); + + workspace->users = new_users; +} + +void slack_user_free_all(struct t_slack_workspace *workspace) +{ + while (workspace->users) + slack_user_free(workspace, workspace->users); +} diff --git a/slack-user.h b/slack-user.h new file mode 100644 index 0000000..7bdf5a8 --- /dev/null +++ b/slack-user.h @@ -0,0 +1,55 @@ +#ifndef _SLACK_USER_H_ +#define _SLACK_USER_H_ + +struct t_slack_user_profile +{ + char *avatar_hash; + char *status_text; + char *status_emoji; + char *real_name; + char *display_name; + char *real_name_normalized; + char *email; + char *team; +}; + +struct t_slack_user +{ + char *id; + char *name; + char *team_id; + char *real_name; + char *colour; + + int deleted; + char *tz; + char *tz_label; + int tz_offset; + char *locale; + + struct t_slack_user_profile profile; + int updated; + + int is_admin; + int is_owner; + int is_primary_owner; + int is_restricted; + int is_ultra_restricted; + int is_bot; + int is_stranger; + int is_app_user; + int has_2fa; + + struct t_slack_user *prev_user; + struct t_slack_user *next_user; +}; + +struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, + const char *id); + +struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, + const char *id); + +void slack_channel_free_all(struct t_slack_workspace *workspace); + +#endif /*SLACK_USER_H*/ diff --git a/slack-workspace.c b/slack-workspace.c index 32fcf30..fee7b14 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -12,6 +12,9 @@ #include "slack-input.h" #include "slack-workspace.h" #include "slack-api.h" +#include "slack-request.h" +#include "slack-user.h" +#include "slack-channel.h" struct t_slack_workspace *slack_workspaces = NULL; struct t_slack_workspace *last_slack_workspace = NULL; @@ -21,7 +24,7 @@ char *slack_workspace_options[SLACK_WORKSPACE_NUM_OPTIONS][2] = }; static const char *const endpoint = "/api/rtm.connect?" - "token=%s&batch_presence_aware=true&presence_sub=false"; + "token=%s&batch_presence_aware=true&presence_sub=false&"; static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) { @@ -222,7 +225,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, free(json_string); return 0; } - workspace->ws_url = strdup(json_object_get_string(url)); } else @@ -367,12 +369,17 @@ struct t_slack_workspace *slack_workspace_alloc(const char *domain) new_workspace->client_wsi = NULL; new_workspace->context = NULL; new_workspace->json_chunks = NULL; + new_workspace->requests = NULL; new_workspace->user = NULL; new_workspace->nick = NULL; new_workspace->buffer = NULL; new_workspace->buffer_as_string = NULL; + new_workspace->users = NULL; + new_workspace->last_user = NULL; + new_workspace->channels = NULL; + new_workspace->last_channel = NULL; /* create options with null value */ for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) @@ -453,10 +460,8 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace) free(workspace->uri); if (workspace->ws_url) free(workspace->ws_url); - if (workspace->client_wsi) - free(workspace->client_wsi); if (workspace->context) - free(workspace->context); + lws_context_destroy(workspace->context); while (workspace->json_chunks) { struct t_json_chunk *chunk_ptr = workspace->json_chunks->next; @@ -465,6 +470,13 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace) free(workspace->json_chunks); workspace->json_chunks = chunk_ptr; } + while (workspace->requests) + { + struct t_slack_request *request_ptr = workspace->requests->next; + + free(workspace->requests); + workspace->requests = request_ptr; + } if (workspace->user) free(workspace->user); @@ -473,6 +485,9 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace) if (workspace->buffer_as_string) free(workspace->buffer_as_string); + + slack_channel_free_all(workspace); + slack_user_free_all(workspace); } void slack_workspace_free(struct t_slack_workspace *workspace) @@ -638,7 +653,7 @@ struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *wor char buffer_name[256], charset_modifier[256]; snprintf(buffer_name, sizeof(buffer_name), - "slack.%s", workspace->domain); + "workspace.%s", workspace->domain); workspace->buffer = weechat_buffer_new(buffer_name, &slack_input_data_cb, NULL, NULL, &slack_buffer_close_cb, NULL, NULL); @@ -651,12 +666,19 @@ struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *wor weechat_buffer_set(workspace->buffer, "localvar_set_server", workspace->domain); weechat_buffer_set(workspace->buffer, "localvar_set_channel", workspace->domain); snprintf(charset_modifier, sizeof (charset_modifier), - "slack.%s", workspace->domain); + "workspace.%s", workspace->domain); weechat_buffer_set(workspace->buffer, "localvar_set_charset_modifier", charset_modifier); weechat_buffer_set(workspace->buffer, "title", (workspace->name) ? workspace->name : ""); + weechat_buffer_set(workspace->buffer, "nicklist", "1"); + weechat_buffer_set(workspace->buffer, "nicklist_display_groups", "0"); + weechat_buffer_set_pointer(workspace->buffer, "nicklist_callback", + &slack_buffer_nickcmp_cb); + weechat_buffer_set_pointer(workspace->buffer, "nicklist_callback_pointer", + workspace); + return workspace->buffer; } @@ -749,6 +771,7 @@ int slack_workspace_connect(struct t_slack_workspace *workspace) int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls) { struct t_slack_workspace *ptr_workspace; + struct t_slack_request *ptr_request; /* make C compiler happy */ (void) pointer; @@ -761,6 +784,25 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call if (!ptr_workspace->is_connected) continue; + for (ptr_request = ptr_workspace->requests; ptr_request; + ptr_request = ptr_request->next) + { + if (ptr_request->client_wsi) + { + lws_service(ptr_request->context, 0); + } + else if (ptr_request->context) + { + lws_context_destroy(ptr_request->context); + ptr_request->context = NULL; + if (ptr_request->uri) + { + free(ptr_request->uri); + ptr_request->uri = NULL; + } + } + } + if (ptr_workspace->client_wsi) { lws_service(ptr_workspace->context, 0); @@ -785,3 +827,11 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call return WEECHAT_RC_OK; } + +void slack_workspace_register_request(struct t_slack_workspace *workspace, + struct t_slack_request *request) +{ + struct t_slack_request *new_tail = workspace->requests; + workspace->requests = request; + workspace->requests->next = new_tail; +} diff --git a/slack-workspace.h b/slack-workspace.h index 216eeb7..8ce6f53 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -34,12 +34,17 @@ struct t_slack_workspace struct lws *client_wsi; struct lws_context *context; struct t_json_chunk *json_chunks; + struct t_slack_request *requests; char *user; char *nick; struct t_gui_buffer *buffer; char *buffer_as_string; + struct t_slack_user *users; + struct t_slack_user *last_user; + struct t_slack_channel *channels; + struct t_slack_channel *last_channel; struct t_slack_workspace *prev_workspace; struct t_slack_workspace *next_workspace; }; @@ -59,5 +64,7 @@ void slack_workspace_disconnect_all(); void slack_workspace_close_connection(struct t_slack_workspace *workspace); int slack_workspace_connect(struct t_slack_workspace *workspace); int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls); +void slack_workspace_register_request(struct t_slack_workspace *workspace, + struct t_slack_request *request); #endif /*SLACK_WORKSPACE_H*/ diff --git a/slack.c b/slack.c index 528e4b1..c1cee92 100644 --- a/slack.c +++ b/slack.c @@ -2,12 +2,14 @@ #include #include #include +#include #include "weechat-plugin.h" #include "slack.h" #include "slack-config.h" #include "slack-command.h" #include "slack-workspace.h" +#include "slack-api.h" WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME); @@ -15,7 +17,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Slack (slack.com) protocol")); WEECHAT_PLUGIN_AUTHOR("Tony Olagbaiye "); WEECHAT_PLUGIN_VERSION(SLACK_PLUGIN_VERSION); WEECHAT_PLUGIN_LICENSE("MPL2"); -WEECHAT_PLUGIN_PRIORITY(6000); +WEECHAT_PLUGIN_PRIORITY(5500); struct t_weechat_plugin *weechat_slack_plugin = NULL; @@ -52,6 +54,8 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) slack_command_init(); + slack_api_init(); + slack_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, &slack_workspace_timer_cb, NULL, NULL); From 346a5fd71de99a5b9a07308acdad062a235434fa Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 2 May 2018 16:55:41 +0100 Subject: [PATCH 006/118] pagination --- request/slack-request-channels-list.c | 60 +++++++++++++----- request/slack-request-users-list.c | 88 ++++++++++++++++++++------- slack-channel.c | 31 ++++++++-- slack-channel.h | 5 +- slack-request.c | 1 + slack-request.h | 5 +- slack-user.c | 43 +++++++++++-- slack-user.h | 5 +- slack-workspace.c | 60 +++++++++++++----- slack-workspace.h | 2 + 10 files changed, 234 insertions(+), 66 deletions(-) diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index d5c948c..d829a97 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -12,7 +12,7 @@ static const char *const endpoint = "/api/channels.list?" "token=%s&cursor=%s&" - "exclude_archived=false&exclude_members=true&limit=0"; + "exclude_archived=false&exclude_members=true&limit=20"; static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) { @@ -42,8 +42,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: weechat_printf( request->workspace->buffer, - _("%s%s: error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, in ? (char *)in : "(null)"); request->client_wsi = NULL; break; @@ -52,8 +52,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, status = lws_http_client_http_response(wsi); weechat_printf( request->workspace->buffer, - _("%s%s: retrieving channels... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) retrieving channels... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, status); break; @@ -98,8 +98,9 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, { int chunk_count, i; char *json_string; - json_object *response, *ok, *error, *channels; - json_object *channel, *id, *name, *topic; + char cursor[64]; + json_object *response, *ok, *error, *channels, *metadata; + json_object *channel, *id, *name, *topic, *next_cursor; struct t_json_chunk *chunk_ptr; chunk_count = 0; @@ -129,8 +130,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( request->workspace->buffer, - _("%s%s: got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, json_string); response = json_tokener_parse(json_string); @@ -194,6 +195,35 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_get_string(id), json_object_get_string(name)); } + + metadata = json_object_object_get(response, "response_metadata"); + if (!json_valid(metadata, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + next_cursor = json_object_object_get(metadata, "next_cursor"); + if (!json_valid(next_cursor, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor)); + + if (cursor[0]) + { + struct t_slack_request *next_request; + + next_request = slack_request_channels_list(request->workspace, + weechat_config_string( + request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + cursor); + if (next_request) + slack_workspace_register_request(request->workspace, next_request); + } } else { @@ -207,8 +237,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( request->workspace->buffer, - _("%s%s: failed to retrieve channels: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) failed to retrieve channels: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, json_object_get_string(error)); } @@ -261,16 +291,16 @@ struct t_slack_request *slack_request_channels_list( { weechat_printf( workspace->buffer, - _("%s%s: error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); return NULL; } else { weechat_printf( workspace->buffer, - _("%s%s: contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); } memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index 3b85506..f8bc4a6 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -7,11 +7,12 @@ #include "../slack.h" #include "../slack-workspace.h" #include "../slack-request.h" +#include "../slack-user.h" #include "../request/slack-request-users-list.h" static const char *const endpoint = "/api/users.list?" "token=%s&cursor=%s&" - "exclude_archived=false&exclude_members=true&limit=0"; + "exclude_archived=false&exclude_members=true&limit=20"; static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) { @@ -41,8 +42,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: weechat_printf( request->workspace->buffer, - _("%s%s: error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, in ? (char *)in : "(null)"); request->client_wsi = NULL; break; @@ -51,8 +52,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, status = lws_http_client_http_response(wsi); weechat_printf( request->workspace->buffer, - _("%s%s: retrieving users... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) retrieving users... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, status); break; @@ -97,8 +98,9 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, { int chunk_count, i; char *json_string; - json_object *response, *ok, *error, *members; - json_object *user, *id, *name; + char cursor[64]; + json_object *response, *ok, *error, *members, *metadata; + json_object *user, *id, *name, *profile, *display_name, *next_cursor; struct t_json_chunk *chunk_ptr; chunk_count = 0; @@ -128,8 +130,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( request->workspace->buffer, - _("%s%s: got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, json_string); response = json_tokener_parse(json_string); @@ -153,6 +155,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, for (i = json_object_array_length(members); i > 0; i--) { + struct t_slack_user *new_user; + user = json_object_array_get_idx(members, i - 1); if (!json_valid(user, request->workspace)) { @@ -177,12 +181,54 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, return 0; } - weechat_printf( - request->workspace->buffer, - _("%s%s: got user: %s (%s)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - json_object_get_string(name), - json_object_get_string(id)); + profile = json_object_object_get(user, "profile"); + if (!json_valid(profile, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + display_name = json_object_object_get(profile, "display_name"); + if (!json_valid(display_name, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + new_user = slack_user_new(request->workspace, + json_object_get_string(id), + json_object_get_string(display_name)); + } + + metadata = json_object_object_get(response, "response_metadata"); + if (!json_valid(metadata, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + next_cursor = json_object_object_get(metadata, "next_cursor"); + if (!json_valid(next_cursor, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor)); + + if (cursor[0]) + { + struct t_slack_request *next_request; + + next_request = slack_request_users_list(request->workspace, + weechat_config_string( + request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + cursor); + if (next_request) + slack_workspace_register_request(request->workspace, next_request); } } else @@ -197,8 +243,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, weechat_printf( request->workspace->buffer, - _("%s%s: failed to retrieve users: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + _("%s%s: (%d) failed to retrieve users: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, json_object_get_string(error)); } @@ -251,16 +297,16 @@ struct t_slack_request *slack_request_users_list( { weechat_printf( workspace->buffer, - _("%s%s: error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); return NULL; } else { weechat_printf( workspace->buffer, - _("%s%s: contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); } memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ diff --git a/slack-channel.c b/slack-channel.c index 4b855d6..7fdad3e 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -152,6 +152,29 @@ struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *works return ptr_buffer; } +void slack_channel_add_nicklist_groups(struct t_slack_workspace *workspace, + struct t_slack_channel *channel) +{ + struct t_gui_buffer *ptr_buffer; + char str_group[32]; + + if (channel && channel->type == SLACK_CHANNEL_TYPE_MPIM) + return; + if (channel && channel->type == SLACK_CHANNEL_TYPE_IM) + return; + + ptr_buffer = channel ? channel->buffer : workspace->buffer; + + snprintf(str_group, sizeof(str_group), "%03d|%s", + 000, "+"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", + 999, "..."); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); +} + struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, enum t_slack_channel_type type, const char *id, const char *name) @@ -159,7 +182,7 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, struct t_slack_channel *new_channel, *ptr_channel; struct t_gui_buffer *ptr_buffer; - if (!workspace || !id) + if (!workspace || !id || !name || !name[0]) return NULL; ptr_channel = slack_channel_search(workspace, id); @@ -206,12 +229,12 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, new_channel->buffer = ptr_buffer; new_channel->buffer_as_string = NULL; - new_channel->prev_channel = NULL; - new_channel->next_channel = NULL; - new_channel->prev_channel = workspace->last_channel; + new_channel->next_channel = NULL; if (workspace->last_channel) (workspace->last_channel)->next_channel = new_channel; + else + workspace->channels = new_channel; workspace->last_channel = new_channel; return new_channel; diff --git a/slack-channel.h b/slack-channel.h index b9b46b5..56c11a6 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -71,10 +71,13 @@ struct t_slack_channel struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace, const char *id); +void slack_channel_add_nicklist_groups(struct t_slack_workspace *workspace, + struct t_slack_channel *channel); + struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, enum t_slack_channel_type type, const char *id, const char *name); -void slack_user_free_all(struct t_slack_workspace *workspace); +void slack_channel_free_all(struct t_slack_workspace *workspace); #endif /*SLACK_CHANNEL_H*/ diff --git a/slack-request.c b/slack-request.c index 6db1816..55343aa 100644 --- a/slack-request.c +++ b/slack-request.c @@ -17,6 +17,7 @@ struct t_slack_request *slack_request_alloc( memset(request, 0, sizeof(struct t_slack_request)); request->workspace = workspace; + request->idx = workspace->idx++; return request; } diff --git a/slack-request.h b/slack-request.h index 21abf8b..9416a71 100644 --- a/slack-request.h +++ b/slack-request.h @@ -5,12 +5,15 @@ struct t_slack_request { struct t_slack_workspace *workspace; + int idx; + char *uri; struct lws *client_wsi; struct lws_context *context; struct t_json_chunk *json_chunks; - struct t_slack_request *next; + struct t_slack_request *prev_request; + struct t_slack_request *next_request; }; struct t_slack_request *slack_request_alloc( diff --git a/slack-user.c b/slack-user.c index c093b97..b78184c 100644 --- a/slack-user.c +++ b/slack-user.c @@ -5,6 +5,7 @@ #include "slack.h" #include "slack-workspace.h" #include "slack-user.h" +#include "slack-channel.h" struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, const char *id) @@ -24,17 +25,43 @@ struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, return NULL; } +void slack_user_nicklist_add(struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + struct t_slack_user *user) +{ + struct t_gui_nick_group *ptr_group; + struct t_gui_buffer *ptr_buffer; + + ptr_buffer = channel ? channel->buffer : workspace->buffer; + + ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, + user->is_away ? + "+" : "..."); + weechat_nicklist_add_nick(ptr_buffer, ptr_group, + user->profile.display_name, + weechat_color(user->is_away ? + "weechat.color.nicklist_away" : + "bar_fg"), + user->is_away ? "+" : "", + weechat_color(""), + 1); +} + struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, - const char *id) + const char *id, const char *display_name) { struct t_slack_user *new_user, *ptr_user; - if (!workspace || !id) + if (!workspace || !id || !display_name || !display_name[0]) return NULL; + if (!workspace->users) + slack_channel_add_nicklist_groups(workspace, NULL); + ptr_user = slack_user_search(workspace, id); if (ptr_user) { + slack_user_nicklist_add(workspace, NULL, ptr_user); return ptr_user; } @@ -42,7 +69,11 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, return NULL; new_user->prev_user = workspace->last_user; - (workspace->last_user)->next_user = new_user; + new_user->next_user = NULL; + if (workspace->last_user) + (workspace->last_user)->next_user = new_user; + else + workspace->users = new_user; workspace->last_user = new_user; new_user->id = strdup(id); @@ -61,11 +92,12 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, new_user->profile.status_text = NULL; new_user->profile.status_emoji = NULL; new_user->profile.real_name = NULL; - new_user->profile.display_name = NULL; + new_user->profile.display_name = strdup(display_name); new_user->profile.real_name_normalized = NULL; new_user->profile.email = NULL; new_user->profile.team = NULL; new_user->updated = 0; + new_user->is_away = 0; new_user->is_admin = 0; new_user->is_owner = 0; @@ -77,8 +109,7 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, new_user->is_app_user = 0; new_user->has_2fa = 0; - new_user->prev_user = NULL; - new_user->next_user = NULL; + slack_user_nicklist_add(workspace, NULL, new_user); return new_user; } diff --git a/slack-user.h b/slack-user.h index 7bdf5a8..ecf6944 100644 --- a/slack-user.h +++ b/slack-user.h @@ -29,6 +29,7 @@ struct t_slack_user struct t_slack_user_profile profile; int updated; + int is_away; int is_admin; int is_owner; @@ -48,8 +49,8 @@ struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, const char *id); struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, - const char *id); + const char *id, const char *display_name); -void slack_channel_free_all(struct t_slack_workspace *workspace); +void slack_user_free_all(struct t_slack_workspace *workspace); #endif /*SLACK_USER_H*/ diff --git a/slack-workspace.c b/slack-workspace.c index fee7b14..ee0c3ca 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -364,12 +364,14 @@ struct t_slack_workspace *slack_workspace_alloc(const char *domain) new_workspace->is_connected = 0; new_workspace->disconnected = 0; + new_workspace->idx = 0; new_workspace->uri = NULL; new_workspace->ws_url = NULL; new_workspace->client_wsi = NULL; new_workspace->context = NULL; new_workspace->json_chunks = NULL; new_workspace->requests = NULL; + new_workspace->last_request = NULL; new_workspace->user = NULL; new_workspace->nick = NULL; @@ -433,8 +435,9 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace) } slack_redirect_free_all(workspace); slack_notify_free_all(workspace); - slack_channel_free_all(workspace); */ + slack_channel_free_all(workspace); + slack_user_free_all(workspace); /* free hashtables */ /* @@ -472,8 +475,19 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace) } while (workspace->requests) { - struct t_slack_request *request_ptr = workspace->requests->next; + struct t_slack_request *request_ptr = workspace->requests->next_request; + workspace->requests->client_wsi = NULL; + if (workspace->requests->context) + { + lws_context_destroy(workspace->requests->context); + workspace->requests->context = NULL; + if (workspace->requests->uri) + { + free(workspace->requests->uri); + workspace->requests->uri = NULL; + } + } free(workspace->requests); workspace->requests = request_ptr; } @@ -548,28 +562,19 @@ void slack_workspace_disconnect(struct t_slack_workspace *workspace, * remove all nicks and write disconnection message on each * channel/private buffer */ - /* + slack_user_free_all(workspace); for (ptr_channel = workspace->channels; ptr_channel; ptr_channel = ptr_channel->next_channel) { - slack_nick_free_all(workspace, ptr_channel); - if (ptr_channel->hook_autorejoin) - { - weechat_unhook(ptr_channel->hook_autorejoin); - ptr_channel->hook_autorejoin = NULL; - } - weechat_buffer_set(ptr_channel->buffer, "localvar_del_away", ""); weechat_printf( ptr_channel->buffer, _("%s%s: disconnected from workspace"), weechat_prefix("network"), SLACK_PLUGIN_NAME); } - */ /* remove away status on workspace buffer */ //weechat_buffer_set(workspace->buffer, "localvar_del_away", ""); } - /* slack_workspace_close_connection(workspace); if (workspace->buffer) @@ -580,6 +585,7 @@ void slack_workspace_disconnect(struct t_slack_workspace *workspace, weechat_prefix ("network"), SLACK_PLUGIN_NAME); } + /* workspace->current_retry = 0; if (switch_address) @@ -785,7 +791,7 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call continue; for (ptr_request = ptr_workspace->requests; ptr_request; - ptr_request = ptr_request->next) + ptr_request = ptr_request->next_request) { if (ptr_request->client_wsi) { @@ -793,6 +799,8 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call } else if (ptr_request->context) { + struct t_slack_request *new_requests; + lws_context_destroy(ptr_request->context); ptr_request->context = NULL; if (ptr_request->uri) @@ -800,6 +808,22 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call free(ptr_request->uri); ptr_request->uri = NULL; } + + /* remove request from requests list */ + if (ptr_workspace->last_request == ptr_request) + ptr_workspace->last_request = ptr_request->prev_request; + if (ptr_request->prev_request) + { + (ptr_request->prev_request)->next_request = ptr_request->next_request; + new_requests = ptr_workspace->requests; + } + else + new_requests = ptr_request->next_request; + + if (ptr_request->next_request) + (ptr_request->next_request)->prev_request = ptr_request->prev_request; + + ptr_workspace->requests = new_requests; } } @@ -831,7 +855,11 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call void slack_workspace_register_request(struct t_slack_workspace *workspace, struct t_slack_request *request) { - struct t_slack_request *new_tail = workspace->requests; - workspace->requests = request; - workspace->requests->next = new_tail; + request->prev_request = workspace->last_request; + request->next_request = NULL; + if (workspace->last_request) + (workspace->last_request)->next_request = request; + else + workspace->requests = request; + workspace->last_request = request; } diff --git a/slack-workspace.h b/slack-workspace.h index 8ce6f53..dc1f773 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -29,12 +29,14 @@ struct t_slack_workspace int is_connected; int disconnected; + int idx; char *uri; char *ws_url; struct lws *client_wsi; struct lws_context *context; struct t_json_chunk *json_chunks; struct t_slack_request *requests; + struct t_slack_request *last_request; char *user; char *nick; From 44915eb1b6e6800606bba5c1be30aa7fbb9b1067 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 2 May 2018 23:16:20 +0100 Subject: [PATCH 007/118] implement message subtype routing --- Makefile | 2 + api/message/slack-api-message-unimplemented.c | 45 +++++ api/message/slack-api-message-unimplemented.h | 8 + api/slack-api-message.c | 166 ++++++++++++++++++ api/slack-api-message.h | 9 + request/slack-request-channels-list.c | 5 +- request/slack-request-users-list.c | 5 +- slack-api.c | 21 ++- slack-buffer.c | 2 +- slack-channel.c | 6 +- slack-channel.h | 2 + slack-oauth.c | 3 +- slack-teaminfo.c | 3 +- slack-workspace.c | 45 ++++- slack-workspace.h | 2 +- 15 files changed, 309 insertions(+), 15 deletions(-) create mode 100644 api/message/slack-api-message-unimplemented.c create mode 100644 api/message/slack-api-message-unimplemented.h create mode 100644 api/slack-api-message.c create mode 100644 api/slack-api-message.h diff --git a/Makefile b/Makefile index 1098b37..6e0eb15 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,8 @@ SRCS=slack.c \ slack-workspace.c \ api/slack-api-hello.c \ api/slack-api-error.c \ + api/slack-api-message.c \ + api/message/slack-api-message-unimplemented.c \ request/slack-request-channels-list.c \ request/slack-request-users-list.c OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a diff --git a/api/message/slack-api-message-unimplemented.c b/api/message/slack-api-message-unimplemented.c new file mode 100644 index 0000000..fb66ebd --- /dev/null +++ b/api/message/slack-api-message-unimplemented.c @@ -0,0 +1,45 @@ +#include +#include + +#include "../../weechat-plugin.h" +#include "../../slack.h" +#include "../../slack-workspace.h" +#include "../../slack-api.h" +#include "../../slack-channel.h" +#include "../../slack-user.h" +#include "../slack-api-message.h" + +static const char *subtype = "unimplemented"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %smessage.%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), subtype, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_unimplemented(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *subtype = json_object_object_get(message, "subtype"); + if (!json_valid(subtype, workspace)) + return 0; + + weechat_printf( + workspace->buffer, + _("%s%s: got unhandled message of type: message.%s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_object_get_string(subtype)); + + return 1; +} + diff --git a/api/message/slack-api-message-unimplemented.h b/api/message/slack-api-message-unimplemented.h new file mode 100644 index 0000000..b83b4d8 --- /dev/null +++ b/api/message/slack-api-message-unimplemented.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_API_MESSAGE_UNIMPLEMENTED_H_ +#define _SLACK_API_MESSAGE_UNIMPLEMENTED_H_ + +int slack_api_message_unimplemented( + struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_MESSAGE_UNIMPLEMENTED_H*/ diff --git a/api/slack-api-message.c b/api/slack-api-message.c new file mode 100644 index 0000000..fb385ca --- /dev/null +++ b/api/slack-api-message.c @@ -0,0 +1,166 @@ +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-api.h" +#include "../slack-channel.h" +#include "../slack-user.h" +#include "slack-api-message.h" +#include "message/slack-api-message-unimplemented.h" + +static const char *type = "message"; + +struct stringcase +{ + const char *string; + int (*func)(struct t_slack_workspace *workspace, + json_object *message); +}; + +static struct stringcase cases[] = +{ { "bot_message", &slack_api_message_unimplemented } +, { "channel_archive", &slack_api_message_unimplemented } +, { "channel_join", &slack_api_message_unimplemented } +, { "channel_leave", &slack_api_message_unimplemented } +, { "channel_name", &slack_api_message_unimplemented } +, { "channel_purpose", &slack_api_message_unimplemented } +, { "channel_topic", &slack_api_message_unimplemented } +, { "channel_unarchive", &slack_api_message_unimplemented } +, { "file_comment", &slack_api_message_unimplemented } +, { "file_mention", &slack_api_message_unimplemented } +, { "file_share", &slack_api_message_unimplemented } +, { "group_archive", &slack_api_message_unimplemented } +, { "group_join", &slack_api_message_unimplemented } +, { "group_leave", &slack_api_message_unimplemented } +, { "group_name", &slack_api_message_unimplemented } +, { "group_purpose", &slack_api_message_unimplemented } +, { "group_topic", &slack_api_message_unimplemented } +, { "group_unarchive", &slack_api_message_unimplemented } +, { "me_message", &slack_api_message_unimplemented } +, { "message_changed", &slack_api_message_unimplemented } +, { "message_deleted", &slack_api_message_unimplemented } +, { "message_replied", &slack_api_message_unimplemented } +, { "pinned_item", &slack_api_message_unimplemented } +, { "reply_broadcast", &slack_api_message_unimplemented } +, { "thread_broadcast", &slack_api_message_unimplemented } +, { "unpinned_item", &slack_api_message_unimplemented } +}; + +static int stringcase_cmp(const void *p1, const void *p2) +{ + return strcasecmp(((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string); +} + +void slack_api_message_init() +{ + size_t case_count = sizeof(cases) / sizeof(cases[0]); + qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); +} + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %s%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), type, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_message_handle(struct t_slack_workspace *workspace, + const char *channel, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + + (void) ts; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; /* silently ignore if user hasn't been loaded yet */ + + weechat_printf( + workspace->buffer, + _("%s%s: message [%s]: <%s> %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + ptr_channel->name, ptr_user->profile.display_name, text); + + return 1; +} + +int slack_api_message_route_message(struct t_slack_workspace *workspace, + const char *subtype, + json_object *message) +{ + struct stringcase key; + key.string = type; + + size_t case_count = sizeof(cases) / sizeof(cases[0]); + void *entry_ptr = bsearch(&key, cases, case_count, + sizeof(struct stringcase), stringcase_cmp); + + if (entry_ptr) + { + struct stringcase *entry = (struct stringcase *)entry_ptr; + return (*entry->func)(workspace, message); + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: got unhandled message of type: message.%s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + subtype); + return 1; + } +} + +int slack_api_message(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *subtype, *channel, *user, *text, *ts; + + subtype = json_object_object_get(message, "subtype"); + if (!subtype) + { /* normal message */ + channel = json_object_object_get(message, "channel"); + if (!json_valid(channel, workspace)) + return 0; + + user = json_object_object_get(message, "user"); + if (!json_valid(user, workspace)) + return 0; + + text = json_object_object_get(message, "text"); + if (!json_valid(text, workspace)) + return 0; + + ts = json_object_object_get(message, "ts"); + if (!json_valid(ts, workspace)) + return 0; + + return slack_api_message_message_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user), + json_object_get_string(text), + json_object_get_string(ts)); + } + else + { /* special message */ + return slack_api_message_route_message(workspace, + json_object_get_string(subtype), + message); + } +} diff --git a/api/slack-api-message.h b/api/slack-api-message.h new file mode 100644 index 0000000..eed80e3 --- /dev/null +++ b/api/slack-api-message.h @@ -0,0 +1,9 @@ +#ifndef _SLACK_API_MESSAGE_H_ +#define _SLACK_API_MESSAGE_H_ + +int slack_api_message(struct t_slack_workspace *workspace, + json_object *message); + +void slack_api_message_init(); + +#endif /*SLACK_API_MESSAGE_H*/ diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index d829a97..6227875 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -22,7 +22,7 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work workspace->buffer, _("%s%s: error retrieving channels: unexpected response from server"), weechat_prefix("error"), SLACK_PLUGIN_NAME); - __asm__("int3"); + //__asm__("int3"); return 0; } @@ -247,7 +247,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, } case LWS_CALLBACK_CLOSED_CLIENT_HTTP: request->client_wsi = NULL; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ break; default: diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index f8bc4a6..d0e051a 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -22,7 +22,7 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work workspace->buffer, _("%s%s: error retrieving users: unexpected response from server"), weechat_prefix("error"), SLACK_PLUGIN_NAME); - __asm__("int3"); + //__asm__("int3"); return 0; } @@ -253,7 +253,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, } case LWS_CALLBACK_CLOSED_CLIENT_HTTP: request->client_wsi = NULL; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ break; default: diff --git a/slack-api.c b/slack-api.c index ff92721..4492d18 100644 --- a/slack-api.c +++ b/slack-api.c @@ -9,6 +9,7 @@ #include "slack-api.h" #include "api/slack-api-hello.h" #include "api/slack-api-error.h" +#include "api/slack-api-message.h" struct stringcase { @@ -18,8 +19,9 @@ struct stringcase }; struct stringcase cases[] = -{ { "hello", slack_api_hello } -, { "error", slack_api_error } +{ { "hello", &slack_api_hello } +, { "error", &slack_api_error } +, { "message", &slack_api_message } }; static int stringcase_cmp(const void *p1, const void *p2) @@ -80,6 +82,9 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, workspace->buffer, _("%s%s: unexpected data received from websocket: closing"), weechat_prefix("error"), SLACK_PLUGIN_NAME); + + slack_workspace_disconnect(workspace, 0); + json_object_put(response); free(json_string); return -1; @@ -88,6 +93,18 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, if (!slack_api_route_message(workspace, json_object_get_string(type), response)) { + weechat_printf( + workspace->buffer, + _("%s%s: error while handling message: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_string); + weechat_printf( + workspace->buffer, + _("%s%s: closing connection."), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + + slack_workspace_disconnect(workspace, 0); + json_object_put(response); free(json_string); return -1; diff --git a/slack-buffer.c b/slack-buffer.c index 40d49c0..04ff85e 100644 --- a/slack-buffer.c +++ b/slack-buffer.c @@ -87,7 +87,7 @@ int slack_buffer_close_cb(const void *pointer, void *data, if (!ptr_workspace->disconnected) { //slack_command_quit_workspace(ptr_workspace, NULL); - slack_workspace_disconnect(ptr_workspace, 0, 0); + slack_workspace_disconnect(ptr_workspace, 0); } ptr_workspace->buffer = NULL; diff --git a/slack-channel.c b/slack-channel.c index 7fdad3e..d6255e2 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -181,6 +181,7 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, { struct t_slack_channel *new_channel, *ptr_channel; struct t_gui_buffer *ptr_buffer; + char buffer_name[SLACK_CHANNEL_NAME_MAX_LEN + 2]; if (!workspace || !id || !name || !name[0]) return NULL; @@ -191,7 +192,10 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, return ptr_channel; } - ptr_buffer = slack_channel_create_buffer(workspace, type, name); + buffer_name[0] = '#'; + strncpy(&buffer_name[1], name, SLACK_CHANNEL_NAME_MAX_LEN + 1); + + ptr_buffer = slack_channel_create_buffer(workspace, type, buffer_name); if (!ptr_buffer) return NULL; diff --git a/slack-channel.h b/slack-channel.h index 56c11a6..f5892be 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -1,6 +1,8 @@ #ifndef _SLACK_CHANNEL_H_ #define _SLACK_CHANNEL_H_ +#define SLACK_CHANNEL_NAME_MAX_LEN 22 + enum t_slack_channel_type { SLACK_CHANNEL_TYPE_CHANNEL, diff --git a/slack-oauth.c b/slack-oauth.c index ca46285..5bd2845 100644 --- a/slack-oauth.c +++ b/slack-oauth.c @@ -135,7 +135,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: case LWS_CALLBACK_CLOSED_CLIENT_HTTP: client_wsi = NULL; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ break; default: diff --git a/slack-teaminfo.c b/slack-teaminfo.c index 431bfd7..ba1347e 100644 --- a/slack-teaminfo.c +++ b/slack-teaminfo.c @@ -230,7 +230,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, } case LWS_CALLBACK_CLOSED_CLIENT_HTTP: client_wsi = NULL; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ break; default: diff --git a/slack-workspace.c b/slack-workspace.c index ee0c3ca..8438fba 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -249,7 +249,8 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, } case LWS_CALLBACK_CLOSED_CLIENT_HTTP: workspace->client_wsi = NULL; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ break; default: @@ -548,9 +549,8 @@ void slack_workspace_free_all() } void slack_workspace_disconnect(struct t_slack_workspace *workspace, - int switch_address, int reconnect) + int reconnect) { - (void) switch_address; (void) reconnect; struct t_slack_channel *ptr_channel; @@ -563,9 +563,11 @@ void slack_workspace_disconnect(struct t_slack_workspace *workspace, * channel/private buffer */ slack_user_free_all(workspace); + weechat_nicklist_remove_all(workspace->buffer); for (ptr_channel = workspace->channels; ptr_channel; ptr_channel = ptr_channel->next_channel) { + weechat_nicklist_remove_all(ptr_channel->buffer); weechat_printf( ptr_channel->buffer, _("%s%s: disconnected from workspace"), @@ -650,7 +652,7 @@ void slack_workspace_disconnect_all() for (ptr_workspace = slack_workspaces; ptr_workspace; ptr_workspace = ptr_workspace->next_workspace) { - slack_workspace_disconnect(ptr_workspace, 0, 0); + slack_workspace_disconnect(ptr_workspace, 0); } } @@ -690,9 +692,44 @@ struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *wor void slack_workspace_close_connection(struct t_slack_workspace *workspace) { + struct t_slack_request *ptr_request; + workspace->is_connected = 0; workspace->client_wsi = NULL; workspace->context = NULL; + + for (ptr_request = workspace->requests; ptr_request; + ptr_request = ptr_request->next_request) + { + if (ptr_request->context) + { + struct t_slack_request *new_requests; + + lws_context_destroy(ptr_request->context); + ptr_request->context = NULL; + if (ptr_request->uri) + { + free(ptr_request->uri); + ptr_request->uri = NULL; + } + + /* remove request from requests list */ + if (workspace->last_request == ptr_request) + workspace->last_request = ptr_request->prev_request; + if (ptr_request->prev_request) + { + (ptr_request->prev_request)->next_request = ptr_request->next_request; + new_requests = workspace->requests; + } + else + new_requests = ptr_request->next_request; + + if (ptr_request->next_request) + (ptr_request->next_request)->prev_request = ptr_request->prev_request; + + workspace->requests = new_requests; + } + } } void slack_workspace_websocket_create(struct t_slack_workspace *workspace) diff --git a/slack-workspace.h b/slack-workspace.h index dc1f773..9861ab9 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -61,7 +61,7 @@ void slack_workspace_free_data(struct t_slack_workspace *workspace); void slack_workspace_free(struct t_slack_workspace *workspace); void slack_workspace_free_all(); void slack_workspace_disconnect(struct t_slack_workspace *workspace, - int switch_address, int reconnect); + int reconnect); void slack_workspace_disconnect_all(); void slack_workspace_close_connection(struct t_slack_workspace *workspace); int slack_workspace_connect(struct t_slack_workspace *workspace); From 22f22a0aeef65567a8ced0f0f98c71cdc1f3aad3 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 4 May 2018 01:31:06 +0100 Subject: [PATCH 008/118] frankly i'm not sure --- .gitignore | 1 + Makefile | 14 +- api/slack-api-message.c | 17 +- request/slack-request-chat-postmessage.c | 244 +++++++++++++++++++++++ request/slack-request-chat-postmessage.h | 9 + slack-api.c | 4 +- slack-buffer.c | 2 +- slack-buffer.h | 4 + slack-input.c | 57 +++++- slack-message.c | 139 +++++++++++++ slack-message.h | 9 + slack-user.c | 20 ++ slack-user.h | 3 + slack-workspace.c | 2 +- slack.c | 2 +- 15 files changed, 512 insertions(+), 15 deletions(-) create mode 100644 request/slack-request-chat-postmessage.c create mode 100644 request/slack-request-chat-postmessage.h create mode 100644 slack-message.c create mode 100644 slack-message.h diff --git a/.gitignore b/.gitignore index 4e9fb6b..771d19f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Prerequisites +cscope* .depend *.d diff --git a/Makefile b/Makefile index 6e0eb15..ee1280a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC=clang CXX=clang++ RM=rm -f -CFLAGS=-fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c -LDFLAGS=-shared -g +CFLAGS=-fsanitize=address -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c +LDFLAGS=-shared -g -fsanitize=address LDLIBS=-lgnutls SRCS=slack.c \ @@ -12,6 +12,7 @@ SRCS=slack.c \ slack-config.c \ slack-command.c \ slack-input.c \ + slack-message.c \ slack-oauth.c \ slack-request.c \ slack-teaminfo.c \ @@ -21,6 +22,7 @@ SRCS=slack.c \ api/slack-api-error.c \ api/slack-api-message.c \ api/message/slack-api-message-unimplemented.c \ + request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ request/slack-request-users-list.c OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a @@ -52,4 +54,12 @@ clean: distclean: clean $(RM) *~ .depend +.PHONY: tags cs + +tags: + ctags -f .git/tags -R *.c *.h + +cs: + cscope -RUbq + include .depend diff --git a/api/slack-api-message.c b/api/slack-api-message.c index fb385ca..3ea0514 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -7,6 +7,7 @@ #include "../slack-api.h" #include "../slack-channel.h" #include "../slack-user.h" +#include "../slack-message.h" #include "slack-api-message.h" #include "message/slack-api-message-unimplemented.h" @@ -82,8 +83,6 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, struct t_slack_channel *ptr_channel; struct t_slack_user *ptr_user; - (void) ts; - ptr_channel = slack_channel_search(workspace, channel); if (!ptr_channel) return 1; /* silently ignore if channel hasn't been loaded yet */ @@ -91,11 +90,15 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, if (!ptr_user) return 1; /* silently ignore if user hasn't been loaded yet */ - weechat_printf( - workspace->buffer, - _("%s%s: message [%s]: <%s> %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - ptr_channel->name, ptr_user->profile.display_name, text); + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message", + _("%s%s"), + slack_user_as_prefix(workspace, ptr_user), + message); + free(message); return 1; } diff --git a/request/slack-request-chat-postmessage.c b/request/slack-request-chat-postmessage.c new file mode 100644 index 0000000..d795a9c --- /dev/null +++ b/request/slack-request-chat-postmessage.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-request.h" +#include "../slack-user.h" +#include "../request/slack-request-chat-postmessage.h" + +static const char *const endpoint = "/api/chat.postMessage?" + "token=%s&channel=%s&text=%s&" + "as_user=true&link_names=true&mrkdwn=false&parse=full"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error posting message: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + //__asm__("int3"); + return 0; + } + + return 1; +} + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + in ? (char *)in : "(null)"); + request->client_wsi = NULL; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) posting message... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + /* wait for websocket to catch up */ + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) failed to post message: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_chat_postmessage( + struct t_slack_workspace *workspace, + const char *token, const char *channel, + const char *text) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + + size_t urilen = snprintf(NULL, 0, endpoint, token, channel, text) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token, channel, text); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-chat-postmessage.h b/request/slack-request-chat-postmessage.h new file mode 100644 index 0000000..48d31fc --- /dev/null +++ b/request/slack-request-chat-postmessage.h @@ -0,0 +1,9 @@ +#ifndef _SLACK_REQUEST_CHAT_POSTMESSAGE_H_ +#define _SLACK_REQUEST_CHAT_POSTMESSAGE_H_ + +struct t_slack_request *slack_request_chat_postmessage( + struct t_slack_workspace *workspace, + const char *token, const char *channel, + const char *text); + +#endif /*SLACK_REQUEST_CHAT_POSTMESSAGE_H*/ diff --git a/slack-api.c b/slack-api.c index 4492d18..2314951 100644 --- a/slack-api.c +++ b/slack-api.c @@ -18,7 +18,7 @@ struct stringcase json_object *message); }; -struct stringcase cases[] = +static struct stringcase cases[] = { { "hello", &slack_api_hello } , { "error", &slack_api_error } , { "message", &slack_api_message } @@ -33,6 +33,8 @@ void slack_api_init() { size_t case_count = sizeof(cases) / sizeof(cases[0]); qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); + + slack_api_message_init(); } static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, diff --git a/slack-buffer.c b/slack-buffer.c index 04ff85e..d50816d 100644 --- a/slack-buffer.c +++ b/slack-buffer.c @@ -1,8 +1,8 @@ #include "weechat-plugin.h" #include "slack.h" -#include "slack-buffer.h" #include "slack-workspace.h" #include "slack-channel.h" +#include "slack-buffer.h" void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, struct t_slack_workspace **workspace, diff --git a/slack-buffer.h b/slack-buffer.h index 7410ab2..649c813 100644 --- a/slack-buffer.h +++ b/slack-buffer.h @@ -1,6 +1,10 @@ #ifndef _SLACK_BUFFER_H_ #define _SLACK_BUFFER_H_ +void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, + struct t_slack_workspace **workspace, + struct t_slack_channel **channel); + int slack_buffer_nickcmp_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, const char *nick1, diff --git a/slack-input.c b/slack-input.c index ec36d5d..1b06398 100644 --- a/slack-input.c +++ b/slack-input.c @@ -1,10 +1,63 @@ +#include +#include + #include "weechat-plugin.h" +#include "slack.h" +#include "slack-workspace.h" +#include "slack-channel.h" +#include "slack-buffer.h" +#include "slack-request.h" +#include "slack-message.h" #include "slack-input.h" +#include "request/slack-request-chat-postmessage.h" int slack_input_data(struct t_gui_buffer *buffer, const char *input_data) { - (void) buffer; - (void) input_data; + struct t_slack_workspace *workspace = NULL; + struct t_slack_channel *channel = NULL; + struct t_slack_request *request; + char *text; + + slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); + + if (!workspace) + return WEECHAT_RC_ERROR; + + if (channel) + { + if (!workspace->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + text = malloc(SLACK_MESSAGE_MAX_LENGTH); + if (!text) + { + weechat_printf(buffer, + _("%s%s: error allocating string"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return WEECHAT_RC_ERROR; + } + lws_urlencode(text, input_data, SLACK_MESSAGE_MAX_LENGTH); + + request = slack_request_chat_postmessage(workspace, + weechat_config_string( + workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + channel->id, text); + if (request) + slack_workspace_register_request(workspace, request); + + free(text); + } + else + { + weechat_printf(buffer, + _("%s%s: this buffer is not a channel!"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + } return WEECHAT_RC_OK; } diff --git a/slack-message.c b/slack-message.c new file mode 100644 index 0000000..4aa6ef1 --- /dev/null +++ b/slack-message.c @@ -0,0 +1,139 @@ +#include +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-channel.h" +#include "../slack-user.h" +#include "../slack-message.h" + +static const char format_regex[] = "<(.*?)>"; +static const size_t max_groups = 2; + +char *slack_message_translate_code(struct t_slack_workspace *workspace, + const char *code) +{ + struct t_slack_channel *channel; + struct t_slack_user *user; + char *command; + + switch (code[0]) + { + case '#': /* channel */ + channel = slack_channel_search(workspace, code+1); + if (channel) + return strdup(channel->name); + else + return strdup(code); + case '@': /* user */ + user = slack_user_search(workspace, code+1); + if (user) + return strdup(user->profile.display_name); + else + return strdup(code); + case '!': /* special */ + command = strdup(code); + command[0] = '@'; + return command; + default: /* url */ + return strdup(code); + } +} + +char *slack_message_decode(struct t_slack_workspace *workspace, + const char *text) +{ + int rc; + regex_t reg; + regmatch_t groups[max_groups]; + char msgbuf[100]; + char *decoded_text, *pos; + const char *cursor; + size_t offset; + + if ((rc = regcomp(®, format_regex, REG_EXTENDED))) + { + regerror(rc, ®, msgbuf, sizeof(msgbuf)); + weechat_printf( + workspace->buffer, + _("%s%s: error compiling message formatting regex: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + msgbuf); + return strdup(text); + } + + decoded_text = malloc(SLACK_MESSAGE_MAX_LENGTH); + if (!decoded_text) + { + regfree(®); + weechat_printf( + workspace->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return strdup(text); + } + pos = decoded_text; + pos[0] = '\0'; + + for (cursor = text; regexec(®, cursor, max_groups, groups, 0) == 0; cursor += offset) + { + offset = groups[0].rm_eo; + + char *copy = strdup(cursor); + if (!copy) + { + regfree(®); + weechat_printf( + workspace->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return strdup(text); + } + copy[groups[1].rm_eo] = '\0'; + + char *match = strdup(copy + groups[1].rm_so); + if (!match) + { + free(copy); + regfree(®); + weechat_printf( + workspace->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return strdup(text); + } + copy[groups[0].rm_so] = '\0'; + + char *prematch = strdup(copy); + if (!prematch) + { + free(match); + free(copy); + regfree(®); + weechat_printf( + workspace->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return strdup(text); + } + free(copy); + + pos = strncat(decoded_text, prematch, + SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + free(prematch); + + char *replacement = slack_message_translate_code(workspace, match); + free(match); + + pos = strncat(decoded_text, replacement, + SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + free(replacement); + } + pos = strncat(decoded_text, cursor, + SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + + regfree(®); + return decoded_text; +} diff --git a/slack-message.h b/slack-message.h new file mode 100644 index 0000000..baca30f --- /dev/null +++ b/slack-message.h @@ -0,0 +1,9 @@ +#ifndef _SLACK_MESSAGE_H_ +#define _SLACK_MESSAGE_H_ + +#define SLACK_MESSAGE_MAX_LENGTH 40000 + +char *slack_message_decode(struct t_slack_workspace *workspace, + const char *text); + +#endif /*SLACK_MESSAGE_H*/ diff --git a/slack-user.c b/slack-user.c index b78184c..3b0d0fd 100644 --- a/slack-user.c +++ b/slack-user.c @@ -1,5 +1,6 @@ #include #include +#include #include "weechat-plugin.h" #include "slack.h" @@ -7,6 +8,25 @@ #include "slack-user.h" #include "slack-channel.h" +const char *slack_user_get_colour(struct t_slack_user *user) +{ + return weechat_info_get("nick_color", user->profile.display_name); +} + +const char *slack_user_as_prefix(struct t_slack_workspace *workspace, + struct t_slack_user *user) +{ + static char result[256]; + + (void) workspace; + + snprintf(result, sizeof(result), "%s%s\t", + slack_user_get_colour(user), + user->profile.display_name); + + return result; +} + struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, const char *id) { diff --git a/slack-user.h b/slack-user.h index ecf6944..1cd18e2 100644 --- a/slack-user.h +++ b/slack-user.h @@ -45,6 +45,9 @@ struct t_slack_user struct t_slack_user *next_user; }; +const char *slack_user_as_prefix(struct t_slack_workspace *workspace, + struct t_slack_user *user); + struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, const char *id); diff --git a/slack-workspace.c b/slack-workspace.c index 8438fba..2d8fc6d 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -7,7 +7,6 @@ #include "weechat-plugin.h" #include "slack.h" -#include "slack-buffer.h" #include "slack-config.h" #include "slack-input.h" #include "slack-workspace.h" @@ -15,6 +14,7 @@ #include "slack-request.h" #include "slack-user.h" #include "slack-channel.h" +#include "slack-buffer.h" struct t_slack_workspace *slack_workspaces = NULL; struct t_slack_workspace *last_slack_workspace = NULL; diff --git a/slack.c b/slack.c index c1cee92..4b59065 100644 --- a/slack.c +++ b/slack.c @@ -56,7 +56,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) slack_api_init(); - slack_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, + slack_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, &slack_workspace_timer_cb, NULL, NULL); From 0c575b9dbc6faa5dd9311abbb36897aa11a360c4 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 01:09:58 +0100 Subject: [PATCH 009/118] typing notifications --- .gitignore | 1 + Makefile | 11 +- api/slack-api-message.c | 9 ++ api/slack-api-user-typing.c | 63 +++++++++ api/slack-api-user-typing.h | 7 + request/slack-request-channels-list.c | 1 + request/slack-request-chat-postmessage.c | 1 + request/slack-request-users-list.c | 1 + slack-api.c | 106 ++++++++++---- slack-buffer.c | 63 +++++++++ slack-buffer.h | 7 + slack-channel.c | 173 +++++++++++++++++++++-- slack-channel.h | 29 ++++ slack-message.c | 24 ++-- slack-teaminfo.c | 1 + slack-user.c | 34 ++--- slack-workspace.c | 1 + slack-workspace.h | 2 +- slack.c | 18 +++ 19 files changed, 478 insertions(+), 74 deletions(-) create mode 100644 api/slack-api-user-typing.c create mode 100644 api/slack-api-user-typing.h diff --git a/.gitignore b/.gitignore index 771d19f..8498b9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Prerequisites +compile_commands.json cscope* .depend *.d diff --git a/Makefile b/Makefile index ee1280a..9b4bc76 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ CC=clang -CXX=clang++ +CXX=g++ RM=rm -f -CFLAGS=-fsanitize=address -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c -LDFLAGS=-shared -g -fsanitize=address +SANCFLAGS=-fsanitize=address -fsanitize=leak +SANLDFLAGS=-static-libasan -static-liblsan +CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c +LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS) LDLIBS=-lgnutls SRCS=slack.c \ @@ -21,6 +23,7 @@ SRCS=slack.c \ api/slack-api-hello.c \ api/slack-api-error.c \ api/slack-api-message.c \ + api/slack-api-user-typing.c \ api/message/slack-api-message-unimplemented.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ @@ -30,7 +33,7 @@ OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack weechat-slack: $(OBJS) - $(CC) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) + $(CXX) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) libwebsockets/lib/libwebsockets.a: cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 3ea0514..ae6010c 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -82,6 +82,7 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, { struct t_slack_channel *ptr_channel; struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; ptr_channel = slack_channel_search(workspace, channel); if (!ptr_channel) @@ -100,6 +101,14 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, message); free(message); + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + return 1; } diff --git a/api/slack-api-user-typing.c b/api/slack-api-user-typing.c new file mode 100644 index 0000000..75eaf65 --- /dev/null +++ b/api/slack-api-user-typing.c @@ -0,0 +1,63 @@ +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-user.h" +#include "../slack-channel.h" +#include "../slack-api.h" +#include "slack-api-user-typing.h" + +static const char *type = "user_typing"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %s%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), type, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_user_typing_handle(struct t_slack_workspace *workspace, + const char *channel, const char *user) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; /* silently ignore if user hasn't been loaded yet */ + + slack_channel_add_typing(ptr_channel, ptr_user); + + return 1; +} + +int slack_api_user_typing(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *channel, *user; + + channel = json_object_object_get(message, "channel"); + if (!json_valid(channel, workspace)) + return 0; + + user = json_object_object_get(message, "user"); + if (!json_valid(user, workspace)) + return 0; + + return slack_api_user_typing_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user)); +} diff --git a/api/slack-api-user-typing.h b/api/slack-api-user-typing.h new file mode 100644 index 0000000..3aea802 --- /dev/null +++ b/api/slack-api-user-typing.h @@ -0,0 +1,7 @@ +#ifndef _SLACK_API_USER_TYPING_H_ +#define _SLACK_API_USER_TYPING_H_ + +int slack_api_user_typing(struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_USER_TYPING_H*/ diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index 6227875..2b50e6d 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -245,6 +245,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_put(response); free(json_string); } + /* fallthrough */ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: request->client_wsi = NULL; /* Does not doing this cause a leak? diff --git a/request/slack-request-chat-postmessage.c b/request/slack-request-chat-postmessage.c index d795a9c..4ca8a35 100644 --- a/request/slack-request-chat-postmessage.c +++ b/request/slack-request-chat-postmessage.c @@ -165,6 +165,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_put(response); free(json_string); } + /* fallthrough */ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: request->client_wsi = NULL; /* Does not doing this cause a leak? diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index d0e051a..85814bb 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -251,6 +251,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_put(response); free(json_string); } + /* fallthrough */ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: request->client_wsi = NULL; /* Does not doing this cause a leak? diff --git a/slack-api.c b/slack-api.c index 2314951..e5d9af3 100644 --- a/slack-api.c +++ b/slack-api.c @@ -10,6 +10,7 @@ #include "api/slack-api-hello.h" #include "api/slack-api-error.h" #include "api/slack-api-message.h" +#include "api/slack-api-user-typing.h" struct stringcase { @@ -22,6 +23,7 @@ static struct stringcase cases[] = { { "hello", &slack_api_hello } , { "error", &slack_api_error } , { "message", &slack_api_message } +, { "user_typing", &slack_api_user_typing } }; static int stringcase_cmp(const void *p1, const void *p2) @@ -71,49 +73,95 @@ static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, weechat_prefix("network"), SLACK_PLUGIN_NAME, (const char *)in); { + int data_size; char *json_string; json_object *response, *type; + struct t_json_chunk *new_chunk, *last_chunk, *chunk_ptr; - json_string = strdup((const char *)in); + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc(((int)len) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; - response = json_tokener_parse(json_string); - type = json_object_object_get(response, "type"); - if (!type) + strncat(new_chunk->data, in, (int)len); + + if (workspace->json_chunks) + { + for (last_chunk = workspace->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else { - weechat_printf( - workspace->buffer, - _("%s%s: unexpected data received from websocket: closing"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); + workspace->json_chunks = new_chunk; + } - slack_workspace_disconnect(workspace, 0); + data_size = 0; + for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next) + { + data_size += strlen(chunk_ptr->data); + } - json_object_put(response); - free(json_string); - return -1; + json_string = malloc(data_size + 1); + json_string[0] = '\0'; + + for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next) + { + strcat(json_string, chunk_ptr->data); } - if (!slack_api_route_message(workspace, - json_object_get_string(type), response)) + response = json_tokener_parse(json_string); + if (response) { - weechat_printf( - workspace->buffer, - _("%s%s: error while handling message: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - json_string); - weechat_printf( - workspace->buffer, - _("%s%s: closing connection."), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - - slack_workspace_disconnect(workspace, 0); + for (chunk_ptr = workspace->json_chunks; chunk_ptr; workspace->json_chunks = chunk_ptr) + { + chunk_ptr = chunk_ptr->next; + free(workspace->json_chunks->data); + free(workspace->json_chunks); + } + + type = json_object_object_get(response, "type"); + if (!type) + { + weechat_printf( + workspace->buffer, + _("%s%s: unexpected data received from websocket: closing"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + + slack_workspace_disconnect(workspace, 0); + + json_object_put(response); + free(json_string); + return -1; + } + + if (!slack_api_route_message(workspace, + json_object_get_string(type), response)) + { + weechat_printf( + workspace->buffer, + _("%s%s: error while handling message: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + json_string); + weechat_printf( + workspace->buffer, + _("%s%s: closing connection."), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + + slack_workspace_disconnect(workspace, 0); + + json_object_put(response); + free(json_string); + return -1; + } json_object_put(response); free(json_string); - return -1; } - - json_object_put(response); - free(json_string); + else + { + free(json_string); + } } return 0; /* don't passthru */ diff --git a/slack-buffer.c b/slack-buffer.c index d50816d..36a3d2a 100644 --- a/slack-buffer.c +++ b/slack-buffer.c @@ -1,3 +1,5 @@ +#include + #include "weechat-plugin.h" #include "slack.h" #include "slack-workspace.h" @@ -42,6 +44,67 @@ void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, /* no workspace or channel found */ } +char *slack_buffer_typing_bar_cb(const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info) +{ + struct t_slack_channel_typing *ptr_typing; + struct t_slack_workspace *workspace; + struct t_slack_channel *channel; + char notification[256]; + unsigned typecount; + + (void) pointer; + (void) data; + (void) item; + (void) window; + (void) extra_info; + + workspace = NULL; + channel = NULL; + + slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); + + if (!channel) + return strdup(""); + + typecount = 0; + + for (ptr_typing = channel->typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + switch (++typecount) + { + case 1: + strcpy(notification, ptr_typing->name); + break; + case 2: + strcat(notification, ", "); + strcat(notification, ptr_typing->name); + break; + case 3: + default: + strcpy(notification, "Several people"); + break; + } + } + + if (typecount) + { + strcat(notification, NG_(" is typing...", + " are typing...", + typecount)); + return strdup(notification); + } + else + { + return strdup(""); + } +} + int slack_buffer_nickcmp_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, const char *nick1, diff --git a/slack-buffer.h b/slack-buffer.h index 649c813..4ed21fa 100644 --- a/slack-buffer.h +++ b/slack-buffer.h @@ -5,6 +5,13 @@ void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, struct t_slack_workspace **workspace, struct t_slack_channel **channel); +char *slack_buffer_typing_bar_cb(const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info); + int slack_buffer_nickcmp_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, const char *nick1, diff --git a/slack-channel.c b/slack-channel.c index d6255e2..a3b99d6 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -1,10 +1,12 @@ #include #include #include +#include #include "weechat-plugin.h" #include "slack.h" #include "slack-workspace.h" +#include "slack-user.h" #include "slack-channel.h" #include "slack-input.h" #include "slack-buffer.h" @@ -73,7 +75,7 @@ struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *works const char *name) { struct t_gui_buffer *ptr_buffer; - int buffer_created, current_buffer_number; + int buffer_created; const char *short_name, *localvar_channel; char buffer_name[256]; @@ -89,9 +91,6 @@ struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *works } else { - current_buffer_number = weechat_buffer_get_integer( - weechat_current_buffer(), "number"); - ptr_buffer = weechat_buffer_new(buffer_name, &slack_input_data_cb, NULL, NULL, &slack_buffer_close_cb, NULL, NULL); @@ -181,6 +180,7 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, { struct t_slack_channel *new_channel, *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_hook *typing_timer; char buffer_name[SLACK_CHANNEL_NAME_MAX_LEN + 2]; if (!workspace || !id || !name || !name[0]) @@ -202,6 +202,10 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, if ((new_channel = malloc(sizeof(*new_channel))) == NULL) return NULL; + typing_timer = weechat_hook_timer(1 * 1000, 0, 0, + &slack_channel_typing_cb, + new_channel, NULL); + new_channel->type = type; new_channel->id = strdup(id); new_channel->name = strdup(name); @@ -228,6 +232,9 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, new_channel->is_user_deleted = 0; + new_channel->typing_hook_timer = typing_timer; + new_channel->typings = NULL; + new_channel->last_typing = NULL; new_channel->members = NULL; new_channel->last_member = NULL; new_channel->buffer = ptr_buffer; @@ -244,6 +251,137 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, return new_channel; } +void slack_channel_typing_free(struct t_slack_channel *channel, + struct t_slack_channel_typing *typing) +{ + struct t_slack_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 slack_channel_typing_free_all(struct t_slack_channel *channel) +{ + while (channel->typings) + slack_channel_typing_free(channel, channel->typings); +} + +int slack_channel_typing_cb(const void *pointer, + void *data, + int remaining_calls) +{ + struct t_slack_channel_typing *ptr_typing, *next_typing; + struct t_slack_channel *channel; + unsigned typecount; + time_t now; + + (void) data; + (void) remaining_calls; + + if (!pointer) + return WEECHAT_RC_ERROR; + + channel = (struct t_slack_channel *)pointer; + + now = time(NULL); + + typecount = 0; + + for (ptr_typing = channel->typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + next_typing = ptr_typing->next_typing; + + while (ptr_typing && now - ptr_typing->ts > 5) + { + slack_channel_typing_free(channel, ptr_typing); + ptr_typing = next_typing; + if (ptr_typing) + next_typing = ptr_typing->next_typing; + } + + if (!ptr_typing) + break; + + typecount++; + } + + weechat_buffer_set(channel->buffer, + "localvar_set_typing", + typecount > 0 ? "1" : "0"); + weechat_bar_item_update("slack_typing"); + + return WEECHAT_RC_OK; +} + +struct t_slack_channel_typing *slack_channel_typing_search( + struct t_slack_channel *channel, + const char *id) +{ + struct t_slack_channel_typing *ptr_typing; + + if (!channel || !id) + return NULL; + + for (ptr_typing = channel->typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + if (weechat_strcasecmp(ptr_typing->id, id) == 0) + return ptr_typing; + } + + return NULL; +} + +void slack_channel_add_typing(struct t_slack_channel *channel, + struct t_slack_user *user) +{ + struct t_slack_channel_typing *new_typing; + + new_typing = slack_channel_typing_search(channel, user->id); + if (!new_typing) + { + new_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; + } + new_typing->ts = time(NULL); + + slack_channel_typing_cb(channel, NULL, 0); +} + void slack_channel_member_free(struct t_slack_channel *channel, struct t_slack_channel_member *member) { @@ -252,7 +390,7 @@ void slack_channel_member_free(struct t_slack_channel *channel, if (!channel || !member) return; - /* remove member from members list */ + /* remove member from members list */ if (channel->last_member == member) channel->last_member = member->prev_member; if (member->prev_member) @@ -289,7 +427,7 @@ void slack_channel_free(struct t_slack_workspace *workspace, if (!workspace || !channel) return; - /* remove channel from channels list */ + /* remove channel from channels list */ if (workspace->last_channel == channel) workspace->last_channel = channel->prev_channel; if (channel->prev_channel) @@ -303,7 +441,12 @@ void slack_channel_free(struct t_slack_workspace *workspace, 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); + /* free linked lists */ + slack_channel_typing_free_all(channel); slack_channel_member_free_all(channel); /* free channel data */ @@ -313,18 +456,18 @@ void slack_channel_free(struct t_slack_workspace *workspace, free(channel->name); if (channel->name_normalized) free(channel->name_normalized); - if (channel->topic.value) - free(channel->topic.value); - if (channel->topic.creator) - free(channel->topic.creator); - if (channel->purpose.value) - free(channel->purpose.value); - if (channel->purpose.creator) - free(channel->purpose.creator); + if (channel->topic.value) + free(channel->topic.value); + if (channel->topic.creator) + free(channel->topic.creator); + if (channel->purpose.value) + free(channel->purpose.value); + if (channel->purpose.creator) + free(channel->purpose.creator); if (channel->creator) free(channel->creator); if (channel->buffer_as_string) - free (channel->buffer_as_string); + free(channel->buffer_as_string); free(channel); diff --git a/slack-channel.h b/slack-channel.h index f5892be..715c4b2 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -11,6 +11,16 @@ enum t_slack_channel_type SLACK_CHANNEL_TYPE_IM, }; +struct t_slack_channel_typing +{ + char *id; + char *name; + time_t ts; + + struct t_slack_channel_typing *prev_typing; + struct t_slack_channel_typing *next_typing; +}; + struct t_slack_channel_member { char *id; @@ -61,6 +71,9 @@ struct t_slack_channel /* im */ int is_user_deleted; + struct t_hook *typing_hook_timer; + struct t_slack_channel_typing *typings; + struct t_slack_channel_typing *last_typing; struct t_slack_channel_member *members; struct t_slack_channel_member *last_member; struct t_gui_buffer *buffer; @@ -80,6 +93,22 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, enum t_slack_channel_type type, const char *id, const char *name); +void slack_channel_typing_free(struct t_slack_channel *channel, + struct t_slack_channel_typing *typing); + +void slack_channel_typing_free_all(struct t_slack_channel *channel); + +int slack_channel_typing_cb(const void *pointer, + void *data, + int remaining_calls); + +struct t_slack_channel_typing *slack_channel_typing_search( + struct t_slack_channel *channel, + const char *id); + +void slack_channel_add_typing(struct t_slack_channel *channel, + struct t_slack_user *user); + void slack_channel_free_all(struct t_slack_workspace *workspace); #endif /*SLACK_CHANNEL_H*/ diff --git a/slack-message.c b/slack-message.c index 4aa6ef1..2cfa71e 100644 --- a/slack-message.c +++ b/slack-message.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "../weechat-plugin.h" @@ -9,7 +10,7 @@ #include "../slack-user.h" #include "../slack-message.h" -static const char format_regex[] = "<(.*?)>"; +static const char format_regex[] = "<([^>]*?)>"; static const size_t max_groups = 2; char *slack_message_translate_code(struct t_slack_workspace *workspace, @@ -30,7 +31,12 @@ char *slack_message_translate_code(struct t_slack_workspace *workspace, case '@': /* user */ user = slack_user_search(workspace, code+1); if (user) - return strdup(user->profile.display_name); + { + size_t nicklen = snprintf(NULL, 0, "%s@%s%s", weechat_color("chat_nick"), user->profile.display_name, weechat_color("reset")) + 1; + char *tag = malloc(nicklen); + snprintf(tag, nicklen, "%s@%s%s", weechat_color("chat_nick"), user->profile.display_name, weechat_color("reset")); + return tag; + } else return strdup(code); case '!': /* special */ @@ -49,7 +55,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace, regex_t reg; regmatch_t groups[max_groups]; char msgbuf[100]; - char *decoded_text, *pos; + char *decoded_text; const char *cursor; size_t offset; @@ -74,8 +80,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace, weechat_prefix("error"), SLACK_PLUGIN_NAME); return strdup(text); } - pos = decoded_text; - pos[0] = '\0'; + decoded_text[0] = '\0'; for (cursor = text; regexec(®, cursor, max_groups, groups, 0) == 0; cursor += offset) { @@ -85,6 +90,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace, if (!copy) { regfree(®); + free(decoded_text); weechat_printf( workspace->buffer, _("%s%s: error allocating space for message"), @@ -98,6 +104,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace, { free(copy); regfree(®); + free(decoded_text); weechat_printf( workspace->buffer, _("%s%s: error allocating space for message"), @@ -112,6 +119,7 @@ char *slack_message_decode(struct t_slack_workspace *workspace, free(match); free(copy); regfree(®); + free(decoded_text); weechat_printf( workspace->buffer, _("%s%s: error allocating space for message"), @@ -120,18 +128,18 @@ char *slack_message_decode(struct t_slack_workspace *workspace, } free(copy); - pos = strncat(decoded_text, prematch, + strncat(decoded_text, prematch, SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); free(prematch); char *replacement = slack_message_translate_code(workspace, match); free(match); - pos = strncat(decoded_text, replacement, + strncat(decoded_text, replacement, SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); free(replacement); } - pos = strncat(decoded_text, cursor, + strncat(decoded_text, cursor, SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); regfree(®); diff --git a/slack-teaminfo.c b/slack-teaminfo.c index ba1347e..192ca0b 100644 --- a/slack-teaminfo.c +++ b/slack-teaminfo.c @@ -228,6 +228,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_put(response); free(json_string); } + /* fallthrough */ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: client_wsi = NULL; /* Does not doing this cause a leak? diff --git a/slack-user.c b/slack-user.c index 3b0d0fd..c26aca5 100644 --- a/slack-user.c +++ b/slack-user.c @@ -142,7 +142,7 @@ void slack_user_free(struct t_slack_workspace *workspace, if (!workspace || !user) return; - /* remove user from users list */ + /* remove user from users list */ if (workspace->last_user == user) workspace->last_user = user->prev_user; if (user->prev_user) @@ -173,22 +173,22 @@ void slack_user_free(struct t_slack_workspace *workspace, free(user->tz_label); if (user->locale) free(user->locale); - if (user->profile.avatar_hash) - free(user->profile.avatar_hash); - if (user->profile.status_text) - free(user->profile.status_text); - if (user->profile.status_emoji) - free(user->profile.status_emoji); - if (user->profile.real_name) - free(user->profile.real_name); - if (user->profile.display_name) - free(user->profile.display_name); - if (user->profile.real_name_normalized) - free(user->profile.real_name_normalized); - if (user->profile.email) - free(user->profile.email); - if (user->profile.team) - free(user->profile.team); + if (user->profile.avatar_hash) + free(user->profile.avatar_hash); + if (user->profile.status_text) + free(user->profile.status_text); + if (user->profile.status_emoji) + free(user->profile.status_emoji); + if (user->profile.real_name) + free(user->profile.real_name); + if (user->profile.display_name) + free(user->profile.display_name); + if (user->profile.real_name_normalized) + free(user->profile.real_name_normalized); + if (user->profile.email) + free(user->profile.email); + if (user->profile.team) + free(user->profile.team); free(user); diff --git a/slack-workspace.c b/slack-workspace.c index 2d8fc6d..6b0a4af 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -247,6 +247,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_put(response); free(json_string); } + /* fallthrough */ case LWS_CALLBACK_CLOSED_CLIENT_HTTP: workspace->client_wsi = NULL; /* Does not doing this cause a leak? diff --git a/slack-workspace.h b/slack-workspace.h index 9861ab9..997ff23 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -6,7 +6,7 @@ extern struct t_slack_workspace *last_slack_workspace; enum t_slack_workspace_option { - SLACK_WORKSPACE_OPTION_TOKEN = 0, + SLACK_WORKSPACE_OPTION_TOKEN, SLACK_WORKSPACE_NUM_OPTIONS, }; diff --git a/slack.c b/slack.c index 4b59065..0a81640 100644 --- a/slack.c +++ b/slack.c @@ -10,6 +10,7 @@ #include "slack-command.h" #include "slack-workspace.h" #include "slack-api.h" +#include "slack-buffer.h" WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME); @@ -23,6 +24,8 @@ struct t_weechat_plugin *weechat_slack_plugin = NULL; struct t_hook *slack_hook_timer = NULL; +struct t_gui_bar_item *slack_typing_bar_item = NULL; + void slack_lwsl_emit_weechat(int level, const char *line) { char buf[50]; @@ -60,6 +63,18 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) &slack_workspace_timer_cb, NULL, NULL); + if (!weechat_bar_search("typing")) + { + weechat_bar_new("typing", "off", "400", "window", "${typing}", + "bottom", "horizontal", "vertical", + "1", "1", "default", "default", "default", + "off", "slack_typing"); + } + + slack_typing_bar_item = weechat_bar_item_new("slack_typing", + &slack_buffer_typing_bar_cb, + NULL, NULL); + return WEECHAT_RC_OK; } @@ -68,6 +83,9 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) /* make C compiler happy */ (void) plugin; + if (slack_typing_bar_item) + weechat_bar_item_remove(slack_typing_bar_item); + if (slack_hook_timer) weechat_unhook(slack_hook_timer); From 9574f78f8618524af3d9428ba38b31caac30e486 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 13:46:53 +0100 Subject: [PATCH 010/118] channel data --- request/slack-request-channels-list.c | 119 ++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 18 deletions(-) diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index 2b50e6d..42e7fe5 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -100,7 +100,11 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, char *json_string; char cursor[64]; json_object *response, *ok, *error, *channels, *metadata; - json_object *channel, *id, *name, *topic, *next_cursor; + json_object *channel, *id, *name, *created; + json_object *is_general, *name_normalized, *is_shared, *is_org_shared, *is_member; + json_object *topic, *purpose, *is_archived; + json_object *sub_value, *sub_creator, *sub_last_set; + json_object *creator, *next_cursor; struct t_json_chunk *chunk_ptr; chunk_count = 0; @@ -160,33 +164,19 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, channel = json_object_array_get_idx(channels, i - 1); if (!json_valid(channel, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } id = json_object_object_get(channel, "id"); if (!json_valid(id, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } name = json_object_object_get(channel, "name"); if (!json_valid(name, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; - } - - topic = json_object_object_get(channel, "topic"); - if (!json_valid(topic, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; + continue; } new_channel = slack_channel_new( @@ -194,6 +184,99 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, SLACK_CHANNEL_TYPE_CHANNEL, json_object_get_string(id), json_object_get_string(name)); + + /* + created = json_object_object_get(channel, "created"); + if (json_valid(created, request->workspace)) + { + new_channel->created = json_object_get_int(created); + } + + is_general = json_object_object_get(channel, "is_general"); + if (json_valid(is_general, request->workspace)) + { + new_channel->is_general = json_object_get_boolean(is_general); + } + + name_normalized = json_object_object_get(channel, "name_normalized"); + if (json_valid(name_normalized, request->workspace)) + { + new_channel->name_normalized = strdup( + json_object_get_string(name_normalized)); + } + + is_shared = json_object_object_get(channel, "is_shared"); + if (json_valid(is_shared, request->workspace)) + { + new_channel->is_shared = json_object_get_boolean(is_shared); + } + + is_org_shared = json_object_object_get(channel, "is_org_shared"); + if (json_valid(is_org_shared, request->workspace)) + { + new_channel->is_org_shared = json_object_get_boolean(is_org_shared); + } + + is_member = json_object_object_get(channel, "is_member"); + if (json_valid(is_member, request->workspace)) + { + new_channel->is_member = json_object_get_boolean(is_member); + } + + topic = json_object_object_get(channel, "topic"); + if (json_valid(topic, request->workspace)) + { + sub_value = json_object_object_get(topic, "value"); + + sub_creator = json_object_object_get(topic, "creator"); + + sub_last_set = json_object_object_get(topic, "last_set"); + + slack_channel_update_topic(new_channel, + json_valid(sub_value, request->workspace) ? + json_object_get_string(sub_value) : + NULL, + json_valid(sub_creator, request->workspace) ? + json_object_get_string(sub_creator) : + NULL, + json_valid(sub_last_set, request->workspace) ? + json_object_get_int(sub_last_set) : + 0); + } + + purpose = json_object_object_get(channel, "purpose"); + if (json_valid(purpose, request->workspace)) + { + sub_value = json_object_object_get(topic, "value"); + + sub_creator = json_object_object_get(topic, "creator"); + + sub_last_set = json_object_object_get(topic, "last_set"); + + slack_channel_update_purpose(new_channel, + json_valid(sub_value, request->workspace) ? + json_object_get_string(sub_value) : + NULL, + json_valid(sub_creator, request->workspace) ? + json_object_get_string(sub_creator) : + NULL, + json_valid(sub_last_set, request->workspace) ? + json_object_get_int(sub_last_set) : + 0); + } + + is_archived = json_object_object_get(response, "is_archived"); + if (json_valid(is_archived, request->workspace)) + { + new_channel->is_archived = json_object_get_boolean(is_archived); + } + + creator = json_object_object_get(response, "creator"); + if (json_valid(creator, request->workspace)) + { + new_channel->creator = strdup(json_object_get_string(creator)); + } + */ } metadata = json_object_object_get(response, "response_metadata"); From c158142a5a560431e537c30c4d2511c2bd02853b Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 14:35:47 +0100 Subject: [PATCH 011/118] channel data --- request/slack-request-channels-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index 42e7fe5..96e5f53 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -185,7 +185,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_get_string(id), json_object_get_string(name)); - /* created = json_object_object_get(channel, "created"); if (json_valid(created, request->workspace)) { @@ -223,6 +222,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, new_channel->is_member = json_object_get_boolean(is_member); } + /* topic = json_object_object_get(channel, "topic"); if (json_valid(topic, request->workspace)) { @@ -264,6 +264,7 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_get_int(sub_last_set) : 0); } + */ is_archived = json_object_object_get(response, "is_archived"); if (json_valid(is_archived, request->workspace)) @@ -276,7 +277,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, { new_channel->creator = strdup(json_object_get_string(creator)); } - */ } metadata = json_object_object_get(response, "response_metadata"); From 74f01ce9014442127e3e7c4d3ab9b8795283dd58 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 14:45:37 +0100 Subject: [PATCH 012/118] channel data --- slack-channel.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/slack-channel.h b/slack-channel.h index 715c4b2..4c94511 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -33,14 +33,14 @@ struct t_slack_channel_topic { char *value; char *creator; - int last_set; + time_t last_set; }; struct t_slack_channel_purpose { char *value; char *creator; - int last_set; + time_t last_set; }; struct t_slack_channel @@ -48,7 +48,7 @@ struct t_slack_channel enum t_slack_channel_type type; char *id; char *name; - int created; + time_t created; /* channel */ int is_general; @@ -111,4 +111,14 @@ void slack_channel_add_typing(struct t_slack_channel *channel, void slack_channel_free_all(struct t_slack_workspace *workspace); +void slack_channel_update_topic(struct t_slack_channel *channel, + const char* title, + const char* creator, + int last_set); + +void slack_channel_update_purpose(struct t_slack_channel *channel, + const char* purpose, + const char* creator, + int last_set); + #endif /*SLACK_CHANNEL_H*/ From c94091bdff1daf3d6d4a66ad207d1f0719b3845d Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 15:02:15 +0100 Subject: [PATCH 013/118] channel data --- slack-channel.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/slack-channel.c b/slack-channel.c index a3b99d6..87a3b6b 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -296,6 +296,7 @@ int slack_channel_typing_cb(const void *pointer, { struct t_slack_channel_typing *ptr_typing, *next_typing; struct t_slack_channel *channel; + const char *localvar; unsigned typecount; time_t now; @@ -330,9 +331,11 @@ int slack_channel_typing_cb(const void *pointer, typecount++; } - weechat_buffer_set(channel->buffer, - "localvar_set_typing", - typecount > 0 ? "1" : "0"); + 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", + typecount > 0 ? "1" : "0"); weechat_bar_item_update("slack_typing"); return WEECHAT_RC_OK; @@ -479,3 +482,36 @@ void slack_channel_free_all(struct t_slack_workspace *workspace) while (workspace->channels) slack_channel_free(workspace, workspace->channels); } + +void slack_channel_update_topic(struct t_slack_channel *channel, + 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); + else + weechat_buffer_set(channel->buffer, "title", ""); +} + +void slack_channel_update_purpose(struct t_slack_channel *channel, + const char* purpose, + const char* creator, + int last_set) +{ + if (channel->purpose.value) + free(channel->purpose.value); + if (channel->purpose.creator) + free(channel->purpose.creator); + channel->purpose.value = (purpose) ? strdup(purpose) : NULL; + channel->purpose.creator = (creator) ? strdup(creator) : NULL; + channel->purpose.last_set = last_set; +} From 614a7d5b5bb7eba839a8b00f62a8cd2c8c9ce405 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 15:51:07 +0100 Subject: [PATCH 014/118] this commit is in an unspecified state --- request/slack-request-channels-list.c | 2 -- slack-channel.h | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index 96e5f53..9fb90aa 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -222,7 +222,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, new_channel->is_member = json_object_get_boolean(is_member); } - /* topic = json_object_object_get(channel, "topic"); if (json_valid(topic, request->workspace)) { @@ -264,7 +263,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, json_object_get_int(sub_last_set) : 0); } - */ is_archived = json_object_object_get(response, "is_archived"); if (json_valid(is_archived, request->workspace)) diff --git a/slack-channel.h b/slack-channel.h index 4c94511..2e2d08f 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -15,7 +15,7 @@ struct t_slack_channel_typing { char *id; char *name; - time_t ts; + long ts; struct t_slack_channel_typing *prev_typing; struct t_slack_channel_typing *next_typing; @@ -33,14 +33,14 @@ struct t_slack_channel_topic { char *value; char *creator; - time_t last_set; + long last_set; }; struct t_slack_channel_purpose { char *value; char *creator; - time_t last_set; + long last_set; }; struct t_slack_channel @@ -48,7 +48,7 @@ struct t_slack_channel enum t_slack_channel_type type; char *id; char *name; - time_t created; + int created; /* channel */ int is_general; From 32046373b41dd7ba88d46e29f1c9fed41c3cf5b9 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 6 May 2018 21:21:48 +0100 Subject: [PATCH 015/118] htmldecode --- slack-channel.h | 8 ++++---- slack-message.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/slack-channel.h b/slack-channel.h index 2e2d08f..4c94511 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -15,7 +15,7 @@ struct t_slack_channel_typing { char *id; char *name; - long ts; + time_t ts; struct t_slack_channel_typing *prev_typing; struct t_slack_channel_typing *next_typing; @@ -33,14 +33,14 @@ struct t_slack_channel_topic { char *value; char *creator; - long last_set; + time_t last_set; }; struct t_slack_channel_purpose { char *value; char *creator; - long last_set; + time_t last_set; }; struct t_slack_channel @@ -48,7 +48,7 @@ struct t_slack_channel enum t_slack_channel_type type; char *id; char *name; - int created; + time_t created; /* channel */ int is_general; diff --git a/slack-message.c b/slack-message.c index 2cfa71e..c6a2bcd 100644 --- a/slack-message.c +++ b/slack-message.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -48,6 +49,51 @@ char *slack_message_translate_code(struct t_slack_workspace *workspace, } } +void slack_message_htmldecode(char *dest, const char *src, size_t n) +{ + size_t i, j; + + for (i = 0, j = 0; i < n; i++, j++) + switch (src[i]) + { + case '\0': + dest[j] = '\0'; + return; + case '&': + if (src[i+1] == 'g' && + src[i+2] == 't' && + src[i+3] == ';') + { + dest[j] = '>'; + i += 3; + break; + } + else if (src[i+1] == 'l' && + src[i+2] == 't' && + src[i+3] == ';') + { + dest[j] = '<'; + i += 3; + break; + } + else if (src[i+1] == 'a' && + src[i+2] == 'm' && + src[i+3] == 'p' && + src[i+4] == ';') + { + dest[j] = '&'; + i += 4; + break; + } + /* fallthrough */ + default: + dest[j] = src[i]; + break; + } + dest[j-1] = '\0'; + return; +} + char *slack_message_decode(struct t_slack_workspace *workspace, const char *text) { @@ -142,6 +188,9 @@ char *slack_message_decode(struct t_slack_workspace *workspace, strncat(decoded_text, cursor, SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + slack_message_htmldecode(decoded_text, decoded_text, + SLACK_MESSAGE_MAX_LENGTH); + regfree(®); return decoded_text; } From 33eb0d6bb122d6a336b0d5b1b3216c4919eb760a Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 7 May 2018 18:08:34 +0100 Subject: [PATCH 016/118] Release 0.1 --- .gitattributes | 2 + Makefile | 4 + ...1de74b130f35082fb45a12e9ead42ad5c775f9b64f | 1825 +++++++++++ ...6353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 | 1462 +++++++++ debian/.debhelper/bucket/index | 2 + debian/changelog | 6 + debian/compat | 1 + debian/control | 19 + debian/copyright | 2865 +++++++++++++++++ debian/debhelper-build-stamp | 1 + debian/rules | 18 + request/slack-request-channels-list.c | 24 +- request/slack-request-chat-postmessage.c | 24 +- request/slack-request-conversations-members.c | 326 ++ request/slack-request-conversations-members.h | 9 + request/slack-request-users-list.c | 43 +- slack-channel.c | 26 + slack-channel.h | 5 + slack-request.h | 3 + slack-user.h | 4 + slack-workspace.c | 6 + slack.c | 4 +- 22 files changed, 6674 insertions(+), 5 deletions(-) create mode 100644 .gitattributes create mode 100755 debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f create mode 100755 debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 create mode 100644 debian/.debhelper/bucket/index create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/debhelper-build-stamp create mode 100755 debian/rules create mode 100644 request/slack-request-conversations-members.c create mode 100644 request/slack-request-conversations-members.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..51f39db --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Github language display +*.h linguist-language=C diff --git a/Makefile b/Makefile index 9b4bc76..c9305d0 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ SRCS=slack.c \ api/message/slack-api-message-unimplemented.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ + request/slack-request-conversations-members.c \ request/slack-request-users-list.c OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a @@ -57,6 +58,9 @@ clean: distclean: clean $(RM) *~ .depend +install: slack.so + install slack.so ~/.weechat/plugins/ + .PHONY: tags cs tags: diff --git a/debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f b/debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f new file mode 100755 index 0000000..dd2ca93 --- /dev/null +++ b/debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f @@ -0,0 +1,1825 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2016 Free Software Foundation, Inc. + +timestamp='2016-11-04' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2016 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 b/debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 new file mode 100755 index 0000000..2e9ad7f --- /dev/null +++ b/debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 @@ -0,0 +1,1462 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2016 Free Software Foundation, Inc. + +timestamp='2016-10-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2016 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "${UNAME_MACHINE_ARCH}" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = hppa2.0w ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +cat >&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/debian/.debhelper/bucket/index b/debian/.debhelper/bucket/index new file mode 100644 index 0000000..effd394 --- /dev/null +++ b/debian/.debhelper/bucket/index @@ -0,0 +1,2 @@ +8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 json-c/config.guess +1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f json-c/config.sub diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..4fcdaa3 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +weechat-slack (0~1805071648-1) UNRELEASED; urgency=low + + * Initial release. Closes: #nnnn + + + -- Bao Mon, 07 May 2018 17:48:57 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..b4de394 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +11 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..80bcd14 --- /dev/null +++ b/debian/control @@ -0,0 +1,19 @@ +Source: weechat-slack +Section: net +Priority: optional +Maintainer: Tony Olagbaiye +Build-Depends: cmake, debhelper (>= 11), pkg-config +Standards-Version: 4.1.3 +Homepage: https://weechat.org/ +Vcs-Git: https://github.com/bqv/weechat-slack.git +Vcs-Browser: https://github.com/bqv/weechat-slack + +Package: weechat-slack +Architecture: all +Depends: + weechat (>= 1.4) +Description: Fast, light and extensible chat client - Slack plugin + WeeChat (Wee Enhanced Environment for Chat) is a fast and light chat client + for many operating systems. Everything can be done with a keyboard. + . + This package provides the Slack API plugin. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..172e0b9 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,2865 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: weechat-slack +Source: +# +# Please double check copyright with the licensecheck(1) command. + +Files: .depend + .gitattributes + .gitignore + .gitmodules + Makefile + api/.slack-api-message.c.swp + api/message/.slack-api-message-bot-message.c.swp + api/message/slack-api-message-unimplemented.c + api/message/slack-api-message-unimplemented.h + api/message/slack-api-message-unimplemented.o + api/slack-api-error.c + api/slack-api-error.h + api/slack-api-error.o + api/slack-api-hello.c + api/slack-api-hello.h + api/slack-api-hello.o + api/slack-api-message.c + api/slack-api-message.h + api/slack-api-message.o + api/slack-api-user-typing.c + api/slack-api-user-typing.h + api/slack-api-user-typing.o + compile_commands.json + debian/control + json-c/.deps/arraylist.Plo + json-c/.deps/debug.Plo + json-c/.deps/json_c_version.Plo + json-c/.deps/json_object.Plo + json-c/.deps/json_object_iterator.Plo + json-c/.deps/json_pointer.Plo + json-c/.deps/json_tokener.Plo + json-c/.deps/json_util.Plo + json-c/.deps/json_visit.Plo + json-c/.deps/linkhash.Plo + json-c/.deps/printbuf.Plo + json-c/.deps/random_seed.Plo + json-c/.deps/strerror_override.Plo + json-c/.editorconfig + json-c/.git + json-c/.gitignore + json-c/.travis.yml + json-c/AUTHORS + json-c/Android.configure.mk + json-c/CMakeCache.txt + json-c/CMakeFiles/3.9.0/CMakeCCompiler.cmake + json-c/CMakeFiles/3.9.0/CMakeCXXCompiler.cmake + json-c/CMakeFiles/3.9.0/CMakeDetermineCompilerABI_C.bin + json-c/CMakeFiles/3.9.0/CMakeDetermineCompilerABI_CXX.bin + json-c/CMakeFiles/3.9.0/CMakeSystem.cmake + json-c/CMakeFiles/3.9.0/CompilerIdC/CMakeCCompilerId.c + json-c/CMakeFiles/3.9.0/CompilerIdC/a.out + json-c/CMakeFiles/3.9.0/CompilerIdCXX/CMakeCXXCompilerId.cpp + json-c/CMakeFiles/3.9.0/CompilerIdCXX/a.out + json-c/CMakeFiles/CMakeDirectoryInformation.cmake + json-c/CMakeFiles/CMakeOutput.log + json-c/CMakeFiles/Makefile.cmake + json-c/CMakeFiles/Makefile2 + json-c/CMakeFiles/TargetDirectories.txt + json-c/CMakeFiles/cmake.check_cache + json-c/CMakeFiles/feature_tests.bin + json-c/CMakeFiles/feature_tests.c + json-c/CMakeFiles/feature_tests.cxx + json-c/CMakeFiles/json-c-static.dir/C.includecache + json-c/CMakeFiles/json-c-static.dir/DependInfo.cmake + json-c/CMakeFiles/json-c-static.dir/arraylist.c.o + json-c/CMakeFiles/json-c-static.dir/build.make + json-c/CMakeFiles/json-c-static.dir/cmake_clean.cmake + json-c/CMakeFiles/json-c-static.dir/cmake_clean_target.cmake + json-c/CMakeFiles/json-c-static.dir/debug.c.o + json-c/CMakeFiles/json-c-static.dir/depend.internal + json-c/CMakeFiles/json-c-static.dir/depend.make + json-c/CMakeFiles/json-c-static.dir/flags.make + json-c/CMakeFiles/json-c-static.dir/json_c_version.c.o + json-c/CMakeFiles/json-c-static.dir/json_object.c.o + json-c/CMakeFiles/json-c-static.dir/json_object_iterator.c.o + json-c/CMakeFiles/json-c-static.dir/json_pointer.c.o + json-c/CMakeFiles/json-c-static.dir/json_tokener.c.o + json-c/CMakeFiles/json-c-static.dir/json_util.c.o + json-c/CMakeFiles/json-c-static.dir/json_visit.c.o + json-c/CMakeFiles/json-c-static.dir/link.txt + json-c/CMakeFiles/json-c-static.dir/linkhash.c.o + json-c/CMakeFiles/json-c-static.dir/printbuf.c.o + json-c/CMakeFiles/json-c-static.dir/progress.make + json-c/CMakeFiles/json-c-static.dir/random_seed.c.o + json-c/CMakeFiles/json-c-static.dir/strerror_override.c.o + json-c/CMakeFiles/json-c.dir/DependInfo.cmake + json-c/CMakeFiles/json-c.dir/build.make + json-c/CMakeFiles/json-c.dir/cmake_clean.cmake + json-c/CMakeFiles/json-c.dir/depend.make + json-c/CMakeFiles/json-c.dir/flags.make + json-c/CMakeFiles/json-c.dir/link.txt + json-c/CMakeFiles/json-c.dir/progress.make + json-c/CMakeFiles/progress.marks + json-c/Doxyfile + json-c/INSTALL + json-c/Makefile + json-c/Makefile.am + json-c/NEWS + json-c/README + json-c/README.md + json-c/RELEASE_CHECKLIST.txt + json-c/STYLE.txt + json-c/appveyor.yml + json-c/autoconf-archive/README.txt + json-c/autogen.sh + json-c/autom4te.cache/requests + json-c/autom4te.cache/traces.1 + json-c/autom4te.cache/traces.2 + json-c/cmake_install.cmake + json-c/config.h + json-c/config.h.in + json-c/config.h.win32 + json-c/configure.ac + json-c/fuzz/README.md + json-c/fuzz/tokener_parse_ex_fuzzer.cc + json-c/fuzz/tokener_parse_ex_fuzzer.dict + json-c/include/config.h + json-c/include/json_config.h + json-c/issues_closed_for_0.13.md + json-c/json-c-uninstalled.pc + json-c/json-c-uninstalled.pc.in + json-c/json-c.pc + json-c/json-c.pc.in + json-c/json_config.h + json-c/json_config.h.in + json-c/json_config.h.win32 + json-c/json_inttypes.h + json-c/json_object_iterator.c + json-c/json_object_iterator.h + json-c/json_visit.h + json-c/libjson-c.a + json-c/libjson.c + json-c/math_compat.h + json-c/snprintf_compat.h + json-c/stamp-h1 + json-c/stamp-h2 + json-c/strdup_compat.h + json-c/strerror_override.c + json-c/strerror_override.h + json-c/strerror_override_private.h + json-c/tests/.deps/test1.Po + json-c/tests/.deps/test1Formatted-parse_flags.Po + json-c/tests/.deps/test1Formatted-test1.Po + json-c/tests/.deps/test2.Po + json-c/tests/.deps/test2Formatted-parse_flags.Po + json-c/tests/.deps/test2Formatted-test2.Po + json-c/tests/.deps/test4.Po + json-c/tests/.deps/testReplaceExisting.Po + json-c/tests/.deps/test_cast.Po + json-c/tests/.deps/test_charcase.Po + json-c/tests/.deps/test_compare.Po + json-c/tests/.deps/test_deep_copy.Po + json-c/tests/.deps/test_double_serializer.Po + json-c/tests/.deps/test_float.Po + json-c/tests/.deps/test_int_add.Po + json-c/tests/.deps/test_json_pointer.Po + json-c/tests/.deps/test_locale.Po + json-c/tests/.deps/test_null.Po + json-c/tests/.deps/test_parse.Po + json-c/tests/.deps/test_parse_int64.Po + json-c/tests/.deps/test_printbuf.Po + json-c/tests/.deps/test_set_serializer.Po + json-c/tests/.deps/test_set_value.Po + json-c/tests/.deps/test_util_file.Po + json-c/tests/.deps/test_visit.Po + json-c/tests/Makefile.am + json-c/tests/parse_flags.c + json-c/tests/parse_flags.h + json-c/tests/test-defs.sh + json-c/tests/test1.c + json-c/tests/test1.expected + json-c/tests/test1.test + json-c/tests/test1Formatted_plain.expected + json-c/tests/test1Formatted_pretty.expected + json-c/tests/test1Formatted_spaced.expected + json-c/tests/test2.c + json-c/tests/test2.expected + json-c/tests/test2.test + json-c/tests/test2Formatted_plain.expected + json-c/tests/test2Formatted_pretty.expected + json-c/tests/test2Formatted_spaced.expected + json-c/tests/test4.c + json-c/tests/test4.expected + json-c/tests/testReplaceExisting.c + json-c/tests/testReplaceExisting.expected + json-c/tests/test_basic.test + json-c/tests/test_cast.c + json-c/tests/test_cast.expected + json-c/tests/test_charcase.c + json-c/tests/test_charcase.expected + json-c/tests/test_compare.c + json-c/tests/test_compare.expected + json-c/tests/test_deep_copy.c + json-c/tests/test_deep_copy.expected + json-c/tests/test_double_serializer.c + json-c/tests/test_double_serializer.expected + json-c/tests/test_float.expected + json-c/tests/test_int_add.c + json-c/tests/test_int_add.expected + json-c/tests/test_json_pointer.c + json-c/tests/test_json_pointer.expected + json-c/tests/test_locale.c + json-c/tests/test_locale.expected + json-c/tests/test_null.c + json-c/tests/test_null.expected + json-c/tests/test_parse.c + json-c/tests/test_parse.expected + json-c/tests/test_parse_int64.c + json-c/tests/test_parse_int64.expected + json-c/tests/test_printbuf.c + json-c/tests/test_printbuf.expected + json-c/tests/test_set_serializer.c + json-c/tests/test_set_serializer.expected + json-c/tests/test_set_value.c + json-c/tests/test_set_value.expected + json-c/tests/test_util_file.c + json-c/tests/test_util_file.expected + json-c/tests/test_visit.c + json-c/tests/test_visit.expected + json-c/tests/valid.json + json-c/vasprintf_compat.h + libwebsockets/.git + libwebsockets/.gitignore + libwebsockets/.travis.yml + libwebsockets/CMakeCache.txt + libwebsockets/CMakeFiles/3.9.0/CMakeCCompiler.cmake + libwebsockets/CMakeFiles/3.9.0/CMakeDetermineCompilerABI_C.bin + libwebsockets/CMakeFiles/3.9.0/CMakeSystem.cmake + libwebsockets/CMakeFiles/3.9.0/CompilerIdC/CMakeCCompilerId.c + libwebsockets/CMakeFiles/3.9.0/CompilerIdC/a.out + libwebsockets/CMakeFiles/CMakeDirectoryInformation.cmake + libwebsockets/CMakeFiles/CMakeError.log + libwebsockets/CMakeFiles/CMakeOutput.log + libwebsockets/CMakeFiles/CMakeRuleHashes.txt + libwebsockets/CMakeFiles/Export/lib/cmake/libwebsockets/LibwebsocketsTargets-debug.cmake + libwebsockets/CMakeFiles/Export/lib/cmake/libwebsockets/LibwebsocketsTargets.cmake + libwebsockets/CMakeFiles/LibwebsocketsConfig.cmake + libwebsockets/CMakeFiles/Makefile.cmake + libwebsockets/CMakeFiles/Makefile2 + libwebsockets/CMakeFiles/TargetDirectories.txt + libwebsockets/CMakeFiles/cmake.check_cache + libwebsockets/CMakeFiles/dist.dir/DependInfo.cmake + libwebsockets/CMakeFiles/dist.dir/build.make + libwebsockets/CMakeFiles/dist.dir/cmake_clean.cmake + libwebsockets/CMakeFiles/dist.dir/progress.make + libwebsockets/CMakeFiles/feature_tests.bin + libwebsockets/CMakeFiles/feature_tests.c + libwebsockets/CMakeFiles/progress.marks + libwebsockets/CMakeFiles/websockets.dir/C.includecache + libwebsockets/CMakeFiles/websockets.dir/DependInfo.cmake + libwebsockets/CMakeFiles/websockets.dir/build.make + libwebsockets/CMakeFiles/websockets.dir/cmake_clean.cmake + libwebsockets/CMakeFiles/websockets.dir/cmake_clean_target.cmake + libwebsockets/CMakeFiles/websockets.dir/depend.internal + libwebsockets/CMakeFiles/websockets.dir/depend.make + libwebsockets/CMakeFiles/websockets.dir/flags.make + libwebsockets/CMakeFiles/websockets.dir/lib/alloc.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/context.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/event-libs/poll/poll.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/libwebsockets.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/misc/base64-decode.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/misc/lws-ring.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/misc/sha-1.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/output.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/plat/lws-plat-unix.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/pollfd.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/h1/ops-h1.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/client/client-handshake.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/client/client.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/header.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/server/lws-spa.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/server/parsers.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/server/server.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/listen/ops-listen.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/pipe/ops-pipe.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/raw/ops-raw.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/client-parser-ws.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/client-ws.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/ops-ws.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/server-ws.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/service.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/tls/openssl/openssl-client.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/tls/openssl/openssl-server.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/tls/openssl/ssl.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/tls/tls-client.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/tls/tls-server.c.o + libwebsockets/CMakeFiles/websockets.dir/lib/tls/tls.c.o + libwebsockets/CMakeFiles/websockets.dir/link.txt + libwebsockets/CMakeFiles/websockets.dir/progress.make + libwebsockets/CMakeLists.txt + libwebsockets/CPackConfig.cmake + libwebsockets/CPackSourceConfig.cmake + libwebsockets/Kconfig + libwebsockets/LibwebsocketsConfig.cmake + libwebsockets/LibwebsocketsConfigVersion.cmake + libwebsockets/LibwebsocketsTargets.cmake + libwebsockets/Makefile + libwebsockets/Makefile.projbuild + libwebsockets/README.md + libwebsockets/READMEs/README-plugin-sshd-base.md + libwebsockets/READMEs/README.build.md + libwebsockets/READMEs/README.esp32.md + libwebsockets/READMEs/README.generic-sessions.md + libwebsockets/READMEs/README.generic-table.md + libwebsockets/READMEs/README.lws-meta.md + libwebsockets/READMEs/README.lwsws.md + libwebsockets/READMEs/README.plugin-acme.md + libwebsockets/READMEs/README.problems.md + libwebsockets/READMEs/mainpage.md + libwebsockets/READMEs/release-checklist + libwebsockets/appveyor.yml + libwebsockets/cmake/FindLibWebSockets.cmake + libwebsockets/cmake/FindOpenSSLbins.cmake + libwebsockets/cmake/LibwebsocketsConfig.cmake.in + libwebsockets/cmake/LibwebsocketsConfigVersion.cmake.in + libwebsockets/cmake/UseRPMTools.cmake + libwebsockets/cmake/lws_config.h.in + libwebsockets/cmake/lws_config_private.h.in + libwebsockets/cmake_install.cmake + libwebsockets/component.mk + libwebsockets/contrib/Android.mk + libwebsockets/contrib/abi/README.md + libwebsockets/contrib/abi/libwebsockets.json + libwebsockets/contrib/abi/lws-abi-update.sh + libwebsockets/contrib/android-make-script.sh + libwebsockets/contrib/cross-aarch64.cmake + libwebsockets/contrib/cross-arm-linux-gnueabihf.cmake + libwebsockets/contrib/cross-esp32.cmake + libwebsockets/contrib/cross-ming.cmake + libwebsockets/contrib/cross-openwrt-makefile + libwebsockets/contrib/cross-w32.cmake + libwebsockets/contrib/cross-w64.cmake + libwebsockets/doc-assets/lws-overview.png + libwebsockets/doc-assets/lws-smp-example.png + libwebsockets/doc-assets/lws-smp-ov.png + libwebsockets/doc-assets/lwsgt-overview.png + libwebsockets/include/lws_config.h + libwebsockets/lib/alloc.c + libwebsockets/lib/event-libs/README.md + libwebsockets/lib/plat/lws-plat-optee.c + libwebsockets/lib/plat/lws-plat-win.c + libwebsockets/lib/roles/README.md + libwebsockets/lib/roles/h2/huftable.h + libwebsockets/lib/roles/http/client/client-handshake.c + libwebsockets/lib/roles/http/lextable-strings.h + libwebsockets/lib/roles/http/lextable.h + libwebsockets/lib/roles/http/server/rewrite.c + libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.h + libwebsockets/lib/roles/ws/ext/extension.c + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_stack.h + libwebsockets/libwebsockets.dox + libwebsockets/libwebsockets.pc + libwebsockets/libwebsockets_static.pc + libwebsockets/lws_config.h + libwebsockets/lws_config_private.h + libwebsockets/lwsws/etc-logrotate.d-lwsws + libwebsockets/lwsws/etc-lwsws-conf-EXAMPLE + libwebsockets/lwsws/etc-lwsws-conf.d-localhost-EXAMPLE + libwebsockets/lwsws/usr-lib-systemd-system-lwsws.service + libwebsockets/minimal-examples/README.md + libwebsockets/minimal-examples/client-server/README.md + libwebsockets/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt + libwebsockets/minimal-examples/client-server/minimal-ws-proxy/README.md + libwebsockets/minimal-examples/client-server/minimal-ws-proxy/mount-origin/favicon.ico + libwebsockets/minimal-examples/client-server/minimal-ws-proxy/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-client/README.md + libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt + libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/README.md + libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer + libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt + libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/README.md + libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh + libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer + libwebsockets/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt + libwebsockets/minimal-examples/http-client/minimal-http-client-multi/README.md + libwebsockets/minimal-examples/http-client/minimal-http-client-multi/selftest.sh + libwebsockets/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer + libwebsockets/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt + libwebsockets/minimal-examples/http-client/minimal-http-client-post/README.md + libwebsockets/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer + libwebsockets/minimal-examples/http-client/minimal-http-client-post/selftest.sh + libwebsockets/minimal-examples/http-client/minimal-http-client/CMakeLists.txt + libwebsockets/minimal-examples/http-client/minimal-http-client/README.md + libwebsockets/minimal-examples/http-client/minimal-http-client/selftest.sh + libwebsockets/minimal-examples/http-client/minimal-http-client/warmcat.com.cer + libwebsockets/minimal-examples/http-server/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/ba-passwords + libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-secret-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/localhost-100y.cert + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/localhost-100y.key + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/localhost-100y.cert + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/localhost-100y.key + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.cert + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.key + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-smp/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-sse/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/localhost-100y.cert + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/localhost-100y.key + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/http-server/minimal-http-server/CMakeLists.txt + libwebsockets/minimal-examples/http-server/minimal-http-server/README.md + libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/favicon.ico + libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/index.html + libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/raw/README.md + libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt + libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/README.md + libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt + libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/README.md + libwebsockets/minimal-examples/raw/minimal-raw-file/CMakeLists.txt + libwebsockets/minimal-examples/raw/minimal-raw-file/README.md + libwebsockets/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt + libwebsockets/minimal-examples/raw/minimal-raw-vhost/README.md + libwebsockets/minimal-examples/selftests-library.sh + libwebsockets/minimal-examples/selftests.sh + libwebsockets/minimal-examples/ws-client/README.md + libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt + libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/README.md + libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt + libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/README.md + libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt + libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/README.md + libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer + libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh + libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt + libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/README.md + libwebsockets/minimal-examples/ws-server/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-broker/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-broker/mount-origin/favicon.ico + libwebsockets/minimal-examples/ws-server/minimal-ws-broker/mount-origin/index.html + libwebsockets/minimal-examples/ws-server/minimal-ws-broker/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/favicon.ico + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/index.html + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/mount-origin/favicon.ico + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/mount-origin/index.html + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/mount-origin/favicon.ico + libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/mount-origin/index.html + libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/mount-origin/favicon.ico + libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/mount-origin/libwebsockets.org-logo.png + libwebsockets/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt + libwebsockets/minimal-examples/ws-server/minimal-ws-server/README.md + libwebsockets/minimal-examples/ws-server/minimal-ws-server/mount-origin/favicon.ico + libwebsockets/minimal-examples/ws-server/minimal-ws-server/mount-origin/index.html + libwebsockets/minimal-examples/ws-server/minimal-ws-server/mount-origin/libwebsockets.org-logo.png + libwebsockets/plugin-standalone/CMakeLists.txt + libwebsockets/plugins/generic-sessions/assets/lwsgs-logo.png + libwebsockets/plugins/generic-sessions/assets/md5.min.js + libwebsockets/plugins/generic-sessions/assets/post-register-fail.html + libwebsockets/plugins/generic-sessions/assets/seats.jpg + libwebsockets/plugins/generic-sessions/assets/sent-forgot-ok.html + libwebsockets/plugins/generic-table/assets/lwsgt.js + libwebsockets/plugins/lwsws-logo.png + libwebsockets/plugins/ssh-base/crypto/chacha.c + libwebsockets/plugins/ssh-base/crypto/ed25519.c + libwebsockets/plugins/ssh-base/crypto/fe25519.c + libwebsockets/plugins/ssh-base/crypto/fe25519.h + libwebsockets/plugins/ssh-base/crypto/ge25519.c + libwebsockets/plugins/ssh-base/crypto/ge25519.h + libwebsockets/plugins/ssh-base/crypto/ge25519_base.data + libwebsockets/plugins/ssh-base/crypto/poly1305.c + libwebsockets/plugins/ssh-base/crypto/sc25519.c + libwebsockets/plugins/ssh-base/crypto/sc25519.h + libwebsockets/plugins/ssh-base/crypto/smult_curve25519_ref.c + libwebsockets/plugins/ssh-base/include/lws-plugin-sshd-static-build-includes.h + libwebsockets/scripts/attack.sh + libwebsockets/scripts/autobahn-test.sh + libwebsockets/scripts/build-gcov.sh + libwebsockets/scripts/client-ca/certindex.txt + libwebsockets/scripts/client-ca/create-ca.sh + libwebsockets/scripts/client-ca/create-client-cert.sh + libwebsockets/scripts/client-ca/create-server-cert.sh + libwebsockets/scripts/client-ca/serial + libwebsockets/scripts/client-ca/tmp.cnf + libwebsockets/scripts/esp32.mk + libwebsockets/scripts/gcov.sh + libwebsockets/scripts/h2load-smp.sh + libwebsockets/scripts/h2load.sh + libwebsockets/scripts/h2spec.sh + libwebsockets/scripts/libwebsockets.spec + libwebsockets/scripts/travis_control.sh + libwebsockets/scripts/travis_install.sh + libwebsockets/test-apps/.gitignore + libwebsockets/test-apps/android/app/build.gradle + libwebsockets/test-apps/android/app/src/main/jni/Android.mk + libwebsockets/test-apps/android/app/src/main/jni/Application.mk + libwebsockets/test-apps/android/app/src/main/libs/placeholder + libwebsockets/test-apps/android/app/src/main/res/drawable/warmcat.png + libwebsockets/test-apps/android/app/src/main/res/mipmap-hdpi/ic_launcher.png + libwebsockets/test-apps/android/app/src/main/res/mipmap-mdpi/ic_launcher.png + libwebsockets/test-apps/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png + libwebsockets/test-apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png + libwebsockets/test-apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png + libwebsockets/test-apps/android/build.gradle + libwebsockets/test-apps/android/gradle.properties + libwebsockets/test-apps/android/settings.gradle + libwebsockets/test-apps/candide.zip + libwebsockets/test-apps/favicon.ico + libwebsockets/test-apps/http2.png + libwebsockets/test-apps/libwebsockets-test-server.service + libwebsockets/test-apps/libwebsockets.org-logo.png + libwebsockets/test-apps/lws-cgi-test.sh + libwebsockets/test-apps/lws-common.js + libwebsockets/test-apps/lws-ssh-test-keys + libwebsockets/test-apps/lws-ssh-test-keys.pub + libwebsockets/test-apps/private/index.html + libwebsockets/test-apps/wss-over-h2.png + libwebsockets/win32port/libwebsockets.nsi + libwebsockets/win32port/version.rc.in + libwebsockets/win32port/win32helpers/getopt.h + libwebsockets/win32port/win32helpers/gettimeofday.c + libwebsockets/win32port/win32helpers/gettimeofday.h + libwebsockets/win32port/zlib/ZLib.vcxproj + libwebsockets/win32port/zlib/ZLib.vcxproj.filters + libwebsockets/win32port/zlib/crc32.h + libwebsockets/win32port/zlib/inffixed.h + libwebsockets/win32port/zlib/trees.h + request/#slack-request-conversations-members.c# + request/slack-request-channels-list.c + request/slack-request-channels-list.h + request/slack-request-channels-list.o + request/slack-request-chat-postmessage.c + request/slack-request-chat-postmessage.h + request/slack-request-chat-postmessage.o + request/slack-request-conversations-members.c + request/slack-request-conversations-members.h + request/slack-request-conversations-members.o + request/slack-request-users-list.c + request/slack-request-users-list.h + request/slack-request-users-list.o + slack-api.c + slack-api.h + slack-api.o + slack-buffer.c + slack-buffer.h + slack-buffer.o + slack-channel.c + slack-channel.h + slack-channel.o + slack-command.c + slack-command.h + slack-command.o + slack-config.c + slack-config.h + slack-config.o + slack-input.c + slack-input.h + slack-input.o + slack-message.c + slack-message.h + slack-message.o + slack-oauth.c + slack-oauth.h + slack-oauth.o + slack-request.c + slack-request.h + slack-request.o + slack-teaminfo.c + slack-teaminfo.h + slack-teaminfo.o + slack-user.c + slack-user.h + slack-user.o + slack-workspace.c + slack-workspace.h + slack-workspace.o + slack.c + slack.h + slack.o +Copyright: __NO_COPYRIGHT_NOR_LICENSE__ +License: __NO_COPYRIGHT_NOR_LICENSE__ + +Files: libwebsockets/include/libwebsockets.h + libwebsockets/lib/context.c + libwebsockets/lib/event-libs/libev/libev.c + libwebsockets/lib/event-libs/libev/private.h + libwebsockets/lib/event-libs/libevent/libevent.c + libwebsockets/lib/event-libs/libevent/private.h + libwebsockets/lib/event-libs/libuv/libuv.c + libwebsockets/lib/event-libs/libuv/private.h + libwebsockets/lib/event-libs/poll/poll.c + libwebsockets/lib/event-libs/poll/private.h + libwebsockets/lib/libwebsockets.c + libwebsockets/lib/libwebsockets.h + libwebsockets/lib/misc/jws/jwk.c + libwebsockets/lib/misc/jws/jws.c + libwebsockets/lib/misc/lejp.c + libwebsockets/lib/misc/lws-ring.c + libwebsockets/lib/misc/peer-limits.c + libwebsockets/lib/output.c + libwebsockets/lib/plat/lws-plat-esp32.c + libwebsockets/lib/plat/lws-plat-unix.c + libwebsockets/lib/pollfd.c + libwebsockets/lib/private-libwebsockets.h + libwebsockets/lib/roles/cgi/cgi-server.c + libwebsockets/lib/roles/cgi/ops-cgi.c + libwebsockets/lib/roles/cgi/private.h + libwebsockets/lib/roles/h1/ops-h1.c + libwebsockets/lib/roles/h1/private.h + libwebsockets/lib/roles/h2/hpack.c + libwebsockets/lib/roles/h2/http2.c + libwebsockets/lib/roles/h2/ops-h2.c + libwebsockets/lib/roles/h2/private.h + libwebsockets/lib/roles/http/client/client.c + libwebsockets/lib/roles/http/header.c + libwebsockets/lib/roles/http/server/access-log.c + libwebsockets/lib/roles/http/server/lejp-conf.c + libwebsockets/lib/roles/http/server/lws-spa.c + libwebsockets/lib/roles/http/server/parsers.c + libwebsockets/lib/roles/http/server/ranges.c + libwebsockets/lib/roles/http/server/server.c + libwebsockets/lib/roles/listen/ops-listen.c + libwebsockets/lib/roles/pipe/ops-pipe.c + libwebsockets/lib/roles/raw/ops-raw.c + libwebsockets/lib/roles/ws/client-parser-ws.c + libwebsockets/lib/roles/ws/client-ws.c + libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c + libwebsockets/lib/roles/ws/ops-ws.c + libwebsockets/lib/roles/ws/private.h + libwebsockets/lib/roles/ws/server-ws.c + libwebsockets/lib/service.c + libwebsockets/lib/tls/mbedtls/lws-genhash.c + libwebsockets/lib/tls/mbedtls/lws-genrsa.c + libwebsockets/lib/tls/mbedtls/mbedtls-client.c + libwebsockets/lib/tls/mbedtls/mbedtls-server.c + libwebsockets/lib/tls/mbedtls/ssl.c + libwebsockets/lib/tls/openssl/lws-genhash.c + libwebsockets/lib/tls/openssl/lws-genrsa.c + libwebsockets/lib/tls/openssl/openssl-client.c + libwebsockets/lib/tls/openssl/openssl-server.c + libwebsockets/lib/tls/openssl/ssl.c + libwebsockets/lib/tls/private.h + libwebsockets/lib/tls/tls-client.c + libwebsockets/lib/tls/tls-server.c + libwebsockets/lib/tls/tls.c + libwebsockets/plugins/protocol_esp32_lws_ota.c + libwebsockets/plugins/ssh-base/include/lws-plugin-ssh.h + libwebsockets/plugins/ssh-base/include/lws-ssh.h + libwebsockets/plugins/ssh-base/kex-25519.c + libwebsockets/plugins/ssh-base/sshd.c + libwebsockets/plugins/ssh-base/telnet.c + libwebsockets/test-apps/test-lejp.c +Copyright: 2010-2018 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: json-c/fuzz/build.sh + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl3.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_code.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_dbg.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_lib.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_methods.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_types.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_x509.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/tls1.h + libwebsockets/lib/tls/mbedtls/wrapper/include/internal/x509_vfy.h + libwebsockets/lib/tls/mbedtls/wrapper/include/openssl/ssl.h + libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h + libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_port.h + libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_cert.c + libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_lib.c + libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_methods.c + libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_pkey.c + libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_stack.c + libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_x509.c + libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_pm.c + libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_port.c +Copyright: 2015-2016 Espressif Systems (Shanghai) PTE LTD + 2018 Google Inc. +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the complete text of the Apache License Version 2.0 + can be found in `/usr/share/common-licenses/Apache-2.0'. + +Files: json-c/tests/test_float.c + libwebsockets/READMEs/README.test-apps.md + libwebsockets/lib/misc/daemonize.c + libwebsockets/win32port/zlib/adler32.c + libwebsockets/win32port/zlib/compress.c + libwebsockets/win32port/zlib/gzguts.h + libwebsockets/win32port/zlib/gzlib.c + libwebsockets/win32port/zlib/gzread.c + libwebsockets/win32port/zlib/gzwrite.c + libwebsockets/win32port/zlib/inffast.c + libwebsockets/win32port/zlib/inftrees.c + libwebsockets/win32port/zlib/trees.c + libwebsockets/win32port/zlib/uncompr.c + libwebsockets/win32port/zlib/zconf.h + libwebsockets/win32port/zlib/zutil.c +Copyright: 1995-2010 Jean-loup Gailly + 1995-2010 Jean-loup Gailly. For conditions of distribution and use, see copyright notice in zlib.h + 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h + 2006-2013 Andy Green + 2010-2011 Andy Green licensed under LGPL2.1 Compiled with SSL support, not using it Listening on port 7681 server sees client connect accepted v06 connection Spamming 360 random fragments + 2016 Rainer Gerhards Released under ASL 2.0 +License: __NO_LICENSE__ + +Files: libwebsockets/lwsws/main.c + libwebsockets/plugins/protocol_lws_mirror.c + libwebsockets/plugins/protocol_lws_server_status.c + libwebsockets/plugins/protocol_lws_status.c + libwebsockets/test-apps/android/README + libwebsockets/test-apps/android/app/src/main/java/org/libwebsockets/client/LwsService.java + libwebsockets/test-apps/android/app/src/main/java/org/libwebsockets/client/MainActivity.java + libwebsockets/test-apps/android/app/src/main/java/org/libwebsockets/client/ThreadService.java + libwebsockets/test-apps/android/app/src/main/jni/LwsService.cpp + libwebsockets/test-apps/test-client.c + libwebsockets/test-apps/test-server-libev.c + libwebsockets/test-apps/test-server-libevent.c + libwebsockets/test-apps/test-server.c +Copyright: 2010-2018 Andy Green + 2016 Alexander Bruines +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + The person who associated a work with this deed has dedicated + the work to the public domain by waiving all of his or her rights + to the work worldwide under copyright law, including all related + and neighboring rights, to the extent allowed by law. You can copy, + modify, distribute and perform the work, even for commercial purposes, + all without asking permission. + . + The test apps are intended to be adapted for use in your code, which + may be proprietary. So unlike the library itself, they are licensed + Public Domain. + +Files: json-c/arraylist.c + json-c/arraylist.h + json-c/debug.c + json-c/json_c_version.c + json-c/json_object.c + json-c/json_object.h + json-c/json_tokener.h + json-c/json_util.c + json-c/linkhash.c + json-c/linkhash.h + json-c/random_seed.c +Copyright: 2004-2013 Metaparadigm Pte. Ltd. Michael Clark + 2009 Hewlett-Packard Development Company, L.P. + 2012 Eric Haszlakiewicz +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + +Files: libwebsockets/lib/misc/smtp.c + libwebsockets/plugins/generic-sessions/handlers.c + libwebsockets/plugins/generic-sessions/private-lwsgs.h + libwebsockets/plugins/generic-sessions/protocol_generic_sessions.c + libwebsockets/plugins/generic-sessions/protocol_lws_messageboard.c + libwebsockets/plugins/generic-sessions/utils.c + libwebsockets/plugins/generic-table/protocol_table_dirlisting.c +Copyright: 2010-2017 Andy Green +License: LGPL-2.1 + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + . + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: json-c/autoconf-archive/m4/libtool.m4 + json-c/autoconf-archive/m4/ltoptions.m4 + json-c/autoconf-archive/m4/ltsugar.m4 + json-c/autoconf-archive/m4/ltversion.m4 + json-c/autoconf-archive/m4/lt~obsolete.m4 +Copyright: 1996-2015 Free Software Foundation, Inc. +License: PERMISSIVE + This file is free software; the Free Software Foundation gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + +Files: libwebsockets/plugin-standalone/protocol_example_standalone.c + libwebsockets/plugins/protocol_client_loopback_test.c + libwebsockets/plugins/protocol_dumb_increment.c + libwebsockets/plugins/protocol_lws_sshd_demo.c + libwebsockets/plugins/protocol_post_demo.c +Copyright: 2010-2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + The person who associated a work with this deed has dedicated + the work to the public domain by waiving all of his or her rights + to the work worldwide under copyright law, including all related + and neighboring rights, to the extent allowed by law. You can copy, + modify, distribute and perform the work, even for commercial purposes, + all without asking permission. + . + These test plugins are intended to be adapted for use in your code, which + may be proprietary. So unlike the library itself, they are licensed + Public Domain. + +Files: json-c/autom4te.cache/output.0 + json-c/autom4te.cache/output.1 + json-c/autom4te.cache/output.2 + json-c/configure +Copyright: 1992-2012 Free Software Foundation, Inc. +License: PERMISSIVE + This configure script is free software; the Free Software Foundation + gives unlimited permission to copy, distribute and modify it. + +Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c + libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c + libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/protocol_lws_minimal_server_echo.c + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c +Copyright: 2010-2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + The protocol shows how to send and receive bulk messages over a ws connection + that optionally may have the permessage-deflate extension negotiated on it. + +Files: libwebsockets/win32port/zlib/deflate.h + libwebsockets/win32port/zlib/inffast.h + libwebsockets/win32port/zlib/inflate.h + libwebsockets/win32port/zlib/zutil.h +Copyright: 1995-2010 Jean-loup Gailly For conditions of distribution and use, see copyright notice in zlib.h + 1995-2010 Jean-loup Gailly. For conditions of distribution and use, see copyright notice in zlib.h + 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h +License: __UNKNOWN__ + WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + +Files: json-c/autoconf-archive/m4/ax_append_compile_flags.m4 + json-c/autoconf-archive/m4/ax_append_flag.m4 + json-c/autoconf-archive/m4/ax_check_compile_flag.m4 + json-c/autoconf-archive/m4/ax_compile_check_sizeof.m4 +Copyright: 2008 Guido U. Draheim + 2008 Kaveh Ghazi + 2011 Maarten Bosmans +License: GPL-3.0+ with unknown exception *** check multiple exceptions *** + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + Public License for more details. + . + You should have received a copy of the GNU General Public License along + with this program. If not, see . + . + As a special exception, the respective Autoconf Macro's copyright owner + gives unlimited permission to copy, distribute and modify the configure + scripts that are the output of Autoconf when processing the Macro. You + need not follow the terms of the GNU General Public License when using + or distributing such scripts, even though portions of the text of the + Macro appear in them. The GNU General Public License (GPL) does govern + all other use of the material that constitutes the Autoconf Macro. + . + This special exception to the GPL applies to versions of the Autoconf + Macro released by the Autoconf Archive. When you make and distribute a + modified version of the Autoconf Macro, you may extend this special + exception to the GPL to apply to your modified version as well. + . + On Debian systems, the complete text of the GNU General Public License + Version 3 can be found in `/usr/share/common-licenses/GPL-3'. + +Files: json-c/debug.h + json-c/json_object_private.h + json-c/random_seed.h +Copyright: 2004-2013 Metaparadigm Pte. Ltd. Michael Clark + 2009 Hewlett-Packard Development Company, L.P. +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + @brief Do not use, json-c internal, may be changed or removed at any time. + +Files: libwebsockets/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c + libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c + libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c +Copyright: 2010-2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + +Files: json-c/compile + json-c/missing + json-c/test-driver +Copyright: 1996-2014 Free Software Foundation, Inc. +License: GPL-2.0+ with autoconf exception + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program that contains a + configuration script generated by Autoconf, you may include it under + the same distribution terms that you use for the rest of that program. + . + On Debian systems, the complete text of the GNU General Public License + Version 2 can be found in `/usr/share/common-licenses/GPL-2'. + +Files: libwebsockets/lib/event-libs/private.h + libwebsockets/lib/roles/private.h +Copyright: 2010-2018 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + This is included from private-libwebsockets.h + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: libwebsockets/plugins/protocol_esp32_lws_group.c + libwebsockets/plugins/protocol_esp32_lws_scan.c +Copyright: 2017 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA* + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c + libwebsockets/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http server that can serve both normal static + content and server-side event connections. + . + To keep it simple, it serves the static stuff from the subdirectory + "./mount-origin" of the directory it was started in. + . + You can change that by changing mount.origin below. + +Files: libwebsockets/lib/roles/h2/minihuf.c + libwebsockets/lib/roles/http/minilex.c +Copyright: 2011-2014 Andy Green +License: __UNKNOWN__ + Licensed under LGPL2 + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/protocol_lws_minimal.c + libwebsockets/minimal-examples/ws-server/minimal-ws-server/protocol_lws_minimal.c +Copyright: 2010-2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This version holds a single message at a time, which may be lost if a new + message comes. See the minimal-ws-server-ring sample for the same thing + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c + libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/minimal-ws-server-pmd.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws. + . + To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + the directory it was started in. + You can change that by changing mount.origin. + +Files: json-c/json_pointer.c + json-c/json_visit.c +Copyright: 2016 Alexandru Ardelean. + 2016 Eric Haszlakiewicz +License: __UNKNOWN__ + This is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/minimal-http-server.c + libwebsockets/minimal-examples/http-server/minimal-http-server/minimal-http-server.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws. + . + To keep it simple, it serves stuff from the subdirectory + "./mount-origin" of the directory it was started in. + You can change that by changing mount.origin below. + +Files: json-c/json_tokener.c + json-c/printbuf.c +Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark + 2008-2009 Yahoo! Inc. +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + The copyrights to the contents of this file are licensed under the MIT License + (http://www.opensource.org/licenses/mit-license.php) + +Files: libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c + libwebsockets/minimal-examples/http-client/minimal-http-client/minimal-http-client.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the a minimal http client using lws. + . + It visits https://warmcat.com/ and receives the html page there. You + can dump the page data by changing the #if 0 below. + +Files: libwebsockets/lib/misc/romfs.c + libwebsockets/lib/misc/romfs.h +Copyright: 2017 National Institute of Advanced Industrial Science and Technology (AIST) +License: BSD-3-Clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + . + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + Neither the name of AIST nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + . + On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" + License can be found in `/usr/share/common-licenses/BSD'. + +Files: libwebsockets/win32port/win32helpers/getopt.c + libwebsockets/win32port/win32helpers/getopt_long.c +Copyright: 1987-1996 The Regents of the University of California. +License: BSD-4-Clause-UC + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +Files: json-c/Makefile.in + json-c/tests/Makefile.in +Copyright: 1994-2017 Free Software Foundation, Inc. +License: __AUTO_PERMISSIVE__ + Autogenerated files with permissive licenses. + +Files: json-c/install-sh +Copyright: 1994 X Consortium +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- + TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + . + Except as contained in this notice, the name of the X Consortium shall not + be used in advertising or otherwise to promote the sale, use or other deal- + ings in this Software without prior written authorization from the X Consor- + tium. + . + FSF changes to this file are in the public domain. + . + Calling this script install-sh is preferred over install.sh, to prevent + 'make' implicit rules from creating a file called install from it + when there is no Makefile. + . + This script is compatible with the BSD install script, but was written + from scratch. + +Files: libwebsockets/win32port/zlib/zlib.h +Copyright: 1995-2010 Jean-loup Gailly and Mark Adler +License: Zlib + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + . + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + . + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + . + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + . + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + +Files: libwebsockets/lib/misc/base64-decode.c +Copyright: __NO_COPYRIGHT__ in: libwebsockets/lib/misc/base64-decode.c +License: Expat + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, + subject to the following conditions: + . + The above copyright notice and this permission notice shall + be included in all copies or substantial portions of the + Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS + OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + . + VERSION HISTORY: + Bob Trower 08/04/01 -- Create Version 0.00.00B + . + I cleaned it up quite a bit to match the (linux kernel) style of the rest + of libwebsockets; this version is under LGPL2.1 + SLE like the rest of lws + since he explicitly allows sublicensing, but I give the URL above so you can + get the original with Bob's super-liberal terms directly if you prefer. + +Files: weechat-plugin.h +Copyright: 2003-2018 Sébastien Helleu +License: GPL-3.0+ + This file is part of WeeChat, the extensible chat client. + . + WeeChat is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + . + WeeChat is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with WeeChat. If not, see . + . + On Debian systems, the complete text of the GNU General Public License + Version 3 can be found in `/usr/share/common-licenses/GPL-3'. + +Files: libwebsockets/test-apps/fuzxy.c +Copyright: 2016 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + fuzxy is designed to go on the client path + . + [ client <-> fuzxy ] <-> server + . + you can arrange that with, eg, + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: libwebsockets/lib/roles/http/private.h +Copyright: 2010-2018 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + This is included from private-libwebsockets.h if either H1 or H2 roles are + enabled + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: libwebsockets/plugins/acme-client/protocol_lws_acme_client.c +Copyright: 2017 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + Acme is in a big messy transition at the moment from a homebrewed api + to an IETF one. The old repo for the homebrew api (they currently + implement) is marked up as deprecated and "not accurate[ly] reflect[ing]" + what they implement, but the IETF standard, currently at v7 is not yet + implemented at let's encrypt (ETA Jan 2018). + . + This implementation follows draft 7 of the IETF standard, and falls back + to whatever differences exist for Boulder's tls-sni-01 challenge. The + tls-sni-02 support is there but nothing to test it against at the time of + writing (Nov 1 2017). + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: libwebsockets/plugins/protocol_esp32_lws_reboot_to_factory.c +Copyright: 2017 Andy Green +License: LGPL-2.1 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + This is intended to be mounted somewhere in your ESP32 user app... if the + client touched the mount, the plugin hangs up and reboots into the + factory mode one second later. + . + The factory mode will reassociate with the same IP with the same MAC + shortly afterwards and be accessible by the same IP / mDNS name. + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: libwebsockets/lib/roles/http/server/fops-zip.c +Copyright: 2017 Andy Green + 2017 Per Bothner +License: LGPL-2.1 + MIT License + . + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + ( copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + . + lws rewrite: + . + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation: + version 2.1 of the License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU Lesser General Public License + Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +Files: json-c/autoconf-archive/m4/ax_require_defined.m4 +Copyright: 2014 Mike Frysinger +License: PERMISSIVE + Copying and distribution of this file, with or without modification, are + permitted in any medium without royalty provided the copyright notice + and this notice are preserved. This file is offered as-is, without any + warranty. + +Files: json-c/tests/Makefile +Copyright: 1994-2017 Free Software Foundation, Inc. +License: PERMISSIVE + This Makefile.in is free software; the Free Software Foundation + gives unlimited permission to copy and/or distribute it, + with or without modifications, as long as this notice is preserved. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY, to the extent permitted by law; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. + +Files: json-c/aclocal.m4 +Copyright: 1996-2017 Free Software Foundation, Inc. +License: PERMISSIVE + This file is free software; the Free Software Foundation + gives unlimited permission to copy and/or distribute it, + with or without modifications, as long as this notice is preserved. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY, to the extent permitted by law; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. + +Files: json-c/json_util.h +Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + @brief Miscllaneous utility functions and macros. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/http2.png +Copyright: __NO_COPYRIGHT__ in: libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/http2.png +License: __UNKNOWN__ + _MANY_NON_ASCII_(10chars. over 20chars.) starting with: 8—S¯×P*<ÎY‚@!„À{O + _MANY_NON_ASCII_(3chars. over 4chars.) starting with: ¡µ@© + R + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/minimal-http-server-basicauth.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http server with a second mount that + is protected using a password file and basic auth. + . + To keep it simple, it serves the static stuff from the subdirectory + "./mount-origin" of the directory it was started in. + . + You can change that by changing mount.origin below. + +Files: libwebsockets/minimal-examples/raw/minimal-raw-file/minimal-raw-file.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates adopting a file descriptor into the lws event + loop. + +Files: json-c/CMakeLists.txt +Copyright: __NO_COPYRIGHT__ in: json-c/CMakeLists.txt +License: __UNKNOWN__ + Licensed under the MIT license. See LICENSE file in the project root for full license information. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http server that performs POST with a couple + of parameters. It dumps the parameters to the console log and redirects + to another page. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http[s] server that can work with any of the + supported event loop backends, or the default poll() one. + . + To keep it simple, it serves stuff from the subdirectory + "./mount-origin" of the directory it was started in. + You can change that by changing mount.origin below. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws that + uses a libuv event loop created outside lws. It shows how lws can + participate in someone else's event loop and clean up after itself. + . + You choose the event loop to work with at runtime, by giving the + --uv, --event or --ev switch. Lws has to have been configured to build the + selected event lib support. + . + To keep it simple, it serves stuff from the subdirectory + "./mount-origin" of the directory it was started in. + You can change that by changing mount.origin below. + +Files: libwebsockets/win32port/zlib/crc32.c +Copyright: 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h +License: __UNKNOWN__ + Thanks to Rodney Brown for his contribution of faster + CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + tables for updating the shift register in one step with three exclusive-ors + instead of four steps with four exclusive-ors. This results in about a + factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + +Files: json-c/config.log +Copyright: 2017 Free Software Foundation, Inc. +License: __UNKNOWN__ + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +Files: libwebsockets/READMEs/README.coding.md +Copyright: __NO_COPYRIGHT__ in: libwebsockets/READMEs/README.coding.md +License: __UNKNOWN__ + For these reasons and the response I got trying to raise these issues with + them, if you have a choice about event loop, I would gently encourage you + to avoid libev. Where lws uses an event loop itself, eg in lwsws, we use + libuv. + . + @section extopts Extension option control from user code + . + User code may set per-connection extension options now, using a new api + +Files: json-c/config.status +Copyright: 2012 Free Software Foundation, Inc. +License: __UNKNOWN__ + This config.status script is free software; the Free Software Foundation + gives unlimited permission to copy, distribute and modify it." + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http server that can produce dynamic http + content as well as static content. + . + To keep it simple, it serves the static stuff from the subdirectory + "./mount-origin" of the directory it was started in. + . + You can change that by changing mount.origin below. + +Files: libwebsockets/win32port/zlib/inftrees.h +Copyright: 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h +License: __UNKNOWN__ + WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + . + Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. + +Files: libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates integrating somebody else's connected tcp + socket into the lws event loop as a RAW wsi. It's interesting in + the kind of situation where you already have a connected socket + in your application, and you need to hand it over to lws to deal with. + . + Lws supports "adopting" these foreign sockets. + . + If you simply want a connected client raw socket using lws alone, you + +Files: libwebsockets/test-apps/test-sshd.c +Copyright: 2017 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + The person who associated a work with this deed has dedicated + the work to the public domain by waiving all of his or her rights + to the work worldwide under copyright law, including all related + and neighboring rights, to the extent allowed by law. You can copy, + modify, distribute and perform the work, even for commercial purposes, + all without asking permission. + . + The test apps are intended to be adapted for use in your code, which + may be proprietary. So unlike the library itself, they are licensed + Public Domain. + . + This test app listens on port 2200 for authorized ssh connections. Run it + using + . + $ sudo libwebsockets-test-sshd + . + Connect to it using the test private key with: + . + $ ssh -p 2200 -i /usr/local/share/libwebsockets-test-server/lws-ssh-test-keys anyuser@127.0.0.1 + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/minimal-ws-server-echo.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a ws server that echoes back what it was sent, in a way + compatible with autobahn -m fuzzingclient + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-broker/minimal-ws-broker.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws, + with an added publish / broker / subscribe ws server. + . + To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + the directory it was started in. + You can change that by changing mount.origin. + +Files: libwebsockets/win32port/zlib/inflate.c +Copyright: 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h +License: __UNKNOWN__ + Change history: + . + 1.2.beta0 24 Nov 2002 + - First version -- complete rewrite of inflate to simplify code, avoid + creation of window when not needed, minimize use of window when it is + needed, make inffast.c even faster, implement gzip decoding, and to + improve code readability and style over the previous zlib inflate code + . + 1.2.beta1 25 Nov 2002 + - Use pointers for available input and output checking in inffast.c + - Remove input and output counters in inffast.c + +Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a ws client that sends bulk data in multiple + ws fragments, in a way compatible with per-message deflate. + . + It shows how to send huge messages without needing a lot of memory. + . + Build and start the minimal-examples/ws-server/minmal-ws-server-pmd-bulk + example first. Running this sends a large message to the server and + exits. + . + If you give both sides the -n commandline option, it disables permessage- + deflate compression extension. + +Files: json-c/printbuf.h +Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark + 2008-2009 Yahoo! Inc. +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + The copyrights to the contents of this file are licensed under the MIT License + (http://www.opensource.org/licenses/mit-license.php) + . + @brief Internal string buffer handing. Unless you're writing a + +Files: libwebsockets/cmake/FindGit.cmake +Copyright: Kitware Inc. +License: __UNKNOWN__ + See COPYRIGHT.txt + or http://www.slicer.org/copyright/copyright.txt for details. + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc. + and was partially funded by NIH grant 3P41RR013218-12S1 + . + AG 2013-02-18: I got it from here + https://github.com/Slicer/Slicer/blob/master/CMake/FindGit.cmake + license is BSD + . + The module defines the following variables: + +Files: json-c/json_c_version.h +Copyright: 2012-2017 Eric Haszlakiewicz +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + @brief Methods for retrieving the json-c version. + +Files: json-c/autom4te.cache/traces.0 +Copyright: 2011 Free Software Foundation, Inc. +License: __UNKNOWN__ + This config.lt script is free software; the Free Software Foundation + gives unlimited permision to copy, distribute and modify it." + +Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a ws "publisher" to go with the minimal-ws-broker + example. + . + Two threads are spawned that produce messages to be sent to the broker, + via a local ringbuffer. Locking is provided to make ringbuffer access + threadsafe. + . + When a nailed-up client connection to the broker is established, the + ringbuffer is sent to the broker, which distributes the events to all + connected clients. + +Files: libwebsockets/plugins/protocol_lws_raw_test.c +Copyright: 2010-2017 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + The person who associated a work with this deed has dedicated + the work to the public domain by waiving all of his or her rights + to the work worldwide under copyright law, including all related + and neighboring rights, to the extent allowed by law. You can copy, + modify, distribute and perform the work, even for commercial purposes, + all without asking permission. + . + These test plugins are intended to be adapted for use in your code, which + may be proprietary. So unlike the library itself, they are licensed + Public Domain. + . + This plugin test both raw file descriptors and raw socket descriptors. It + can test both or just one depending on how you configure it. libwebsockets- + test-server-v2.0 is set up to test both. + . + RAW File Descriptor Testing + +Files: libwebsockets/win32port/zlib/infback.c +Copyright: 1995-2009 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h +License: __UNKNOWN__ + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + +Files: libwebsockets/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the a minimal http client using lws and POST. + . + It POSTs both form data and a file to the form at + https://libwebsockets.org/testserver/formtest and dumps + the html page received generated by the POST handler. + +Files: libwebsockets/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates integrating a raw tcp listener into the lws event loop. + . + This demo doesn't have any http or ws support. You can connect to it + using netcat. If you make multiple connections to it, things typed in one + netcat session are broadcast to all netcat connections. + . + $ nc localhost 7681 + . + You can add more vhosts with things like http or ws support, it's as it is + for clarity. + . + The main point is the apis and ways of managing raw sockets are almost + identical to http or ws mode sockets in lws. The callback names for raw + wsi are changed to be specific to RAW mode is all. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http server that performs POST with a couple + of parameters and a file upload, all in multipart (mime) form mode. + It saves the uploaded file in the current directory, dumps the parameters to + the console log and redirects to another page. + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws, + with an added websocket chat server using a ringbuffer. + . + To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + the directory it was started in. + You can change that by changing mount.origin. + +Files: libwebsockets/test-apps/android/app/src/main/jni/NativeLibs.mk +Copyright: 2016 Alexander Bruines +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + The person who associated a work with this deed has dedicated + the work to the public domain by waiving all of his or her rights + to the work worldwide under copyright law, including all related + and neighboring rights, to the extent allowed by law. You can copy, + modify, distribute and perform the work, even for commercial purposes, + all without asking permission. + . + The test apps are intended to be adapted for use in your code, which + may be proprietary. So unlike the library itself, they are licensed + Public Domain. + . + This makefile is fully intergrated with this Android Studio project and + it will be called automaticaly when you build the project with Gradle. + . + The source packages for the libraries will be automaticaly downloaded. + Alternativly you can provide your own sources by placing the following + files in the 'jni' directory: + . + zlib-1.2.8.tar.gz + openssl-1.0.2g.tar.gz + libwebsockets.tar.gz + . + This makefile was tested with the latest NDK/SDK and Android Studio at the + time of this writing. As these software packages evolve changes to this + makefile may be needed or it may become obselete... + . + This makefile was made for use in Linux but you may be able to edit it + and make it work under Windows. + . + At least on Debian, building openssl requires package xutils-dev + for makedepend. Ofcourse the standard development packages must also be + installed, but xutils-dev is not that obvious in this case... + . + Makedepend will most likely print a lot of warnings during the 'make depend' + stage of building openssl. In this case these warnings can be safely ignored. + . + Include Application.mk but do not complain if it is not found + +Files: json-c/json.h +Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark + 2009 Hewlett-Packard Development Company, L.P. +License: __UNKNOWN__ + This library is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + @brief A convenience header that may be included instead of other individual ones. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/minimal-http-server-form-get.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal http server that performs a form GET with a couple + of parameters. It dumps the parameters to the console log and redirects + to another page. + +Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/minimal-ws-client-echo.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a ws client that echoes back what it was sent, in a + way compatible with autobahn -m fuzzingserver + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal multithreaded http server you can make with lws. + . + To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + the directory it was started in. + You can change that by changing mount.origin. + . + Also for simplicity the number of threads is set in the code... note that + +Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the a minimal ws client using lws. + . + It connects to https://libwebsockets.org/ and makes a + wss connection to the dumb-increment protocol there. While + connected, it prints the numbers it is being sent by + dumb-increment protocol. + +Files: libwebsockets/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the a minimal http client using lws, which makes + 8 downloads simultaneously from warmcat.com. + . + Currently that takes the form of 8 individual simultaneous tcp and + tls connections, which happen concurrently. Notice that the ordering + of the returned payload may be intermingled for the various connections. + . + By default the connections happen all together at the beginning and operate + concurrently, which is fast. However this is resource-intenstive, there are + 8 tcp connections, 8 tls tunnels on both the client and server. You can + instead opt to have the connections happen one after the other inside a + single tcp connection and tls tunnel, using HTTP/1.1 pipelining. To be + eligible to be pipelined on another existing connection to the same server, + +Files: libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the a minimal http client using lws. + +Files: libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates integrating a connected udp + socket into the lws event loop as a RAW wsi. It's interesting in + the kind of situation where you already have a connected socket + in your application, and you need to hand it over to lws to deal with. + . + Lws supports "adopting" these foreign sockets, and also has a helper API + to create, bind, and adopt them inside lws. + +Files: libwebsockets/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws, + with three extra lines giving it tls (ssl) capabilities, which in + turn allow operation with HTTP/2 if lws was configured for it. + . + To keep it simple, it serves stuff from the subdirectory + "./mount-origin" of the directory it was started in. + . + You can change that by changing mount.origin below. + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c +Copyright: 2010-2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This implements a minimal "broker", for systems that look like this + . + [ publisher ws client ] <-> [ ws server broker ws server ] <-> [ ws client subscriber ] + . + The "publisher" role is to add data to the broker. + . + The "subscriber" role is to hear about all data added to the system. + . + The "broker" role is to manage incoming data from publishers and pass it out + to subscribers. + . + Any number of publishers and subscribers are supported. + . + This example implements a single ws server, using one ws protocol, that treats ws + connections as being in publisher or subscriber mode according to the URL the ws + connection was made to. ws connections to "/publisher" URL are understood to be + publishing data and to any other URL, subscribing. + +Files: libwebsockets/win32port/zlib/deflate.c +Copyright: 1995-2010 Jean-loup Gailly and Mark Adler For conditions of distribution and use, see copyright notice in zlib.h +License: __UNKNOWN__ + ALGORITHM + . + The "deflation" process depends on being able to identify portions + of the input text which are identical to earlier input (within a + sliding window trailing behind the input currently being processed). + . + The most straightforward technique turns out to be the fastest for + most input files: try all possible matches and select the longest. + The key feature of this algorithm is that insertions into the string + dictionary are very simple and thus fast, and deletions are avoided + completely. Insertions are performed at each input character, whereas + string matches are performed only when the previous match ends. So it + is preferable to spend more time in matches to allow very fast string + insertions and avoid deletions. The matching algorithm for small + strings is inspired from that of Rabin & Karp. A brute force approach + is used to find longer strings when a small match has been found. + A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + (by Leonid Broukhis). + A previous version of this file used a more sophisticated algorithm + (by Fiala and Greene) which is guaranteed to run in linear amortized + time, but has a larger average cost, uses more memory and is patented. + However the F&G algorithm may be faster for some highly redundant + +Files: json-c/json_pointer.h +Copyright: 2016 Alexadru Ardelean. +License: __UNKNOWN__ + This is free software; you can redistribute it and/or modify + it under the terms of the MIT license. See COPYING for details. + . + @brief JSON Pointer (RFC 6901) implementation for retrieving + objects from a json-c object tree. + +Files: libwebsockets/minimal-examples/client-server/minimal-ws-proxy/minimal-ws-proxy.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws, + with an added websocket proxy distributing what is received on a + dumb-increment wss connection to https://libwebsockets.org to all + browsers connected to this server. + . + To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + the directory it was started in. + You can change that by changing mount.origin. + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates a minimal ws server that can cooperate with + other threads cleanly. Two other threads are started, which fill + a ringbuffer with strings at 10Hz. + . + The actual work and thread spawning etc are done in the protocol + +Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c +Copyright: 2018 Andy Green +License: __UNKNOWN__ + This file is made available under the Creative Commons CC0 1.0 + Universal Public Domain Dedication. + . + This demonstrates the most minimal http server you can make with lws, + with an added websocket chat server. + . + To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + the directory it was started in. + You can change that by changing mount.origin. + +Files: libwebsockets/lib/misc/getifaddrs.c +Copyright: 2000-2001 Kungliga Tekniska H�gskolan (Royal Institute of Technology, Stockholm, Sweden). +License: BSD-3-Clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + . + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + . + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + . + 3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + . + originally downloaded from + . + http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c + . + On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" + License can be found in `/usr/share/common-licenses/BSD'. + +Files: libwebsockets/lib/misc/getifaddrs.h +Copyright: 2000 Kungliga Tekniska H�gskolan (Royal Institute of Technology, Stockholm, Sweden). +License: BSD-3-Clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + . + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + . + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + . + 3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + . + $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ + . + On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" + License can be found in `/usr/share/common-licenses/BSD'. + +Files: libwebsockets/lib/misc/sha-1.c +Copyright: 1995-1997 and 1998 WIDE Project. +License: BSD-3-Clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + . + FIPS pub 180-1: Secure Hash Algorithm (SHA-1) + based on: http://csrc.nist.gov/fips/fip180-1.txt + implemented by Jun-ichiro itojun Itoh + . + On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" + License can be found in `/usr/share/common-licenses/BSD'. + +Files: json-c/libtool +Copyright: 2014 Free Software Foundation, Inc. +License: GPL-2.0 with libtool exception + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + . + GNU Libtool is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of of the License, or + (at your option) any later version. + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program or library that is built + using GNU Libtool, you may include this file under the same + distribution terms that you use for the rest of that program. + . + GNU Libtool is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + The names of the tagged configurations supported by this script. + . + On Debian systems, the complete text of the GNU General Public License + Version 2 can be found in `/usr/share/common-licenses/GPL-2'. + +Files: json-c/ltmain.sh +Copyright: 1996-2015 Free Software Foundation, Inc. +License: GPL-2.0+ with libtool exception + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + . + GNU Libtool is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + As a special exception to the GNU General Public License, + if you distribute this file as part of a program or library that + is built using GNU Libtool, you may include this file under the + same distribution terms that you use for the rest of that program. + . + GNU Libtool is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + On Debian systems, the complete text of the GNU General Public License + Version 2 can be found in `/usr/share/common-licenses/GPL-2'. + +Files: json-c/depcomp +Copyright: 1999-2017 Free Software Foundation, Inc. +License: GPL-2.0+ with autoconf exception + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program that contains a + configuration script generated by Autoconf, you may include it under + the same distribution terms that you use for the rest of that program. + . + Originally written by Alexandre Oliva . + . + On Debian systems, the complete text of the GNU General Public License + Version 2 can be found in `/usr/share/common-licenses/GPL-2'. + +Files: json-c/config.guess +Copyright: 1992-2016 Free Software Foundation, Inc. +License: GPL-3.0+ with autoconf exception + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program; if not, see . + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program that contains a + configuration script generated by Autoconf, you may include it under + the same distribution terms that you use for the rest of that + program. This Exception is an additional permission under section 7 + of the GNU General Public License, version 3 ("GPLv3"). + . + Originally written by Per Bothner; maintained since 2000 by Ben Elliston. + . + On Debian systems, the complete text of the GNU General Public License + Version 3 can be found in `/usr/share/common-licenses/GPL-3'. + +Files: json-c/config.sub +Copyright: 1992-2016 Free Software Foundation, Inc. +License: GPL-3.0+ with autoconf exception + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program; if not, see . + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program that contains a + configuration script generated by Autoconf, you may include it under + the same distribution terms that you use for the rest of that + program. This Exception is an additional permission under section 7 + of the GNU General Public License, version 3 ("GPLv3"). + . + On Debian systems, the complete text of the GNU General Public License + Version 3 can be found in `/usr/share/common-licenses/GPL-3'. + +#---------------------------------------------------------------------------- +# xml and html files (skipped): +# json-c/README.html +# libwebsockets/minimal-examples/client-server/minimal-ws-proxy/mount-origin/index.html +# libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/index.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-secret-origin/index.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/index.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/after-form1.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/after-form1.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/after-form1.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/404.html +# libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/404.html +# libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/mount-origin/index.html +# libwebsockets/plugins/server-status.html +# libwebsockets/plugins/generic-sessions/assets/post-register-ok.html +# libwebsockets/plugins/generic-sessions/assets/post-verify-ok.html +# libwebsockets/plugins/generic-sessions/assets/admin-login.html +# libwebsockets/plugins/generic-sessions/assets/failed-login.html +# libwebsockets/plugins/generic-sessions/assets/post-forgot-ok.html +# libwebsockets/plugins/generic-sessions/assets/post-forgot-fail.html +# libwebsockets/plugins/generic-sessions/assets/lwsgs.js +# libwebsockets/plugins/generic-sessions/assets/post-verify-fail.html +# libwebsockets/plugins/generic-sessions/assets/successful-login.html +# libwebsockets/plugins/generic-sessions/assets/sent-forgot-fail.html +# libwebsockets/plugins/generic-sessions/assets/index.html +# libwebsockets/plugins/generic-table/assets/index.html +# libwebsockets/test-apps/test.html +# libwebsockets/test-apps/android/app/app.iml +# libwebsockets/test-apps/android/app/src/main/AndroidManifest.xml +# libwebsockets/test-apps/android/app/src/main/res/layout/activity_main.xml +# libwebsockets/test-apps/android/app/src/main/res/values/colors.xml +# libwebsockets/test-apps/android/app/src/main/res/values/dimens.xml +# libwebsockets/test-apps/android/app/src/main/res/values/strings.xml +# libwebsockets/test-apps/android/app/src/main/res/values/styles.xml + +#---------------------------------------------------------------------------- +# huge files (skipped): +# cscope.out +# cscope.in.out +# cscope.po.out +# slack.so +# libwebsockets/lib/libwebsockets.a +# libwebsockets/test-apps/leaf.jpg + +#---------------------------------------------------------------------------- +# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following +# license/copyright files. + +#---------------------------------------------------------------------------- +# License file: LICENSE + Mozilla Public License Version 2.0 + ================================== + . + 1. Definitions + -------------- + . + 1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + . + 1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + . + 1.3. "Contribution" + means Covered Software of a particular Contributor. + . + 1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + . + 1.5. "Incompatible With Secondary Licenses" + means + . + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + . + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + . + 1.6. "Executable Form" + means any form of the work other than Source Code Form. + . + 1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + . + 1.8. "License" + means this document. + . + 1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + . + 1.10. "Modifications" + means any of the following: + . + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + . + (b) any new file in Source Code Form that contains any Covered + Software. + . + 1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + . + 1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + . + 1.13. "Source Code Form" + means the form of the work preferred for making modifications. + . + 1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + . + 2. License Grants and Conditions + -------------------------------- + . + 2.1. Grants + . + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + . + (a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + . + (b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + . + 2.2. Effective Date + . + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + . + 2.3. Limitations on Grant Scope + . + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + . + (a) for any code that a Contributor has removed from Covered Software; + or + . + (b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + . + (c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + . + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + . + 2.4. Subsequent Licenses + . + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + . + 2.5. Representation + . + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights + to grant the rights to its Contributions conveyed by this License. + . + 2.6. Fair Use + . + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + . + 2.7. Conditions + . + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted + in Section 2.1. + . + 3. Responsibilities + ------------------- + . + 3.1. Distribution of Source Form + . + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + . + 3.2. Distribution of Executable Form + . + If You distribute Covered Software in Executable Form then: + . + (a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + . + (b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + . + 3.3. Distribution of a Larger Work + . + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + . + 3.4. Notices + . + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, + or limitations of liability) contained within the Source Code Form of + the Covered Software, except that You may alter any license notices to + the extent required to remedy known factual inaccuracies. + . + 3.5. Application of Additional Terms + . + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + . + 4. Inability to Comply Due to Statute or Regulation + --------------------------------------------------- + . + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Software due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description must + be placed in a text file included with all distributions of the Covered + Software under this License. Except to the extent prohibited by statute + or regulation, such description must be sufficiently detailed for a + recipient of ordinary skill to be able to understand it. + . + 5. Termination + -------------- + . + 5.1. The rights granted under this License will terminate automatically + if You fail to comply with any of its terms. However, if You become + compliant, then the rights granted under this License from a particular + Contributor are reinstated (a) provisionally, unless and until such + Contributor explicitly and finally terminates Your grants, and (b) on an + ongoing basis, if such Contributor fails to notify You of the + non-compliance by some reasonable means prior to 60 days after You have + come back into compliance. Moreover, Your grants from a particular + Contributor are reinstated on an ongoing basis if such Contributor + notifies You of the non-compliance by some reasonable means, this is the + first time You have received notice of non-compliance with this License + from such Contributor, and You become compliant prior to 30 days after + Your receipt of the notice. + . + 5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + . + 5.3. In the event of termination under Sections 5.1 or 5.2 above, all + end user license agreements (excluding distributors and resellers) which + have been validly granted by You or Your distributors under this License + prior to termination shall survive termination. + . + ************************************************************************ + * * + * 6. Disclaimer of Warranty * + * ------------------------- * + * * + * Covered Software is provided under this License on an "as is" * + * basis, without warranty of any kind, either expressed, implied, or * + * statutory, including, without limitation, warranties that the * + * Covered Software is free of defects, merchantable, fit for a * + * particular purpose or non-infringing. The entire risk as to the * + * quality and performance of the Covered Software is with You. * + * Should any Covered Software prove defective in any respect, You * + * (not any Contributor) assume the cost of any necessary servicing, * + * repair, or correction. This disclaimer of warranty constitutes an * + * essential part of this License. No use of any Covered Software is * + * authorized under this License except under this disclaimer. * + * * + ************************************************************************ + . + ************************************************************************ + * * + * 7. Limitation of Liability * + * -------------------------- * + * * + * Under no circumstances and under no legal theory, whether tort * + * (including negligence), contract, or otherwise, shall any * + * Contributor, or anyone who distributes Covered Software as * + * permitted above, be liable to You for any direct, indirect, * + * special, incidental, or consequential damages of any character * + * including, without limitation, damages for lost profits, loss of * + * goodwill, work stoppage, computer failure or malfunction, or any * + * and all other commercial damages or losses, even if such party * + * shall have been informed of the possibility of such damages. This * + * limitation of liability shall not apply to liability for death or * + * personal injury resulting from such party's negligence to the * + * extent applicable law prohibits such limitation. Some * + * jurisdictions do not allow the exclusion or limitation of * + * incidental or consequential damages, so this exclusion and * + * limitation may not apply to You. * + * * + ************************************************************************ + . + 8. Litigation + ------------- + . + Any litigation relating to this License may be brought only in the + courts of a jurisdiction where the defendant maintains its principal + place of business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. + Nothing in this Section shall prevent a party's ability to bring + cross-claims or counter-claims. + . + 9. Miscellaneous + ---------------- + . + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides + that the language of a contract shall be construed against the drafter + shall not be used to construe this License against a Contributor. + . + 10. Versions of the License + --------------------------- + . + 10.1. New Versions + . + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + . + 10.2. Effect of New Versions + . + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + . + 10.3. Modified Versions + . + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + . + 10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses + . + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + . + Exhibit A - Source Code Form License Notice + ------------------------------------------- + . + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 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/. + . + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to look + for such a notice. + . + You may add additional accurate notices of copyright ownership. + . + Exhibit B - "Incompatible With Secondary Licenses" Notice + --------------------------------------------------------- + . + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/debian/debhelper-build-stamp b/debian/debhelper-build-stamp new file mode 100644 index 0000000..a1dc01d --- /dev/null +++ b/debian/debhelper-build-stamp @@ -0,0 +1 @@ +weechat-slack diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..c564dbf --- /dev/null +++ b/debian/rules @@ -0,0 +1,18 @@ +#!/usr/bin/make -f +# You must remove unused comment lines for the released package. +#export DH_VERBOSE = 1 +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed +export JAVA_HOME=/usr/lib/jvm/default-java +export CLASSPATH=/usr/share/java/csv.jar:/usr/share/java/debug-disable.jar:/usr/share/java/itext.jar + +%: + dh $@ --without autoreconf + + +#override_dh_auto_install: +# dh_auto_install -- prefix=/usr + +#override_dh_install: +# dh_install --list-missing -X.pyc -X.pyo diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index 9fb90aa..edb6b81 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -29,10 +29,13 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work return 1; } +static const struct lws_protocols protocols[]; + static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; int status; @@ -45,7 +48,26 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, _("%s%s: (%d) error connecting to slack: %s"), weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, in ? (char *)in : "(null)"); - request->client_wsi = NULL; + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); break; case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: diff --git a/request/slack-request-chat-postmessage.c b/request/slack-request-chat-postmessage.c index 4ca8a35..635ebea 100644 --- a/request/slack-request-chat-postmessage.c +++ b/request/slack-request-chat-postmessage.c @@ -29,10 +29,13 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work return 1; } +static const struct lws_protocols protocols[]; + static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; int status; @@ -45,7 +48,26 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, _("%s%s: (%d) error connecting to slack: %s"), weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, in ? (char *)in : "(null)"); - request->client_wsi = NULL; + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); break; case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: diff --git a/request/slack-request-conversations-members.c b/request/slack-request-conversations-members.c new file mode 100644 index 0000000..53192b1 --- /dev/null +++ b/request/slack-request-conversations-members.c @@ -0,0 +1,326 @@ +#include +#include +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-channel.h" +#include "../slack-request.h" +#include "../slack-user.h" +#include "../request/slack-request-conversations-members.h" + +static const char *const endpoint = "/api/conversations.members?" + "token=%s&channel=%s&cursor=%s&limit=100"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error retrieving members: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + //__asm__("int3"); + return 0; + } + + return 1; +} + +static const struct lws_protocols protocols[]; + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; + struct t_slack_channel *channel; + const char *channelid; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + in ? (char *)in : "(null)"); + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) retrieving members... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + char cursor[64]; + json_object *response, *ok, *error, *members; + json_object *user, *metadata, *next_cursor; + struct t_json_chunk *chunk_ptr; + + channelid = (const char *)request->pointer; + channel = slack_channel_search(request->workspace, channelid); + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + members = json_object_object_get(response, "members"); + if (!json_valid(members, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + for (i = json_object_array_length(members); i > 0; i--) + { + user = json_object_array_get_idx(members, i - 1); + if (!json_valid(user, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + slack_channel_add_member(request->workspace, + channel, + json_object_get_string(user)); + } + + metadata = json_object_object_get(response, "response_metadata"); + if (!json_valid(metadata, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + next_cursor = json_object_object_get(metadata, "next_cursor"); + if (!json_valid(next_cursor, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor)); + + if (cursor[0]) + { + struct t_slack_request *next_request; + + next_request = slack_request_conversations_members(request->workspace, + weechat_config_string( + request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + channelid, + cursor); + if (next_request) + slack_workspace_register_request(request->workspace, next_request); + } + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) failed to retrieve users: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + /* fallthrough */ + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_conversations_members( + struct t_slack_workspace *workspace, + const char *token, const char *channel, + const char *cursor) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + request->pointer = channel; + + size_t urilen = snprintf(NULL, 0, endpoint, token, channel, cursor) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token, channel, cursor); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-conversations-members.h b/request/slack-request-conversations-members.h new file mode 100644 index 0000000..bdf750f --- /dev/null +++ b/request/slack-request-conversations-members.h @@ -0,0 +1,9 @@ +#ifndef _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_ +#define _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_ + +struct t_slack_request *slack_request_conversations_members( + struct t_slack_workspace *workspace, + const char *token, const char *channel, + const char *cursor); + +#endif /*SLACK_REQUEST_CONVERSATIONS_MEMBERS_H*/ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index 85814bb..e344b49 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -6,8 +6,10 @@ #include "../weechat-plugin.h" #include "../slack.h" #include "../slack-workspace.h" +#include "../slack-channel.h" #include "../slack-request.h" #include "../slack-user.h" +#include "../request/slack-request-conversations-members.h" #include "../request/slack-request-users-list.h" static const char *const endpoint = "/api/users.list?" @@ -29,10 +31,13 @@ static inline int json_valid(json_object *object, struct t_slack_workspace *work return 1; } +static const struct lws_protocols protocols[]; + static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; int status; @@ -45,7 +50,26 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, _("%s%s: (%d) error connecting to slack: %s"), weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, in ? (char *)in : "(null)"); - request->client_wsi = NULL; + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); break; case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: @@ -230,6 +254,23 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, if (next_request) slack_workspace_register_request(request->workspace, next_request); } + else + { + struct t_slack_request *next_request; + struct t_slack_channel *ptr_channel; + + for (ptr_channel = request->workspace->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + next_request = slack_request_conversations_members(request->workspace, + weechat_config_string( + request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + ptr_channel->id, + cursor); + if (next_request) + slack_workspace_register_request(request->workspace, next_request); + } + } } else { diff --git a/slack-channel.c b/slack-channel.c index 87a3b6b..f78b646 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -515,3 +515,29 @@ void slack_channel_update_purpose(struct t_slack_channel *channel, channel->purpose.creator = (creator) ? strdup(creator) : NULL; channel->purpose.last_set = last_set; } + +struct t_slack_channel_member *slack_channel_add_member( + struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + const char *id) +{ + struct t_slack_channel_member *member; + struct t_slack_user *user; + + member = malloc(sizeof(struct t_slack_channel_member)); + member->id = strdup(id); + + 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; + + user = slack_user_search(workspace, id); + if (user) + slack_user_nicklist_add(workspace, channel, user); + + return member; +} diff --git a/slack-channel.h b/slack-channel.h index 4c94511..06c2afb 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -121,4 +121,9 @@ void slack_channel_update_purpose(struct t_slack_channel *channel, const char* creator, int last_set); +struct t_slack_channel_member *slack_channel_add_member( + struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + const char *id); + #endif /*SLACK_CHANNEL_H*/ diff --git a/slack-request.h b/slack-request.h index 9416a71..88c5ee2 100644 --- a/slack-request.h +++ b/slack-request.h @@ -7,6 +7,9 @@ struct t_slack_request int idx; + const void *pointer; + void *data; + char *uri; struct lws *client_wsi; struct lws_context *context; diff --git a/slack-user.h b/slack-user.h index 1cd18e2..8525bb3 100644 --- a/slack-user.h +++ b/slack-user.h @@ -56,4 +56,8 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, void slack_user_free_all(struct t_slack_workspace *workspace); +void slack_user_nicklist_add(struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + struct t_slack_user *user); + #endif /*SLACK_USER_H*/ diff --git a/slack-workspace.c b/slack-workspace.c index 6b0a4af..c806a82 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -846,6 +846,12 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call free(ptr_request->uri); ptr_request->uri = NULL; } + ptr_request->pointer = NULL; + if (ptr_request->data) + { + free(ptr_request->data); + ptr_request->data = NULL; + } /* remove request from requests list */ if (ptr_workspace->last_request == ptr_request) diff --git a/slack.c b/slack.c index 0a81640..32c5614 100644 --- a/slack.c +++ b/slack.c @@ -45,9 +45,9 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_plugin = plugin; - lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO | LLL_DEBUG + lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE /*| LLL_INFO | LLL_DEBUG | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT - | LLL_LATENCY | LLL_USER | LLL_COUNT, + | LLL_LATENCY | LLL_USER | LLL_COUNT*/, slack_lwsl_emit_weechat); if (!slack_config_init()) From 9d4be2e31d29cc92068d174892d54bd09418ccbb Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Tue, 8 May 2018 22:02:17 +0100 Subject: [PATCH 017/118] Bot messages --- .dir-locals.el | 15 ++ Makefile | 3 +- api/message/slack-api-message-bot-message.c | 99 ++++++++ api/message/slack-api-message-bot-message.h | 8 + api/slack-api-message.c | 7 +- request/slack-request-bots-info.c | 268 ++++++++++++++++++++ request/slack-request-bots-info.h | 8 + request/slack-request-users-list.c | 35 +-- slack-user.c | 38 ++- slack-user.h | 7 +- 10 files changed, 462 insertions(+), 26 deletions(-) create mode 100644 .dir-locals.el create mode 100644 api/message/slack-api-message-bot-message.c create mode 100644 api/message/slack-api-message-bot-message.h create mode 100644 request/slack-request-bots-info.c create mode 100644 request/slack-request-bots-info.h diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..46be8ac --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,15 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((c-mode + (eval . (setq-local flycheck-clang-include-path + (list (expand-file-name "libwebsockets/include" (projectile-project-root)) + (expand-file-name "json-c" (projectile-project-root))))) + (eval . (setq-local company-clang-arguments + (list (concat "-I" (expand-file-name "libwebsockets/include" (projectile-project-root))) + (concat "-I" (expand-file-name "json-c" (projectile-project-root)))))) + (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) + (flycheck-clang-language-standard . "gnu99") + (flycheck-checker . c/c++-clang) + (projectile-project-compilation-cmd . "scan-build-3.8 make -j8"))) + diff --git a/Makefile b/Makefile index c9305d0..5f9704a 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ SRCS=slack.c \ api/slack-api-error.c \ api/slack-api-message.c \ api/slack-api-user-typing.c \ + api/message/slack-api-message-bot-message.c \ api/message/slack-api-message-unimplemented.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ @@ -65,7 +66,7 @@ install: slack.so tags: ctags -f .git/tags -R *.c *.h - + cs: cscope -RUbq diff --git a/api/message/slack-api-message-bot-message.c b/api/message/slack-api-message-bot-message.c new file mode 100644 index 0000000..1036afb --- /dev/null +++ b/api/message/slack-api-message-bot-message.c @@ -0,0 +1,99 @@ +#include +#include + +#include "../../weechat-plugin.h" +#include "../../slack.h" +#include "../../slack-workspace.h" +#include "../../slack-message.h" +#include "../../slack-api.h" +#include "../../slack-channel.h" +#include "../../slack-user.h" +#include "../slack-api-message.h" + +static const char *subtype = "bot_message"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %smessage.%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), subtype, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_bot_message_handle(struct t_slack_workspace *workspace, + const char *channel, const char *bot_id, + const char *username, const char *text, + const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_bot_search(workspace, bot_id); + if (!ptr_user) + return 1; /* silently ignore if bot user hasn't been loaded yet */ + + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message,slack_bot_message", + _("%s%s"), + slack_user_as_prefix(workspace, ptr_user, username), + message); + free(message); + + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + + return 1; +} + +int slack_api_message_bot_message(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *channel, *bot_id, *username, *text, *ts; + channel = json_object_object_get(message, "channel"); + if (!json_valid(channel, workspace)) + return 0; + + bot_id = json_object_object_get(message, "bot_id"); + if (!json_valid(bot_id, workspace)) + return 0; + + username = json_object_object_get(message, "username"); + if (!json_valid(username, workspace)) + return 0; + + text = json_object_object_get(message, "text"); + if (!json_valid(text, workspace)) + return 0; + + ts = json_object_object_get(message, "ts"); + if (!json_valid(ts, workspace)) + return 0; + + return slack_api_message_bot_message_handle(workspace, + json_object_get_string(channel), + json_object_get_string(bot_id), + json_object_get_string(username), + json_object_get_string(text), + json_object_get_string(ts)); +} + diff --git a/api/message/slack-api-message-bot-message.h b/api/message/slack-api-message-bot-message.h new file mode 100644 index 0000000..a567f22 --- /dev/null +++ b/api/message/slack-api-message-bot-message.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_API_MESSAGE_BOT_MESSAGE_H_ +#define _SLACK_API_MESSAGE_BOT_MESSAGE_H_ + +int slack_api_message_bot_message( + struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_MESSAGE_BOT_MESSAGE_H*/ diff --git a/api/slack-api-message.c b/api/slack-api-message.c index ae6010c..c181e10 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -10,6 +10,7 @@ #include "../slack-message.h" #include "slack-api-message.h" #include "message/slack-api-message-unimplemented.h" +#include "message/slack-api-message-bot-message.h" static const char *type = "message"; @@ -21,7 +22,7 @@ struct stringcase }; static struct stringcase cases[] = -{ { "bot_message", &slack_api_message_unimplemented } +{ { "bot_message", &slack_api_message_bot_message } , { "channel_archive", &slack_api_message_unimplemented } , { "channel_join", &slack_api_message_unimplemented } , { "channel_leave", &slack_api_message_unimplemented } @@ -97,10 +98,10 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, (time_t)atof(ts), "slack_message", _("%s%s"), - slack_user_as_prefix(workspace, ptr_user), + slack_user_as_prefix(workspace, ptr_user, NULL), message); free(message); - + ptr_typing = slack_channel_typing_search(ptr_channel, ptr_user->profile.display_name); if (ptr_typing) diff --git a/request/slack-request-bots-info.c b/request/slack-request-bots-info.c new file mode 100644 index 0000000..bd04431 --- /dev/null +++ b/request/slack-request-bots-info.c @@ -0,0 +1,268 @@ +#include +#include +#include +#include + +#include "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-channel.h" +#include "../slack-request.h" +#include "../slack-user.h" +#include "../request/slack-request-bots-info.h" + +static const char *const endpoint = "/api/bots.info?" + "token=%s&bot=%s"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error retrieving bot info: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + //__asm__("int3"); + return 0; + } + + return 1; +} + +static const struct lws_protocols protocols[]; + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + in ? (char *)in : "(null)"); + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) retrieving bot info... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + char cursor[64]; + json_object *response, *ok, *error, *members, *metadata; + json_object *user, *id, *name, *profile, *display_name, *next_cursor; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + // TODO: this + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) failed to retrieve users: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + /* fallthrough */ + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_bots_info( + struct t_slack_workspace *workspace, + const char *token, const char *cursor) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + + size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token, cursor); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-bots-info.h b/request/slack-request-bots-info.h new file mode 100644 index 0000000..ca23334 --- /dev/null +++ b/request/slack-request-bots-info.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_REQUEST_BOTS_INFO_H_ +#define _SLACK_REQUEST_BOTS_INFO_H_ + +struct t_slack_request *slack_request_bots_info( + struct t_slack_workspace *workspace, + const char *token, const char *cursor); + +#endif /*SLACK_REQUEST_BOTS_INFO_H*/ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index e344b49..d986fc6 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -123,8 +123,10 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, int chunk_count, i; char *json_string; char cursor[64]; - json_object *response, *ok, *error, *members, *metadata; - json_object *user, *id, *name, *profile, *display_name, *next_cursor; + json_object *response, *ok, *error, *members; + json_object *user, *id, *name; + json_object *profile, *display_name, *bot_id; + json_object *metadata, *next_cursor; struct t_json_chunk *chunk_ptr; chunk_count = 0; @@ -184,46 +186,45 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, user = json_object_array_get_idx(members, i - 1); if (!json_valid(user, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } id = json_object_object_get(user, "id"); if (!json_valid(id, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } name = json_object_object_get(user, "name"); if (!json_valid(name, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } profile = json_object_object_get(user, "profile"); if (!json_valid(profile, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } display_name = json_object_object_get(profile, "display_name"); if (!json_valid(display_name, request->workspace)) { - json_object_put(response); - free(json_string); - return 0; + continue; } new_user = slack_user_new(request->workspace, json_object_get_string(id), json_object_get_string(display_name)); + + if (!new_user) + __asm__("int3"); + + bot_id = json_object_object_get(profile, "bot_id"); + if (json_valid(bot_id, request->workspace)) + { + new_user->profile.bot_id = strdup(json_object_get_string(bot_id)); + } } metadata = json_object_object_get(response, "response_metadata"); diff --git a/slack-user.c b/slack-user.c index c26aca5..6314866 100644 --- a/slack-user.c +++ b/slack-user.c @@ -14,7 +14,8 @@ const char *slack_user_get_colour(struct t_slack_user *user) } const char *slack_user_as_prefix(struct t_slack_workspace *workspace, - struct t_slack_user *user) + struct t_slack_user *user, + const char *name) { static char result[256]; @@ -22,11 +23,30 @@ const char *slack_user_as_prefix(struct t_slack_workspace *workspace, snprintf(result, sizeof(result), "%s%s\t", slack_user_get_colour(user), - user->profile.display_name); + name ? name : user->profile.display_name); return result; } +struct t_slack_user *slack_user_bot_search(struct t_slack_workspace *workspace, + const char *bot_id) +{ + struct t_slack_user *ptr_user; + + if (!workspace || !bot_id) + return NULL; + + for (ptr_user = workspace->users; ptr_user; + ptr_user = ptr_user->next_user) + { + if (ptr_user->profile.bot_id && + weechat_strcasecmp(ptr_user->profile.bot_id, bot_id) == 0) + return ptr_user; + } + + return NULL; +} + struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, const char *id) { @@ -72,7 +92,12 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, { struct t_slack_user *new_user, *ptr_user; - if (!workspace || !id || !display_name || !display_name[0]) + if (!workspace || !id || !display_name) + { + return NULL; + } + + if (!display_name[0] && strcmp("USLACKBOT", id) == 0) return NULL; if (!workspace->users) @@ -86,7 +111,9 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, } if ((new_user = malloc(sizeof(*new_user))) == NULL) + { return NULL; + } new_user->prev_user = workspace->last_user; new_user->next_user = NULL; @@ -112,10 +139,13 @@ struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, new_user->profile.status_text = NULL; new_user->profile.status_emoji = NULL; new_user->profile.real_name = NULL; - new_user->profile.display_name = strdup(display_name); + new_user->profile.display_name = display_name[0] ? + strdup(display_name) : + strdup("slackbot"); new_user->profile.real_name_normalized = NULL; new_user->profile.email = NULL; new_user->profile.team = NULL; + new_user->profile.bot_id = NULL; new_user->updated = 0; new_user->is_away = 0; diff --git a/slack-user.h b/slack-user.h index 8525bb3..a8a25f6 100644 --- a/slack-user.h +++ b/slack-user.h @@ -11,6 +11,7 @@ struct t_slack_user_profile char *real_name_normalized; char *email; char *team; + char *bot_id; }; struct t_slack_user @@ -46,7 +47,11 @@ struct t_slack_user }; const char *slack_user_as_prefix(struct t_slack_workspace *workspace, - struct t_slack_user *user); + struct t_slack_user *user, + const char *name); + +struct t_slack_user *slack_user_bot_search(struct t_slack_workspace *workspace, + const char *bot_id); struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, const char *id); From e6c48d79eaecdb6f80a8a059c0728c4481c94274 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Tue, 8 May 2018 23:34:46 +0100 Subject: [PATCH 018/118] Slackbot responses --- Makefile | 1 + api/message/slack-api-message-bot-message.c | 1 + .../slack-api-message-slackbot-response.c | 94 +++++++++++++++++++ .../slack-api-message-slackbot-response.h | 8 ++ api/message/slack-api-message-unimplemented.c | 1 + api/slack-api-message.c | 4 +- 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 api/message/slack-api-message-slackbot-response.c create mode 100644 api/message/slack-api-message-slackbot-response.h diff --git a/Makefile b/Makefile index 5f9704a..99e3d3a 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ SRCS=slack.c \ api/slack-api-message.c \ api/slack-api-user-typing.c \ api/message/slack-api-message-bot-message.c \ + api/message/slack-api-message-slackbot-response.c \ api/message/slack-api-message-unimplemented.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ diff --git a/api/message/slack-api-message-bot-message.c b/api/message/slack-api-message-bot-message.c index 1036afb..f0b08e5 100644 --- a/api/message/slack-api-message-bot-message.c +++ b/api/message/slack-api-message-bot-message.c @@ -9,6 +9,7 @@ #include "../../slack-channel.h" #include "../../slack-user.h" #include "../slack-api-message.h" +#include "slack-api-message-bot-message.h" static const char *subtype = "bot_message"; diff --git a/api/message/slack-api-message-slackbot-response.c b/api/message/slack-api-message-slackbot-response.c new file mode 100644 index 0000000..a9d364e --- /dev/null +++ b/api/message/slack-api-message-slackbot-response.c @@ -0,0 +1,94 @@ +#include +#include + +#include "../../weechat-plugin.h" +#include "../../slack.h" +#include "../../slack-workspace.h" +#include "../../slack-message.h" +#include "../../slack-api.h" +#include "../../slack-channel.h" +#include "../../slack-user.h" +#include "../slack-api-message.h" +#include "slack-api-message-slackbot-response.h" + +static const char *subtype = "slackbot_response"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %smessage.%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), subtype, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_slackbot_response_handle(struct t_slack_workspace *workspace, + const char *channel, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; /* silently ignore if bot user hasn't been loaded yet */ + + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message,slack_slackbot_response", + _("%s%s"), + slack_user_as_prefix(workspace, ptr_user, "slackbot"), + message); + free(message); + + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + + return 1; +} + +int slack_api_message_slackbot_response(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *channel, *user, *text, *ts; + channel = json_object_object_get(message, "channel"); + if (!json_valid(channel, workspace)) + return 0; + + user = json_object_object_get(message, "user"); + if (!json_valid(user, workspace)) + return 0; + + text = json_object_object_get(message, "text"); + if (!json_valid(text, workspace)) + return 0; + + ts = json_object_object_get(message, "ts"); + if (!json_valid(ts, workspace)) + return 0; + + return slack_api_message_slackbot_response_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user), + json_object_get_string(text), + json_object_get_string(ts)); +} + diff --git a/api/message/slack-api-message-slackbot-response.h b/api/message/slack-api-message-slackbot-response.h new file mode 100644 index 0000000..9f1a203 --- /dev/null +++ b/api/message/slack-api-message-slackbot-response.h @@ -0,0 +1,8 @@ +#ifndef _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_ +#define _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_ + +int slack_api_message_slackbot_response( + struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H*/ diff --git a/api/message/slack-api-message-unimplemented.c b/api/message/slack-api-message-unimplemented.c index fb66ebd..ffb2cad 100644 --- a/api/message/slack-api-message-unimplemented.c +++ b/api/message/slack-api-message-unimplemented.c @@ -8,6 +8,7 @@ #include "../../slack-channel.h" #include "../../slack-user.h" #include "../slack-api-message.h" +#include "slack-api-message-unimplemented.h" static const char *subtype = "unimplemented"; diff --git a/api/slack-api-message.c b/api/slack-api-message.c index c181e10..2749b87 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -11,6 +11,7 @@ #include "slack-api-message.h" #include "message/slack-api-message-unimplemented.h" #include "message/slack-api-message-bot-message.h" +#include "message/slack-api-message-slackbot-response.h" static const char *type = "message"; @@ -46,6 +47,7 @@ static struct stringcase cases[] = , { "message_replied", &slack_api_message_unimplemented } , { "pinned_item", &slack_api_message_unimplemented } , { "reply_broadcast", &slack_api_message_unimplemented } +, { "slackbot_response", &slack_api_message_slackbot_response } , { "thread_broadcast", &slack_api_message_unimplemented } , { "unpinned_item", &slack_api_message_unimplemented } }; @@ -118,7 +120,7 @@ int slack_api_message_route_message(struct t_slack_workspace *workspace, json_object *message) { struct stringcase key; - key.string = type; + key.string = subtype; size_t case_count = sizeof(cases) / sizeof(cases[0]); void *entry_ptr = bsearch(&key, cases, case_count, From 638abde1f9b070ae78d1dc4ac45101e0150c2914 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 01:57:17 +0100 Subject: [PATCH 019/118] CTags --- .dir-locals.el | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.dir-locals.el b/.dir-locals.el index 46be8ac..6166711 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -8,6 +8,7 @@ (eval . (setq-local company-clang-arguments (list (concat "-I" (expand-file-name "libwebsockets/include" (projectile-project-root))) (concat "-I" (expand-file-name "json-c" (projectile-project-root)))))) + (eval . (setq-local tags-table-list (expand-file-name ".git/tags" (projectile-project-root)))) (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) (flycheck-clang-language-standard . "gnu99") (flycheck-checker . c/c++-clang) diff --git a/Makefile b/Makefile index 99e3d3a..1e25c5a 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ install: slack.so .PHONY: tags cs tags: - ctags -f .git/tags -R *.c *.h + $(CC) $(CFLAGS) -M $(SRCS) | sed -e "s/[\\ ]/\n/g" | sed -e "/^$$/d" -e "/\.o:[ \t]*$$/d" | sort | uniq | ctags -e -L - -f .git/tags -R --c-kinds=+px --c++-kinds=+px --fields=+iaS --extra=+fq cs: cscope -RUbq From c76c93fd71fcb3a79782e4ec26e4571bdc442c99 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 03:56:48 +0100 Subject: [PATCH 020/118] Fix channel mentions. Closes #2 --- slack-message.c | 83 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/slack-message.c b/slack-message.c index c6a2bcd..d2f587d 100644 --- a/slack-message.c +++ b/slack-message.c @@ -19,34 +19,83 @@ char *slack_message_translate_code(struct t_slack_workspace *workspace, { struct t_slack_channel *channel; struct t_slack_user *user; - char *command; + size_t resultlen; + char *identifier, *alttext, *result, *symbol, *prefix; - switch (code[0]) + identifier = strdup(code); + alttext = strchr(identifier, '|'); + if (alttext) + *alttext++ = '\0'; + + switch (identifier[0]) { case '#': /* channel */ - channel = slack_channel_search(workspace, code+1); - if (channel) - return strdup(channel->name); + if (alttext) + { + prefix = "#"; + symbol = strdup(alttext); + } else - return strdup(code); + { + channel = slack_channel_search(workspace, identifier+1); + if (channel) + { + prefix = "#"; + symbol = strdup(channel->name); + } + else + { + prefix = "Channel:"; + symbol = strdup(identifier+1); + } + } + break; case '@': /* user */ - user = slack_user_search(workspace, code+1); - if (user) + if (alttext) { - size_t nicklen = snprintf(NULL, 0, "%s@%s%s", weechat_color("chat_nick"), user->profile.display_name, weechat_color("reset")) + 1; - char *tag = malloc(nicklen); - snprintf(tag, nicklen, "%s@%s%s", weechat_color("chat_nick"), user->profile.display_name, weechat_color("reset")); - return tag; + prefix = "@"; + symbol = strdup(alttext); } else - return strdup(code); + { + user = slack_user_search(workspace, identifier+1); + if (user) + { + prefix = "@"; + symbol = strdup(user->profile.display_name); + } + else + { + prefix = "User:"; + symbol = strdup(identifier+1); + } + } + break; case '!': /* special */ - command = strdup(code); - command[0] = '@'; - return command; + if (alttext) + { + prefix = "@"; + symbol = strdup(alttext); + } + else + { + prefix = "@"; + symbol = strdup(identifier+1); + } + break; default: /* url */ - return strdup(code); + prefix = ""; + symbol = strdup(code); + break; } + + free(identifier); + resultlen = snprintf(NULL, 0, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")) + 1; + result = malloc(resultlen); + snprintf(result, resultlen, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")); + free(symbol); + + return result; } void slack_message_htmldecode(char *dest, const char *src, size_t n) From 15cb9da359091581c64977bd89208c4e31282313 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 05:39:16 +0100 Subject: [PATCH 021/118] License headers --- api/message/slack-api-message-bot-message.c | 4 ++++ api/message/slack-api-message-bot-message.h | 4 ++++ api/message/slack-api-message-slackbot-response.c | 4 ++++ api/message/slack-api-message-slackbot-response.h | 4 ++++ api/message/slack-api-message-unimplemented.c | 4 ++++ api/message/slack-api-message-unimplemented.h | 4 ++++ api/slack-api-error.c | 4 ++++ api/slack-api-error.h | 4 ++++ api/slack-api-hello.c | 4 ++++ api/slack-api-hello.h | 4 ++++ api/slack-api-message.c | 4 ++++ api/slack-api-message.h | 4 ++++ api/slack-api-user-typing.c | 4 ++++ api/slack-api-user-typing.h | 4 ++++ request/slack-request-bots-info.c | 4 ++++ request/slack-request-bots-info.h | 4 ++++ request/slack-request-channels-list.c | 4 ++++ request/slack-request-channels-list.h | 4 ++++ request/slack-request-chat-postmessage.c | 4 ++++ request/slack-request-chat-postmessage.h | 4 ++++ request/slack-request-conversations-members.c | 4 ++++ request/slack-request-conversations-members.h | 4 ++++ request/slack-request-users-list.c | 4 ++++ request/slack-request-users-list.h | 4 ++++ slack-api.c | 4 ++++ slack-api.h | 4 ++++ slack-buffer.c | 4 ++++ slack-buffer.h | 4 ++++ slack-channel.c | 4 ++++ slack-channel.h | 4 ++++ slack-command.c | 4 ++++ slack-command.h | 4 ++++ slack-config.c | 4 ++++ slack-config.h | 4 ++++ slack-input.c | 4 ++++ slack-input.h | 4 ++++ slack-message.c | 4 ++++ slack-message.h | 4 ++++ slack-oauth.c | 4 ++++ slack-oauth.h | 4 ++++ slack-request.c | 4 ++++ slack-request.h | 4 ++++ slack-teaminfo.c | 4 ++++ slack-teaminfo.h | 4 ++++ slack-user.c | 4 ++++ slack-user.h | 4 ++++ slack-workspace.c | 4 ++++ slack-workspace.h | 4 ++++ slack.c | 4 ++++ slack.h | 4 ++++ weechat-plugin.h | 4 ++++ 51 files changed, 204 insertions(+) diff --git a/api/message/slack-api-message-bot-message.c b/api/message/slack-api-message-bot-message.c index f0b08e5..d3ae177 100644 --- a/api/message/slack-api-message-bot-message.c +++ b/api/message/slack-api-message-bot-message.c @@ -1,3 +1,7 @@ +// 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 diff --git a/api/message/slack-api-message-bot-message.h b/api/message/slack-api-message-bot-message.h index a567f22..93d55fc 100644 --- a/api/message/slack-api-message-bot-message.h +++ b/api/message/slack-api-message-bot-message.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_MESSAGE_BOT_MESSAGE_H_ #define _SLACK_API_MESSAGE_BOT_MESSAGE_H_ diff --git a/api/message/slack-api-message-slackbot-response.c b/api/message/slack-api-message-slackbot-response.c index a9d364e..4f013af 100644 --- a/api/message/slack-api-message-slackbot-response.c +++ b/api/message/slack-api-message-slackbot-response.c @@ -1,3 +1,7 @@ +// 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 diff --git a/api/message/slack-api-message-slackbot-response.h b/api/message/slack-api-message-slackbot-response.h index 9f1a203..edab623 100644 --- a/api/message/slack-api-message-slackbot-response.h +++ b/api/message/slack-api-message-slackbot-response.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_ #define _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_ diff --git a/api/message/slack-api-message-unimplemented.c b/api/message/slack-api-message-unimplemented.c index ffb2cad..d9b3490 100644 --- a/api/message/slack-api-message-unimplemented.c +++ b/api/message/slack-api-message-unimplemented.c @@ -1,3 +1,7 @@ +// 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 diff --git a/api/message/slack-api-message-unimplemented.h b/api/message/slack-api-message-unimplemented.h index b83b4d8..0e46d70 100644 --- a/api/message/slack-api-message-unimplemented.h +++ b/api/message/slack-api-message-unimplemented.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_MESSAGE_UNIMPLEMENTED_H_ #define _SLACK_API_MESSAGE_UNIMPLEMENTED_H_ diff --git a/api/slack-api-error.c b/api/slack-api-error.c index 6fe75bc..0ed9b4b 100644 --- a/api/slack-api-error.c +++ b/api/slack-api-error.c @@ -1,3 +1,7 @@ +// 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 "../weechat-plugin.h" diff --git a/api/slack-api-error.h b/api/slack-api-error.h index 19afd9d..d6f52ed 100644 --- a/api/slack-api-error.h +++ b/api/slack-api-error.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_ERROR_H_ #define _SLACK_API_ERROR_H_ diff --git a/api/slack-api-hello.c b/api/slack-api-hello.c index 406cbd3..87fa406 100644 --- a/api/slack-api-hello.c +++ b/api/slack-api-hello.c @@ -1,3 +1,7 @@ +// 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 "../weechat-plugin.h" diff --git a/api/slack-api-hello.h b/api/slack-api-hello.h index 08432f3..f3786d8 100644 --- a/api/slack-api-hello.h +++ b/api/slack-api-hello.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_HELLO_H_ #define _SLACK_API_HELLO_H_ diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 2749b87..534f7b0 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -1,3 +1,7 @@ +// 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 diff --git a/api/slack-api-message.h b/api/slack-api-message.h index eed80e3..b72ffa4 100644 --- a/api/slack-api-message.h +++ b/api/slack-api-message.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_MESSAGE_H_ #define _SLACK_API_MESSAGE_H_ diff --git a/api/slack-api-user-typing.c b/api/slack-api-user-typing.c index 75eaf65..1909dbd 100644 --- a/api/slack-api-user-typing.c +++ b/api/slack-api-user-typing.c @@ -1,3 +1,7 @@ +// 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 "../weechat-plugin.h" diff --git a/api/slack-api-user-typing.h b/api/slack-api-user-typing.h index 3aea802..c036333 100644 --- a/api/slack-api-user-typing.h +++ b/api/slack-api-user-typing.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_USER_TYPING_H_ #define _SLACK_API_USER_TYPING_H_ diff --git a/request/slack-request-bots-info.c b/request/slack-request-bots-info.c index bd04431..278d467 100644 --- a/request/slack-request-bots-info.c +++ b/request/slack-request-bots-info.c @@ -1,3 +1,7 @@ +// 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 diff --git a/request/slack-request-bots-info.h b/request/slack-request-bots-info.h index ca23334..f743f13 100644 --- a/request/slack-request-bots-info.h +++ b/request/slack-request-bots-info.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_REQUEST_BOTS_INFO_H_ #define _SLACK_REQUEST_BOTS_INFO_H_ diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c index edb6b81..6e2d30e 100644 --- a/request/slack-request-channels-list.c +++ b/request/slack-request-channels-list.c @@ -1,3 +1,7 @@ +// 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 diff --git a/request/slack-request-channels-list.h b/request/slack-request-channels-list.h index e41545a..d965538 100644 --- a/request/slack-request-channels-list.h +++ b/request/slack-request-channels-list.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_REQUEST_CHANNELS_LIST_H_ #define _SLACK_REQUEST_CHANNELS_LIST_H_ diff --git a/request/slack-request-chat-postmessage.c b/request/slack-request-chat-postmessage.c index 635ebea..1bf644c 100644 --- a/request/slack-request-chat-postmessage.c +++ b/request/slack-request-chat-postmessage.c @@ -1,3 +1,7 @@ +// 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 diff --git a/request/slack-request-chat-postmessage.h b/request/slack-request-chat-postmessage.h index 48d31fc..55be2a3 100644 --- a/request/slack-request-chat-postmessage.h +++ b/request/slack-request-chat-postmessage.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_REQUEST_CHAT_POSTMESSAGE_H_ #define _SLACK_REQUEST_CHAT_POSTMESSAGE_H_ diff --git a/request/slack-request-conversations-members.c b/request/slack-request-conversations-members.c index 53192b1..1b9bd5f 100644 --- a/request/slack-request-conversations-members.c +++ b/request/slack-request-conversations-members.c @@ -1,3 +1,7 @@ +// 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 diff --git a/request/slack-request-conversations-members.h b/request/slack-request-conversations-members.h index bdf750f..d5a1458 100644 --- a/request/slack-request-conversations-members.h +++ b/request/slack-request-conversations-members.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_ #define _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index d986fc6..62d5463 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -1,3 +1,7 @@ +// 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 diff --git a/request/slack-request-users-list.h b/request/slack-request-users-list.h index 4623c4b..e5e3825 100644 --- a/request/slack-request-users-list.h +++ b/request/slack-request-users-list.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_REQUEST_USERS_LIST_H_ #define _SLACK_REQUEST_USERS_LIST_H_ diff --git a/slack-api.c b/slack-api.c index e5d9af3..fc86b4a 100644 --- a/slack-api.c +++ b/slack-api.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-api.h b/slack-api.h index 249f975..723b3b9 100644 --- a/slack-api.h +++ b/slack-api.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_API_H_ #define _SLACK_API_H_ diff --git a/slack-buffer.c b/slack-buffer.c index 36a3d2a..c922cfc 100644 --- a/slack-buffer.c +++ b/slack-buffer.c @@ -1,3 +1,7 @@ +// 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 "weechat-plugin.h" diff --git a/slack-buffer.h b/slack-buffer.h index 4ed21fa..3f4bc66 100644 --- a/slack-buffer.h +++ b/slack-buffer.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_BUFFER_H_ #define _SLACK_BUFFER_H_ diff --git a/slack-channel.c b/slack-channel.c index f78b646..d301f20 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-channel.h b/slack-channel.h index 06c2afb..23275eb 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_CHANNEL_H_ #define _SLACK_CHANNEL_H_ diff --git a/slack-command.c b/slack-command.c index 0d7f4b8..312ddca 100644 --- a/slack-command.c +++ b/slack-command.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-command.h b/slack-command.h index 66c3434..9d27194 100644 --- a/slack-command.h +++ b/slack-command.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_COMMAND_H_ #define _SLACK_COMMAND_H_ diff --git a/slack-config.c b/slack-config.c index f6a8f2c..06a0b94 100644 --- a/slack-config.c +++ b/slack-config.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-config.h b/slack-config.h index 13e33cb..c769419 100644 --- a/slack-config.h +++ b/slack-config.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_CONFIG_H_ #define _SLACK_CONFIG_H_ diff --git a/slack-input.c b/slack-input.c index 1b06398..8643e8c 100644 --- a/slack-input.c +++ b/slack-input.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-input.h b/slack-input.h index e3ac745..fbc1d59 100644 --- a/slack-input.h +++ b/slack-input.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_INPUT_H_ #define _SLACK_INPUT_H_ diff --git a/slack-message.c b/slack-message.c index d2f587d..b7b1e3a 100644 --- a/slack-message.c +++ b/slack-message.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-message.h b/slack-message.h index baca30f..d223ba2 100644 --- a/slack-message.h +++ b/slack-message.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_MESSAGE_H_ #define _SLACK_MESSAGE_H_ diff --git a/slack-oauth.c b/slack-oauth.c index 5bd2845..be9f52d 100644 --- a/slack-oauth.c +++ b/slack-oauth.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-oauth.h b/slack-oauth.h index 5d078ea..d7a6538 100644 --- a/slack-oauth.h +++ b/slack-oauth.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_OAUTH_H_ #define _SLACK_OAUTH_H_ diff --git a/slack-request.c b/slack-request.c index 55343aa..50c185e 100644 --- a/slack-request.c +++ b/slack-request.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-request.h b/slack-request.h index 88c5ee2..675d947 100644 --- a/slack-request.h +++ b/slack-request.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_REQUEST_H_ #define _SLACK_REQUEST_H_ diff --git a/slack-teaminfo.c b/slack-teaminfo.c index 192ca0b..51ec2f7 100644 --- a/slack-teaminfo.c +++ b/slack-teaminfo.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-teaminfo.h b/slack-teaminfo.h index cf37fe9..67bd5d2 100644 --- a/slack-teaminfo.h +++ b/slack-teaminfo.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_TEAMINFO_H_ #define _SLACK_TEAMINFO_H_ diff --git a/slack-user.c b/slack-user.c index 6314866..5794b7b 100644 --- a/slack-user.c +++ b/slack-user.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-user.h b/slack-user.h index a8a25f6..763c832 100644 --- a/slack-user.h +++ b/slack-user.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_USER_H_ #define _SLACK_USER_H_ diff --git a/slack-workspace.c b/slack-workspace.c index c806a82..b820d1d 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack-workspace.h b/slack-workspace.h index 997ff23..d858b08 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_WORKSPACE_H_ #define _SLACK_WORKSPACE_H_ diff --git a/slack.c b/slack.c index 32c5614..fb83898 100644 --- a/slack.c +++ b/slack.c @@ -1,3 +1,7 @@ +// 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 diff --git a/slack.h b/slack.h index 21c6b7f..23f98ec 100644 --- a/slack.h +++ b/slack.h @@ -1,3 +1,7 @@ +// 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/. + #ifndef _SLACK_H_ #define _SLACK_H_ diff --git a/weechat-plugin.h b/weechat-plugin.h index 02dc525..5abb6d0 100644 --- a/weechat-plugin.h +++ b/weechat-plugin.h @@ -1,3 +1,7 @@ +// 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/. + /* * weechat-plugin.h - header to compile WeeChat plugins * From 065b4eabee0a0ac513c7edea5313838b6d1e51c7 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 06:14:05 +0100 Subject: [PATCH 022/118] Administration --- .travis.yml | 5 +++++ Makefile | 2 +- README.org | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 .travis.yml create mode 100644 README.org diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9867dec --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: c +script: make && make install +compiler: + - clang + - gcc diff --git a/Makefile b/Makefile index 1e25c5a..25c4c14 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ distclean: clean $(RM) *~ .depend install: slack.so - install slack.so ~/.weechat/plugins/ + install -D slack.so ~/.weechat/plugins/ .PHONY: tags cs diff --git a/README.org b/README.org new file mode 100644 index 0000000..c3f1691 --- /dev/null +++ b/README.org @@ -0,0 +1,49 @@ +#+TITLE: weechat-slack +#+AUTHOR: Tony Olagbaiye +#+EMAIL: frony0.com +#+DATE: 2018-05-09 +#+DESCRIPTION: Weechat plugin for Slack +#+KEYWORDS: weechat slack c api +#+LANGUAGE: en +#+OPTIONS: H:3 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t +#+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:nil pri:nil tags:not-in-toc +#+EXPORT_EXCLUDE_TAGS: exclude +#+STARTUP: showall + +[[https://travis-ci.org/bqv/weechat-slack][file:https://api.travis-ci.org/bqv/weechat-slack.svg?branch=master]] +[[https://coveralls.io/github/bqv/weechat-slack?branch=master][file:https://coveralls.io/repos/github/bqv/weechat-slack/badge.svg?branch=master]] + + | Status: | Under Development | + | Location: | [[http://github.com/bqv/weechat-slack]] | + | Version: | 0.1.0 | + +* Description + + A weechat plugin in C to extend the chat client to + support Slack workspaces via the RTM and Web APIs. + +* Dependencies + + - libwebsockets (static, submodule) + - json-c (static, submodule) + - weechat (>= v1.4) + +* Building + + #+begin_src sh + git clone git://github.com/bqv/weechat-slack.git + cd weechat-slack + make + make install + #+end_src + +* Contributing + + *Your contributions are always welcome!* + Please submit a pull request or create an issue + to add a new or missing feature. + +* License + + weechat-slack is licensed under the Mozilla Public + License Version 2.0 available [[https://www.mozilla.org/en-US/MPL/2.0/][here]] and in LICENSE. From 8fb1cbcc349cc5a480ceec06aa23b56c302fb967 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 12:12:57 +0100 Subject: [PATCH 023/118] Add TODO to readme --- Makefile | 2 +- README.org | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 25c4c14..6396c99 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX=g++ RM=rm -f SANCFLAGS=-fsanitize=address -fsanitize=leak SANLDFLAGS=-static-libasan -static-liblsan -CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -I libwebsockets/include -I json-c +CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS) LDLIBS=-lgnutls diff --git a/README.org b/README.org index c3f1691..591fc7e 100644 --- a/README.org +++ b/README.org @@ -13,9 +13,9 @@ [[https://travis-ci.org/bqv/weechat-slack][file:https://api.travis-ci.org/bqv/weechat-slack.svg?branch=master]] [[https://coveralls.io/github/bqv/weechat-slack?branch=master][file:https://coveralls.io/repos/github/bqv/weechat-slack/badge.svg?branch=master]] - | Status: | Under Development | + | Status: | Under Development | | Location: | [[http://github.com/bqv/weechat-slack]] | - | Version: | 0.1.0 | + | Version: | 0.1.0 | * Description @@ -37,6 +37,27 @@ make install #+end_src +* Tasks + +** TODO [#A] Implement essential api endpoints and events + - [ ] Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]]) + - [ ] Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]]) + - [ ] Implement handling api message =message.thread_broadcast= + - [X] Implement handling api message =message.bot_message= (see [[http://github.com/bqv/weechat-slack/issues/2][#2]]) + - [ ] Implement handling api message =message.message_changed= + - [ ] Implement handling api message =message.message_deleted= + - [ ] Implement handling api message =message.message_replied= +** TODO [#B] Implement completion engine + - [ ] Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]]) + - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) + - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) +** TODO [#B] Implement debian packaging + - [ ] Switch to system libwebsockets package (dynamically link) + - [ ] Create configure build step (cmake? autotools?) +** TODO [#C] Implement remaining api endpoints and events + - [ ] Complete api endpoint set + - [ ] Complete api event set + * Contributing *Your contributions are always welcome!* From 296e9435baccb57b9440e7cb9c5043a25633a382 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 12:55:57 +0100 Subject: [PATCH 024/118] Fix makefile to find libwebsockets.h --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6396c99..75129a1 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX=g++ RM=rm -f SANCFLAGS=-fsanitize=address -fsanitize=leak SANLDFLAGS=-static-libasan -static-liblsan -CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c +CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/lib -Ijson-c LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS) LDLIBS=-lgnutls From 77cc204d9724a1daadc1997ce81edc13146d57f5 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 13:12:11 +0100 Subject: [PATCH 025/118] Build libwebsockets first --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 75129a1..416911e 100644 --- a/Makefile +++ b/Makefile @@ -42,13 +42,15 @@ libwebsockets/lib/libwebsockets.a: cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . $(MAKE) -C libwebsockets +libwebsockets/include/libwebsockets.h: libwebsockets/lib/libwebsockets.a + json-c/libjson-c.a: cd json-c && cmake -DCMAKE_C_FLAGS=-fPIC . $(MAKE) -C json-c json-c-static depend: .depend -.depend: $(SRCS) +.depend: libwebsockets/include/libwebsockets.h $(SRCS) $(RM) ./.depend $(CC) $(CFLAGS) -MM $^>>./.depend; From a953a2de51d92038ff1b4da0f84bb58fb6df89df Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 13:16:20 +0100 Subject: [PATCH 026/118] Revert libwebsockets header change --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 416911e..1222d4b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX=g++ RM=rm -f SANCFLAGS=-fsanitize=address -fsanitize=leak SANLDFLAGS=-static-libasan -static-liblsan -CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/lib -Ijson-c +CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS) LDLIBS=-lgnutls From afd30dd0d184ac17e190289ff8cac76698bae83c Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 13:24:17 +0100 Subject: [PATCH 027/118] Build libjson-c before too --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1222d4b..c32b1c0 100644 --- a/Makefile +++ b/Makefile @@ -42,15 +42,13 @@ libwebsockets/lib/libwebsockets.a: cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . $(MAKE) -C libwebsockets -libwebsockets/include/libwebsockets.h: libwebsockets/lib/libwebsockets.a - json-c/libjson-c.a: cd json-c && cmake -DCMAKE_C_FLAGS=-fPIC . $(MAKE) -C json-c json-c-static depend: .depend -.depend: libwebsockets/include/libwebsockets.h $(SRCS) +.depend: libwebsockets/lib/libwebsockets.a json_c/libjson-c.a $(SRCS) $(RM) ./.depend $(CC) $(CFLAGS) -MM $^>>./.depend; From c925d1e6908619dff04b79ddecf9155c83b09a66 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 13:26:51 +0100 Subject: [PATCH 028/118] Typo --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c32b1c0..d6e0082 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ json-c/libjson-c.a: depend: .depend -.depend: libwebsockets/lib/libwebsockets.a json_c/libjson-c.a $(SRCS) +.depend: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a $(SRCS) $(RM) ./.depend $(CC) $(CFLAGS) -MM $^>>./.depend; From 6a7fdcca4d2d29fa9d1f7c8156fee19a79704753 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 13:40:23 +0100 Subject: [PATCH 029/118] Move sanitizers to debug build --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d6e0082..154917e 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ CC=clang CXX=g++ RM=rm -f -SANCFLAGS=-fsanitize=address -fsanitize=leak -SANLDFLAGS=-static-libasan -static-liblsan +ifdef DEBUG + SANCFLAGS=-fsanitize=address -fsanitize=leak + SANLDFLAGS=-static-libasan -static-liblsan +endif CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS) LDLIBS=-lgnutls From 4c8df43364b129626df3eeed2f6aedc63bd07acc Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 13:43:28 +0100 Subject: [PATCH 030/118] Fix make install --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 154917e..faa700d 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ distclean: clean $(RM) *~ .depend install: slack.so - install -D slack.so ~/.weechat/plugins/ + install -d slack.so ~/.weechat/plugins/ .PHONY: tags cs From 99e5e130a748c4a9ffb71b91b4202adad126605d Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 14:18:30 +0100 Subject: [PATCH 031/118] Fix install finally --- Makefile | 2 +- README.org | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index faa700d..2efaf28 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ distclean: clean $(RM) *~ .depend install: slack.so - install -d slack.so ~/.weechat/plugins/ + install -t ~/.weechat/plugins -D slack.so .PHONY: tags cs diff --git a/README.org b/README.org index 591fc7e..74267fe 100644 --- a/README.org +++ b/README.org @@ -36,6 +36,9 @@ make make install #+end_src + + Do *NOT* run make install as root, it installs the plugin to your + local weechat plugins directory * Tasks From bcda842f27cc0960dccab448e92c81b5016cdc5c Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 14:23:43 +0100 Subject: [PATCH 032/118] Just remove `make install` from travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9867dec..d9bede5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: c -script: make && make install +script: make compiler: - clang - gcc From e7096e374fbf38a85f301fea697975394af9f600 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 14:30:47 +0100 Subject: [PATCH 033/118] Update README.org --- README.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index 74267fe..688b150 100644 --- a/README.org +++ b/README.org @@ -5,8 +5,8 @@ #+DESCRIPTION: Weechat plugin for Slack #+KEYWORDS: weechat slack c api #+LANGUAGE: en -#+OPTIONS: H:3 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t -#+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:nil pri:nil tags:not-in-toc +#+OPTIONS: H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t +#+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:t tags:not-in-toc #+EXPORT_EXCLUDE_TAGS: exclude #+STARTUP: showall From b41553ccd9e07bbdfee6e47608b80255c35a652c Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 17:35:55 +0100 Subject: [PATCH 034/118] Handle message.me_message (ref #5) --- Makefile | 1 + README.org | 6 +- api/message/slack-api-message-me-message.c | 102 ++++++++++++++++++ api/message/slack-api-message-me-message.h | 12 +++ .../slack-api-message-slackbot-response.c | 2 +- api/slack-api-message.c | 3 +- slack-user.h | 2 + weechat-plugin.h | 4 - 8 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 api/message/slack-api-message-me-message.c create mode 100644 api/message/slack-api-message-me-message.h diff --git a/Makefile b/Makefile index 2efaf28..385ddda 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ SRCS=slack.c \ api/slack-api-user-typing.c \ api/message/slack-api-message-bot-message.c \ api/message/slack-api-message-slackbot-response.c \ + api/message/slack-api-message-me-message.c \ api/message/slack-api-message-unimplemented.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ diff --git a/README.org b/README.org index 688b150..4d963cd 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,6 @@ #+TITLE: weechat-slack #+AUTHOR: Tony Olagbaiye -#+EMAIL: frony0.com +#+EMAIL: frony0@gmail.com #+DATE: 2018-05-09 #+DESCRIPTION: Weechat plugin for Slack #+KEYWORDS: weechat slack c api @@ -43,10 +43,10 @@ * Tasks ** TODO [#A] Implement essential api endpoints and events - - [ ] Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]]) + - [X] +Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - [ ] Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]]) - [ ] Implement handling api message =message.thread_broadcast= - - [X] Implement handling api message =message.bot_message= (see [[http://github.com/bqv/weechat-slack/issues/2][#2]]) + - [X] +Implement handling api message =message.bot_message= (see [[http://github.com/bqv/weechat-slack/issues/2][#2]])+ - [ ] Implement handling api message =message.message_changed= - [ ] Implement handling api message =message.message_deleted= - [ ] Implement handling api message =message.message_replied= diff --git a/api/message/slack-api-message-me-message.c b/api/message/slack-api-message-me-message.c new file mode 100644 index 0000000..fcc91d1 --- /dev/null +++ b/api/message/slack-api-message-me-message.c @@ -0,0 +1,102 @@ +// 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 "../../weechat-plugin.h" +#include "../../slack.h" +#include "../../slack-workspace.h" +#include "../../slack-message.h" +#include "../../slack-api.h" +#include "../../slack-channel.h" +#include "../../slack-user.h" +#include "../slack-api-message.h" +#include "slack-api-message-me-message.h" + +static const char *subtype = "me_message"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %smessage.%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), subtype, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_me_message_handle(struct t_slack_workspace *workspace, + const char *channel, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; /* silently ignore if user hasn't been loaded yet */ + + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message,slack_me_message", + _("%s%s%s%s%s%s"), + weechat_prefix("action"), + slack_user_get_colour(ptr_user), + ptr_user->profile.display_name, + weechat_color("reset"), + message[0] ? " " : "", + message); + free(message); + + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + + return 1; +} + +int slack_api_message_me_message(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *channel, *user, *text, *ts; + channel = json_object_object_get(message, "channel"); + if (!json_valid(channel, workspace)) + return 0; + + user = json_object_object_get(message, "user"); + if (!json_valid(user, workspace)) + return 0; + + text = json_object_object_get(message, "text"); + if (!json_valid(text, workspace)) + return 0; + + ts = json_object_object_get(message, "ts"); + if (!json_valid(ts, workspace)) + return 0; + + return slack_api_message_me_message_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user), + json_object_get_string(text), + json_object_get_string(ts)); +} + diff --git a/api/message/slack-api-message-me-message.h b/api/message/slack-api-message-me-message.h new file mode 100644 index 0000000..1131898 --- /dev/null +++ b/api/message/slack-api-message-me-message.h @@ -0,0 +1,12 @@ +// 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/. + +#ifndef _SLACK_API_MESSAGE_ME_MESSAGE_H_ +#define _SLACK_API_MESSAGE_ME_MESSAGE_H_ + +int slack_api_message_me_message( + struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_MESSAGE_ME_MESSAGE_H*/ diff --git a/api/message/slack-api-message-slackbot-response.c b/api/message/slack-api-message-slackbot-response.c index 4f013af..8252d28 100644 --- a/api/message/slack-api-message-slackbot-response.c +++ b/api/message/slack-api-message-slackbot-response.c @@ -46,7 +46,7 @@ int slack_api_message_slackbot_response_handle(struct t_slack_workspace *workspa return 1; /* silently ignore if channel hasn't been loaded yet */ ptr_user = slack_user_search(workspace, user); if (!ptr_user) - return 1; /* silently ignore if bot user hasn't been loaded yet */ + return 1; /* silently ignore if slackbot user hasn't been loaded yet */ char *message = slack_message_decode(workspace, text); weechat_printf_date_tags( diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 534f7b0..0fd0a04 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -15,6 +15,7 @@ #include "slack-api-message.h" #include "message/slack-api-message-unimplemented.h" #include "message/slack-api-message-bot-message.h" +#include "message/slack-api-message-me-message.h" #include "message/slack-api-message-slackbot-response.h" static const char *type = "message"; @@ -45,7 +46,7 @@ static struct stringcase cases[] = , { "group_purpose", &slack_api_message_unimplemented } , { "group_topic", &slack_api_message_unimplemented } , { "group_unarchive", &slack_api_message_unimplemented } -, { "me_message", &slack_api_message_unimplemented } +, { "me_message", &slack_api_message_me_message } , { "message_changed", &slack_api_message_unimplemented } , { "message_deleted", &slack_api_message_unimplemented } , { "message_replied", &slack_api_message_unimplemented } diff --git a/slack-user.h b/slack-user.h index 763c832..cc97ec4 100644 --- a/slack-user.h +++ b/slack-user.h @@ -50,6 +50,8 @@ struct t_slack_user struct t_slack_user *next_user; }; +const char *slack_user_get_colour(struct t_slack_user *user); + const char *slack_user_as_prefix(struct t_slack_workspace *workspace, struct t_slack_user *user, const char *name); diff --git a/weechat-plugin.h b/weechat-plugin.h index 5abb6d0..02dc525 100644 --- a/weechat-plugin.h +++ b/weechat-plugin.h @@ -1,7 +1,3 @@ -// 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/. - /* * weechat-plugin.h - header to compile WeeChat plugins * From a43417139eb755685cfc8fa73c7e48b8a5b3f9d5 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 19:15:20 +0100 Subject: [PATCH 035/118] Monkeypatch message.bot_message for undoc'd slackbot msgs. Fixes #6 --- README.org | 2 + api/message/slack-api-message-bot-message.c | 73 +++++++++++++++++---- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/README.org b/README.org index 4d963cd..62feb09 100644 --- a/README.org +++ b/README.org @@ -60,6 +60,8 @@ ** TODO [#C] Implement remaining api endpoints and events - [ ] Complete api endpoint set - [ ] Complete api event set +** TODO [#C] Implement full weechat functionality + - [ ] Hook buffer closes * Contributing diff --git a/api/message/slack-api-message-bot-message.c b/api/message/slack-api-message-bot-message.c index d3ae177..5a7b488 100644 --- a/api/message/slack-api-message-bot-message.c +++ b/api/message/slack-api-message-bot-message.c @@ -70,18 +70,50 @@ int slack_api_message_bot_message_handle(struct t_slack_workspace *workspace, return 1; } +int slack_api_message_slackbot_message_handle(struct t_slack_workspace *workspace, + const char *channel, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; /* silently ignore if slackbot user hasn't been loaded yet */ + + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message,slack_slackbot_message", + _("%s%s"), + slack_user_as_prefix(workspace, ptr_user, user), + message); + free(message); + + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + + return 1; +} + int slack_api_message_bot_message(struct t_slack_workspace *workspace, json_object *message) { - json_object *channel, *bot_id, *username, *text, *ts; + json_object *channel, *bot_id, *username, *user, *text, *ts; channel = json_object_object_get(message, "channel"); if (!json_valid(channel, workspace)) return 0; - bot_id = json_object_object_get(message, "bot_id"); - if (!json_valid(bot_id, workspace)) - return 0; - username = json_object_object_get(message, "username"); if (!json_valid(username, workspace)) return 0; @@ -94,11 +126,30 @@ int slack_api_message_bot_message(struct t_slack_workspace *workspace, if (!json_valid(ts, workspace)) return 0; - return slack_api_message_bot_message_handle(workspace, - json_object_get_string(channel), - json_object_get_string(bot_id), - json_object_get_string(username), - json_object_get_string(text), - json_object_get_string(ts)); + if (strcmp("slackbot", json_object_get_string(username)) == 0) + { + user = json_object_object_get(message, "user"); + if (!json_valid(user, workspace)) + return 0; + + return slack_api_message_slackbot_message_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user), + json_object_get_string(text), + json_object_get_string(ts)); + } + else + { + bot_id = json_object_object_get(message, "bot_id"); + if (!json_valid(bot_id, workspace)) + return 0; + + return slack_api_message_bot_message_handle(workspace, + json_object_get_string(channel), + json_object_get_string(bot_id), + json_object_get_string(username), + json_object_get_string(text), + json_object_get_string(ts)); + } } From 8284713cadf8334373d6fe539fd7cbd11af2f015 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 22:03:35 +0100 Subject: [PATCH 036/118] Implement chat.meMessage for /me (closes #5) --- Makefile | 1 + README.org | 3 +- request/slack-request-chat-memessage.c | 270 +++++++++++++++++++++++++ request/slack-request-chat-memessage.h | 13 ++ slack-command.c | 132 +++++++++--- 5 files changed, 389 insertions(+), 30 deletions(-) create mode 100644 request/slack-request-chat-memessage.c create mode 100644 request/slack-request-chat-memessage.h diff --git a/Makefile b/Makefile index 385ddda..63bb5ce 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ SRCS=slack.c \ api/message/slack-api-message-slackbot-response.c \ api/message/slack-api-message-me-message.c \ api/message/slack-api-message-unimplemented.c \ + request/slack-request-chat-memessage.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ request/slack-request-conversations-members.c \ diff --git a/README.org b/README.org index 62feb09..1a0d9c0 100644 --- a/README.org +++ b/README.org @@ -44,7 +44,7 @@ ** TODO [#A] Implement essential api endpoints and events - [X] +Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - - [ ] Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]]) + - [X] +Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - [ ] Implement handling api message =message.thread_broadcast= - [X] +Implement handling api message =message.bot_message= (see [[http://github.com/bqv/weechat-slack/issues/2][#2]])+ - [ ] Implement handling api message =message.message_changed= @@ -62,6 +62,7 @@ - [ ] Complete api event set ** TODO [#C] Implement full weechat functionality - [ ] Hook buffer closes + - [ ] Relay compatibility * Contributing diff --git a/request/slack-request-chat-memessage.c b/request/slack-request-chat-memessage.c new file mode 100644 index 0000000..38a0487 --- /dev/null +++ b/request/slack-request-chat-memessage.c @@ -0,0 +1,270 @@ +// 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 "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-request.h" +#include "../slack-user.h" +#include "../request/slack-request-chat-memessage.h" + +static const char *const endpoint = "/api/chat.meMessage?" + "token=%s&channel=%s&text=%s&"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error sending me-message: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + //__asm__("int3"); + return 0; + } + + return 1; +} + +static const struct lws_protocols protocols[]; + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + in ? (char *)in : "(null)"); + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) sending me-message... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + /* wait for websocket to catch up */ + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) failed to send me-message: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + /* fallthrough */ + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_chat_memessage( + struct t_slack_workspace *workspace, + const char *token, const char *channel, + const char *text) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + + size_t urilen = snprintf(NULL, 0, endpoint, token, channel, text) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token, channel, text); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-chat-memessage.h b/request/slack-request-chat-memessage.h new file mode 100644 index 0000000..d93c95b --- /dev/null +++ b/request/slack-request-chat-memessage.h @@ -0,0 +1,13 @@ +// 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/. + +#ifndef _SLACK_REQUEST_CHAT_MEMESSAGE_H_ +#define _SLACK_REQUEST_CHAT_MEMESSAGE_H_ + +struct t_slack_request *slack_request_chat_memessage( + struct t_slack_workspace *workspace, + const char *token, const char *channel, + const char *text); + +#endif /*SLACK_REQUEST_CHAT_MEMESSAGE_H*/ diff --git a/slack-command.c b/slack-command.c index 312ddca..b2dd04d 100644 --- a/slack-command.c +++ b/slack-command.c @@ -2,15 +2,20 @@ // 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 "weechat-plugin.h" #include "slack.h" -#include "slack-command.h" #include "slack-oauth.h" #include "slack-teaminfo.h" #include "slack-workspace.h" +#include "slack-channel.h" +#include "slack-buffer.h" +#include "slack-message.h" +#include "slack-command.h" +#include "request/slack-request-chat-memessage.h" void slack_command_display_workspace(struct t_slack_workspace *workspace) { @@ -30,7 +35,7 @@ void slack_command_display_workspace(struct t_slack_workspace *workspace) weechat_color("chat_delimiters"), weechat_color("chat_server"), (workspace->name) ? - workspace->name : "???", + workspace->name : "???", weechat_color("chat_delimiters"), weechat_color("reset"), (workspace->is_connected) ? @@ -52,7 +57,7 @@ void slack_command_display_workspace(struct t_slack_workspace *workspace) weechat_color("chat_delimiters"), weechat_color("chat_server"), (workspace->name) ? - workspace->name : "???", + workspace->name : "???", weechat_color("chat_delimiters"), weechat_color("reset")); } @@ -140,18 +145,18 @@ void slack_command_add_workspace(struct t_slack_teaminfo *slack_teaminfo) weechat_config_option_set(workspace->options[SLACK_WORKSPACE_OPTION_TOKEN], slack_teaminfo->token, 1); - weechat_printf ( - NULL, - _("%s: workspace %s%s%s.slack.com %s(%s%s%s)%s added"), - SLACK_PLUGIN_NAME, - weechat_color("chat_server"), - workspace->domain, - weechat_color("reset"), - weechat_color("chat_delimiters"), - weechat_color("chat_server"), - workspace->name, - weechat_color("chat_delimiters"), - weechat_color("reset")); + weechat_printf ( + NULL, + _("%s: workspace %s%s%s.slack.com %s(%s%s%s)%s added"), + SLACK_PLUGIN_NAME, + weechat_color("chat_server"), + workspace->domain, + weechat_color("reset"), + weechat_color("chat_delimiters"), + weechat_color("chat_server"), + workspace->name, + weechat_color("chat_delimiters"), + weechat_color("reset")); free_teaminfo(slack_teaminfo); } @@ -214,8 +219,8 @@ int slack_command_connect_workspace(struct t_slack_workspace *workspace) int slack_command_workspace_connect(int argc, char **argv) { - int i, nb_connect, connect_ok; - struct t_slack_workspace *ptr_workspace; + int i, nb_connect, connect_ok; + struct t_slack_workspace *ptr_workspace; (void) argc; (void) argv; @@ -223,17 +228,17 @@ int slack_command_workspace_connect(int argc, char **argv) connect_ok = 1; nb_connect = 0; - for (i = 2; i < argc; i++) - { + for (i = 2; i < argc; i++) + { nb_connect++; - ptr_workspace = slack_workspace_search(argv[i]); - if (ptr_workspace) - { + ptr_workspace = slack_workspace_search(argv[i]); + if (ptr_workspace) + { if (!slack_command_connect_workspace(ptr_workspace)) { connect_ok = 0; } - } + } else { weechat_printf( @@ -243,7 +248,7 @@ int slack_command_workspace_connect(int argc, char **argv) weechat_prefix("error"), SLACK_PLUGIN_NAME, argv[i]); } - } + } return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; } @@ -307,11 +312,11 @@ int slack_command_slack(const void *pointer, void *data, (void) data; (void) buffer; - if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) - { - slack_command_workspace_list(argc, argv); - return WEECHAT_RC_OK; - } + if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) + { + slack_command_workspace_list(argc, argv); + return WEECHAT_RC_OK; + } if (argc > 1) { @@ -339,6 +344,68 @@ int slack_command_slack(const void *pointer, void *data, return WEECHAT_RC_OK; } +int slack_command_me(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + struct t_slack_workspace *ptr_workspace = NULL; + struct t_slack_channel *ptr_channel = NULL; + struct t_slack_request *request; + char *text; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) buffer; + (void) argv; + + slack_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel); + + if (!ptr_workspace) + return WEECHAT_RC_ERROR; + + if (!ptr_channel) + { + weechat_printf ( + ptr_workspace->buffer, + _("%s%s: \"%s\" command can not be executed on a workspace buffer"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, "me"); + return WEECHAT_RC_OK; + } + + if (!ptr_workspace->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + text = malloc(SLACK_MESSAGE_MAX_LENGTH); + if (!text) + { + weechat_printf(buffer, + _("%s%s: error allocating string"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + return WEECHAT_RC_ERROR; + } + lws_urlencode(text, argv_eol[1], SLACK_MESSAGE_MAX_LENGTH); + + request = slack_request_chat_memessage(ptr_workspace, + weechat_config_string( + ptr_workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), + ptr_channel->id, text); + if (request) + slack_workspace_register_request(ptr_workspace, request); + + free(text); + } + + return WEECHAT_RC_OK; +} + void slack_command_init() { weechat_hook_command( @@ -357,4 +424,11 @@ void slack_command_init() " || connect %(slack_workspace)" " || delete %(slack_workspace)", &slack_command_slack, NULL, NULL); + + weechat_hook_command( + "me", + N_("send a slack action to the current channel"), + N_(""), + N_("message: message to send"), + NULL, &slack_command_me, NULL, NULL); } From 27254d5fd8cb750b04d25aa280decdb3ab71fb45 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 9 May 2018 23:58:37 +0100 Subject: [PATCH 037/118] Update README.org --- README.org | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.org b/README.org index 1a0d9c0..e529901 100644 --- a/README.org +++ b/README.org @@ -12,6 +12,10 @@ [[https://travis-ci.org/bqv/weechat-slack][file:https://api.travis-ci.org/bqv/weechat-slack.svg?branch=master]] [[https://coveralls.io/github/bqv/weechat-slack?branch=master][file:https://coveralls.io/repos/github/bqv/weechat-slack/badge.svg?branch=master]] +[[https://github.com/bqv/weechat-slack/issues][file:https://img.shields.io/github/issues/bqv/weechat-slack.svg]] +[[https://github.com/bqv/weechat-slack/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-slack.svg]] +[[https://github.com/bqv/weechat-slack/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-slack.svg]] +[[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-slack-yellow.svg]] | Status: | Under Development | | Location: | [[http://github.com/bqv/weechat-slack]] | @@ -42,7 +46,8 @@ * Tasks -** TODO [#A] Implement essential api endpoints and events +** DONE [#A] Implement basic functionality (milestone v0.1) +** TODO [#A] Implement essential api endpoints and events (milestone v0.2) - [X] +Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - [X] +Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - [ ] Implement handling api message =message.thread_broadcast= @@ -50,19 +55,20 @@ - [ ] Implement handling api message =message.message_changed= - [ ] Implement handling api message =message.message_deleted= - [ ] Implement handling api message =message.message_replied= -** TODO [#B] Implement completion engine +** TODO [#B] Implement completion engine (milestone v0.3) - [ ] Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]]) - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) -** TODO [#B] Implement debian packaging +** TODO [#B] Implement debian packaging (milestone v0.4) - [ ] Switch to system libwebsockets package (dynamically link) - [ ] Create configure build step (cmake? autotools?) -** TODO [#C] Implement remaining api endpoints and events +** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) - [ ] Complete api endpoint set - [ ] Complete api event set -** TODO [#C] Implement full weechat functionality +** TODO [#C] Implement full weechat functionality (milestone v0.6) - [ ] Hook buffer closes - [ ] Relay compatibility +** TODO [#D] Close all issues (milestone v1.0) * Contributing From 135f468ed442e265fc8a3e4ef26d716246508739 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 10 May 2018 00:12:42 +0100 Subject: [PATCH 038/118] Update README.org --- README.org | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.org b/README.org index e529901..72ec81f 100644 --- a/README.org +++ b/README.org @@ -43,6 +43,17 @@ Do *NOT* run make install as root, it installs the plugin to your local weechat plugins directory + +* Development + + I use emacs for development of this, although I am also a fan of vim. + My debug build process involves static analysis with clang and cppcheck, + and dynamic analysis with address-sanitizer and leak-sanitizer. + + I have no real requests for style of pull requests besides a wish that + you keep vaguely to the style I have adopted for this project. + + Happy coding! * Tasks From 3e7eb06ff7e27d422b6f389f2a8ec94133b2ced0 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 10 May 2018 09:32:24 +0100 Subject: [PATCH 039/118] Describe debug process --- README.org | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.org b/README.org index 72ec81f..25f3dd0 100644 --- a/README.org +++ b/README.org @@ -49,6 +49,9 @@ I use emacs for development of this, although I am also a fan of vim. My debug build process involves static analysis with clang and cppcheck, and dynamic analysis with address-sanitizer and leak-sanitizer. + My debug evaluation process involves gdb/mi run with the arguments + =-ex "handle SIGPIPE nostop noprint pass" --args weechat -a 2>asan.log= + since part of weechat and it's default plugins use SIGPIPE as control. I have no real requests for style of pull requests besides a wish that you keep vaguely to the style I have adopted for this project. From 601209ae8132b18c67dda5b3afb1f8018e60cabc Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 10 May 2018 15:20:06 +0100 Subject: [PATCH 040/118] Switch to git-buildpackage --- README.org | 2 +- ...1de74b130f35082fb45a12e9ead42ad5c775f9b64f | 1825 ----------------- ...6353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 | 1462 ------------- debian/.debhelper/bucket/index | 2 - debian/changelog | 33 +- debian/control | 3 +- debian/debhelper-build-stamp | 1 - 7 files changed, 32 insertions(+), 3296 deletions(-) delete mode 100755 debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f delete mode 100755 debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 delete mode 100644 debian/.debhelper/bucket/index delete mode 100644 debian/debhelper-build-stamp diff --git a/README.org b/README.org index 25f3dd0..d91695a 100644 --- a/README.org +++ b/README.org @@ -74,7 +74,7 @@ - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) ** TODO [#B] Implement debian packaging (milestone v0.4) - - [ ] Switch to system libwebsockets package (dynamically link) + - [ ] Switch to system libwebsockets package (dynamically link) (see [[http://github.com/bqv/weechat-slack/issues/7][#7]]) - [ ] Create configure build step (cmake? autotools?) ** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) - [ ] Complete api endpoint set diff --git a/debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f b/debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f deleted file mode 100755 index dd2ca93..0000000 --- a/debian/.debhelper/bucket/files/1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f +++ /dev/null @@ -1,1825 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. - -timestamp='2016-11-04' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2016 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix* | -fuchsia*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -ios) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 b/debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 deleted file mode 100755 index 2e9ad7f..0000000 --- a/debian/.debhelper/bucket/files/8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 +++ /dev/null @@ -1,1462 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. - -timestamp='2016-10-02' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess -# -# Please send patches to . - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ - echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown - ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently (or will in the future) and ABI. - case "${UNAME_MACHINE_ARCH}" in - earm*) - os=netbsdelf - ;; - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE=alpha ;; - "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; - "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; - "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; - "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; - "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; - "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; - "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; - "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; - "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; - "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; - "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = hppa2.0w ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH=hppa2.0w - else - HP_ARCH=hppa64 - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - mips64el:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} - exit ;; - or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = 386; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; - amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; -esac - -cat >&2 </dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/debian/.debhelper/bucket/index b/debian/.debhelper/bucket/index deleted file mode 100644 index effd394..0000000 --- a/debian/.debhelper/bucket/index +++ /dev/null @@ -1,2 +0,0 @@ -8131853dbc8c3be5171fa96353de7a884a79d3f1d6b3fbf48f99037f5f95fe27 json-c/config.guess -1ee0b1581032c46aac6ebd1de74b130f35082fb45a12e9ead42ad5c775f9b64f json-c/config.sub diff --git a/debian/changelog b/debian/changelog index 4fcdaa3..1e355d9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,31 @@ -weechat-slack (0~1805071648-1) UNRELEASED; urgency=low +weechat-slack (0.1) UNRELEASED; urgency=medium - * Initial release. Closes: #nnnn - + [ Tony Olagbaiye ] + * Initial release. + * Bot messages + * Slackbot responses + * CTags + * Fix channel mentions. Closes #2 + * License headers + * Administration + * Add TODO to readme + * Fix makefile to find libwebsockets.h + * Build libwebsockets first + * Revert libwebsockets header change + * Build libjson-c before too + * Typo + * Move sanitizers to debug build + * Fix make install + * Fix install finally + * Just remove `make install` from travis + * Update README.org + * Handle message.me_message (ref #5) + * Monkeypatch message.bot_message for undoc'd slackbot msgs. Fixes #6 + * Implement chat.meMessage for /me (closes #5) + * Update README.org + * Update README.org + * Describe debug process - -- Bao Mon, 07 May 2018 17:48:57 +0100 + [ Bao ] + + -- Bao Thu, 10 May 2018 15:18:26 +0100 diff --git a/debian/control b/debian/control index 80bcd14..a118b2d 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,8 @@ Vcs-Browser: https://github.com/bqv/weechat-slack Package: weechat-slack Architecture: all Depends: - weechat (>= 1.4) + weechat (>= 1.4), + libwebsockets (>= 2.0) Description: Fast, light and extensible chat client - Slack plugin WeeChat (Wee Enhanced Environment for Chat) is a fast and light chat client for many operating systems. Everything can be done with a keyboard. diff --git a/debian/debhelper-build-stamp b/debian/debhelper-build-stamp deleted file mode 100644 index a1dc01d..0000000 --- a/debian/debhelper-build-stamp +++ /dev/null @@ -1 +0,0 @@ -weechat-slack From 95261b2fc4a326f0ffcc12f312f6df4b8b93765c Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 10 May 2018 15:40:10 +0100 Subject: [PATCH 041/118] Packaging --- .gitignore | 2 ++ Makefile | 36 ++++++++++++++++++++++++--------- debian/changelog | 2 +- debian/control | 13 ++++++++---- debian/files | 1 + debian/rules | 17 ++++++++-------- debian/source/lintian-overrides | 6 ++++++ 7 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 debian/files create mode 100644 debian/source/lintian-overrides diff --git a/.gitignore b/.gitignore index 8498b9d..a49f82a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ # Prerequisites +debian/weechat-slack/ +.debhelper/ compile_commands.json cscope* .depend diff --git a/Makefile b/Makefile index 63bb5ce..b4d05ed 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,18 @@ -CC=clang -CXX=g++ -RM=rm -f ifdef DEBUG - SANCFLAGS=-fsanitize=address -fsanitize=leak - SANLDFLAGS=-static-libasan -static-liblsan + CC=clang + CXX=g++ + DBGCFLAGS=-fsanitize=address -fsanitize=leak + DBGLDFLAGS=-static-libasan -static-liblsan endif -CFLAGS=$(SANCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c -LDFLAGS=-shared -g $(SANCFLAGS) $(SANLDFLAGS) +RM=rm -f +CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c +LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) LDLIBS=-lgnutls +PREFIX ?= /usr/local +LIBDIR ?= $(PREFIX)/lib +INSTALL ?= /usr/bin/install + SRCS=slack.c \ slack-api.c \ slack-buffer.c \ @@ -43,11 +47,11 @@ weechat-slack: $(OBJS) $(CXX) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) libwebsockets/lib/libwebsockets.a: - cd libwebsockets && cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . + cd libwebsockets && env CFLAGS= LDFLAGS= cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . $(MAKE) -C libwebsockets json-c/libjson-c.a: - cd json-c && cmake -DCMAKE_C_FLAGS=-fPIC . + cd json-c && env CFLAGS= LDFLAGS= cmake -DCMAKE_C_FLAGS=-fPIC . $(MAKE) -C json-c json-c-static depend: .depend @@ -60,12 +64,24 @@ clean: $(RM) $(OBJS) $(MAKE) -C libwebsockets clean $(MAKE) -C json-c clean + git submodule foreach --recursive git clean -xfd || true + git submodule foreach --recursive git reset --hard || true + git submodule update --init --recursive || true distclean: clean $(RM) *~ .depend install: slack.so - install -t ~/.weechat/plugins -D slack.so +ifeq ($(shell id -u),0) + $(INSTALL) -s -t $(DESTDIR)$(LIBDIR)/weechat/plugins -D -m 0755 slack.so +else + $(INSTALL) -s -t ~/.weechat/plugins -D -m 0755 slack.so +endif + +package-debian: + env ARCH=i386 gbp buildpackage --git-arch=i386 --git-ignore-new --git-pbuilder + env ARCH=amd64 gbp buildpackage --git-arch=amd64 --git-ignore-new --git-pbuilder +# gbp buildpackage -S --git-ignore-new .PHONY: tags cs diff --git a/debian/changelog b/debian/changelog index 1e355d9..cbe0a3f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -weechat-slack (0.1) UNRELEASED; urgency=medium +weechat-slack (0.1.0) sid; urgency=medium [ Tony Olagbaiye ] * Initial release. diff --git a/debian/control b/debian/control index a118b2d..5d845d0 100644 --- a/debian/control +++ b/debian/control @@ -2,17 +2,22 @@ Source: weechat-slack Section: net Priority: optional Maintainer: Tony Olagbaiye -Build-Depends: cmake, debhelper (>= 11), pkg-config -Standards-Version: 4.1.3 +Build-Depends: + cmake, pkg-config, + debhelper (>= 11), + libssl-dev, + libgnutls28-dev +Standards-Version: 4.0.0 Homepage: https://weechat.org/ Vcs-Git: https://github.com/bqv/weechat-slack.git Vcs-Browser: https://github.com/bqv/weechat-slack Package: weechat-slack -Architecture: all +Architecture: any Depends: weechat (>= 1.4), - libwebsockets (>= 2.0) + ${shlibs:Depends}, + ${misc:Depends} Description: Fast, light and extensible chat client - Slack plugin WeeChat (Wee Enhanced Environment for Chat) is a fast and light chat client for many operating systems. Everything can be done with a keyboard. diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..55d3874 --- /dev/null +++ b/debian/files @@ -0,0 +1 @@ +weechat-slack_0.1.0_source.buildinfo net optional diff --git a/debian/rules b/debian/rules index c564dbf..3cf9a4e 100755 --- a/debian/rules +++ b/debian/rules @@ -1,18 +1,17 @@ #!/usr/bin/make -f -# You must remove unused comment lines for the released package. + +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + #export DH_VERBOSE = 1 #export DEB_BUILD_MAINT_OPTIONS = hardening=+all #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic -#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed -export JAVA_HOME=/usr/lib/jvm/default-java -export CLASSPATH=/usr/share/java/csv.jar:/usr/share/java/debug-disable.jar:/usr/share/java/itext.jar +export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed %: dh $@ --without autoreconf +override_dh_auto_install: + dh_auto_install -- LIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH) -#override_dh_auto_install: -# dh_auto_install -- prefix=/usr - -#override_dh_install: -# dh_install --list-missing -X.pyc -X.pyo +override_dh_install: + dh_install diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides new file mode 100644 index 0000000..75668d3 --- /dev/null +++ b/debian/source/lintian-overrides @@ -0,0 +1,6 @@ +# This is an override for the following lintian errors: +# E: weechat-slack source: source-is-missing libwebsockets/plugins/generic-sessions/assets/lwsgs.js +# E: weechat-slack source: source-is-missing libwebsockets/plugins/generic-sessions/assets/md5.min.js +# The source is not missing, all sources are included. +# This is a lintian false-positive. +weechat-slack source: source-is-missing \ No newline at end of file From c771e3bf19c2485b8bfaa6d6ae98d480f409ed13 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 11 May 2018 02:07:51 +0100 Subject: [PATCH 042/118] Debian packaging implemented We won't switch to the system libwebsockets package as we need custom behaviour and don't want to be linked against openssl. We don't need to bother with a configure build step as it seems the current Makefile is sufficient for packaging. --- README.org | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.org b/README.org index d91695a..8fb1fd1 100644 --- a/README.org +++ b/README.org @@ -73,9 +73,6 @@ - [ ] Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]]) - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) -** TODO [#B] Implement debian packaging (milestone v0.4) - - [ ] Switch to system libwebsockets package (dynamically link) (see [[http://github.com/bqv/weechat-slack/issues/7][#7]]) - - [ ] Create configure build step (cmake? autotools?) ** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) - [ ] Complete api endpoint set - [ ] Complete api event set From 06b81810a58c83c75aeaeafc145bd5a034238a73 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 11 May 2018 03:31:21 +0100 Subject: [PATCH 043/118] Installing --- README.org | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.org b/README.org index 8fb1fd1..a43ce62 100644 --- a/README.org +++ b/README.org @@ -26,6 +26,11 @@ A weechat plugin in C to extend the chat client to support Slack workspaces via the RTM and Web APIs. +* Installing + + See http://github.com/bqv/weechat-extras for the suite this is part of + and a repository/package for your distribution. + * Dependencies - libwebsockets (static, submodule) From b762aa3a8c8a955b34ec6ce2841947d93a596ad9 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 11 May 2018 11:38:01 +0100 Subject: [PATCH 044/118] Nicklist colours --- Makefile | 4 ++-- slack-user.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index b4d05ed..953f6ee 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ endif RM=rm -f CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) -LDLIBS=-lgnutls +LDLIBS=-Wl,--push-state,--as-needed -lgnutls PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -73,7 +73,7 @@ distclean: clean install: slack.so ifeq ($(shell id -u),0) - $(INSTALL) -s -t $(DESTDIR)$(LIBDIR)/weechat/plugins -D -m 0755 slack.so + $(INSTALL) -s -t $(DESTDIR)$(LIBDIR)/weechat/plugins -D -m 0644 slack.so else $(INSTALL) -s -t ~/.weechat/plugins -D -m 0755 slack.so endif diff --git a/slack-user.c b/slack-user.c index 5794b7b..ff3fcd2 100644 --- a/slack-user.c +++ b/slack-user.c @@ -17,6 +17,11 @@ const char *slack_user_get_colour(struct t_slack_user *user) return weechat_info_get("nick_color", user->profile.display_name); } +const char *slack_user_get_colour_for_nicklist(struct t_slack_user *user) +{ + return weechat_info_get("nick_color_name", user->profile.display_name); +} + const char *slack_user_as_prefix(struct t_slack_workspace *workspace, struct t_slack_user *user, const char *name) @@ -83,11 +88,11 @@ void slack_user_nicklist_add(struct t_slack_workspace *workspace, "+" : "..."); weechat_nicklist_add_nick(ptr_buffer, ptr_group, user->profile.display_name, - weechat_color(user->is_away ? - "weechat.color.nicklist_away" : - "bar_fg"), + user->is_away ? + "weechat.color.nicklist_away" : + slack_user_get_colour_for_nicklist(user), user->is_away ? "+" : "", - weechat_color(""), + "bar_fg", 1); } From 3e0cd6e8d550a6d04a803619b70e6bbb0873b4a6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 11 May 2018 17:16:27 +0100 Subject: [PATCH 045/118] Add standard slack emoji to a compilation unit --- Makefile | 4 + README.org | 5 + slack-emoji.c | 12 + slack-emoji.h | 10 + slack-emoji.inc | 1698 +++++++++++++++++++++++++++++++++++++++++++++++ slack-emoji.py | 50 ++ 6 files changed, 1779 insertions(+) create mode 100644 slack-emoji.c create mode 100644 slack-emoji.h create mode 100644 slack-emoji.inc create mode 100755 slack-emoji.py diff --git a/Makefile b/Makefile index 953f6ee..621ad4a 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ SRCS=slack.c \ slack-channel.c \ slack-config.c \ slack-command.c \ + slack-emoji.c \ slack-input.c \ slack-message.c \ slack-oauth.c \ @@ -46,6 +47,9 @@ all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack weechat-slack: $(OBJS) $(CXX) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) +slack-emoji.inc: slack-emoji.py + env python3 slack-emoji.py > slack-emoji.inc + libwebsockets/lib/libwebsockets.a: cd libwebsockets && env CFLAGS= LDFLAGS= cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . $(MAKE) -C libwebsockets diff --git a/README.org b/README.org index a43ce62..b7842af 100644 --- a/README.org +++ b/README.org @@ -74,10 +74,15 @@ - [ ] Implement handling api message =message.message_changed= - [ ] Implement handling api message =message.message_deleted= - [ ] Implement handling api message =message.message_replied= + - [ ] Implement sending websocket =typing= message ** TODO [#B] Implement completion engine (milestone v0.3) - [ ] Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]]) + - [ ] Support Slack Emoji + - [ ] Support Custom Emoji - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) +** TODO [#B] Implement websocket ping and pong (milestone v0.4) + - [ ] Add ping timer and pong handler (see [[http://github.com/bqv/weechat-slack/issues/9][#9]]) ** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) - [ ] Complete api endpoint set - [ ] Complete api event set diff --git a/slack-emoji.c b/slack-emoji.c new file mode 100644 index 0000000..21983cf --- /dev/null +++ b/slack-emoji.c @@ -0,0 +1,12 @@ +// 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 "weechat-plugin.h" +#include "slack.h" +#include "slack-emoji.h" + +#include "slack-emoji.inc" + diff --git a/slack-emoji.h b/slack-emoji.h new file mode 100644 index 0000000..26ae2c4 --- /dev/null +++ b/slack-emoji.h @@ -0,0 +1,10 @@ +// 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/. + +#ifndef _SLACK_EMOJI_H_ +#define _SLACK_EMOJI_H_ + + + +#endif /*SLACK_EMOJI_H*/ diff --git a/slack-emoji.inc b/slack-emoji.inc new file mode 100644 index 0000000..743c407 --- /dev/null +++ b/slack-emoji.inc @@ -0,0 +1,1698 @@ + +#include + +#define MAX_TEXTS 7 +#define MAX_NAMES 4 + +struct t_slack_emoji_by_name { + const char *name; + const char *unicode; + const char *text_to; + const char *text_from[MAX_TEXTS]; +}; + +struct t_slack_emoji_by_text { + const char *text; + const char *unicode; + const char *name_to; + const char *name_from[MAX_NAMES]; +}; + +static struct t_slack_emoji_by_name slack_emoji_by_name[] = +{ { "+1", "\u1f44D", NULL, {NULL} } +, { "-1", "\u1f44E", NULL, {NULL} } +, { "100", "\u1f4aF", NULL, {NULL} } +, { "1234", "\u1f522", NULL, {NULL} } +, { "8ball", "\u1f3b1", NULL, {NULL} } +, { "a", "\u1f170\ufe0f", NULL, {NULL} } +, { "ab", "\u1f18E", NULL, {NULL} } +, { "abc", "\u1f524", NULL, {NULL} } +, { "abcd", "\u1f521", NULL, {NULL} } +, { "accept", "\u1f251", NULL, {NULL} } +, { "admission_tickets", "\u1f39F\ufe0f", NULL, {NULL} } +, { "adult", "\u1f9d1", NULL, {NULL} } +, { "aerial_tramway", "\u1f6a1", NULL, {NULL} } +, { "airplane", "\u2708\ufe0f", NULL, {NULL} } +, { "airplane_arriving", "\u1f6eC", NULL, {NULL} } +, { "airplane_departure", "\u1f6eB", NULL, {NULL} } +, { "alarm_clock", "\u23f0", NULL, {NULL} } +, { "alembic", "\u2697\ufe0f", NULL, {NULL} } +, { "alien", "\u1f47D", NULL, {NULL} } +, { "ambulance", "\u1f691", NULL, {NULL} } +, { "amphora", "\u1f3fA", NULL, {NULL} } +, { "anchor", "\u2693", NULL, {NULL} } +, { "angel", "\u1f47C", NULL, {NULL} } +, { "anger", "\u1f4a2", NULL, {NULL} } +, { "angry", "\u1f620", NULL, {">:(", ">:-(", NULL} } +, { "anguished", "\u1f627", NULL, {"D:", NULL} } +, { "ant", "\u1f41C", NULL, {NULL} } +, { "apple", "\u1f34E", NULL, {NULL} } +, { "aquarius", "\u2652", NULL, {NULL} } +, { "aries", "\u2648", NULL, {NULL} } +, { "arrow_backward", "\u25c0\ufe0f", NULL, {NULL} } +, { "arrow_double_down", "\u23ec", NULL, {NULL} } +, { "arrow_double_up", "\u23eb", NULL, {NULL} } +, { "arrow_down", "\u2b07\ufe0f", NULL, {NULL} } +, { "arrow_down_small", "\u1f53D", NULL, {NULL} } +, { "arrow_forward", "\u25b6\ufe0f", NULL, {NULL} } +, { "arrow_heading_down", "\u2935\ufe0f", NULL, {NULL} } +, { "arrow_heading_up", "\u2934\ufe0f", NULL, {NULL} } +, { "arrow_left", "\u2b05\ufe0f", NULL, {NULL} } +, { "arrow_lower_left", "\u2199\ufe0f", NULL, {NULL} } +, { "arrow_lower_right", "\u2198\ufe0f", NULL, {NULL} } +, { "arrow_right", "\u27a1\ufe0f", NULL, {NULL} } +, { "arrow_right_hook", "\u21aa\ufe0f", NULL, {NULL} } +, { "arrow_up", "\u2b06\ufe0f", NULL, {NULL} } +, { "arrow_up_down", "\u2195\ufe0f", NULL, {NULL} } +, { "arrow_up_small", "\u1f53C", NULL, {NULL} } +, { "arrow_upper_left", "\u2196\ufe0f", NULL, {NULL} } +, { "arrow_upper_right", "\u2197\ufe0f", NULL, {NULL} } +, { "arrows_clockwise", "\u1f503", NULL, {NULL} } +, { "arrows_counterclockwise", "\u1f504", NULL, {NULL} } +, { "art", "\u1f3a8", NULL, {NULL} } +, { "articulated_lorry", "\u1f69B", NULL, {NULL} } +, { "astonished", "\u1f632", NULL, {NULL} } +, { "athletic_shoe", "\u1f45F", NULL, {NULL} } +, { "atm", "\u1f3e7", NULL, {NULL} } +, { "atom_symbol", "\u269b\ufe0f", NULL, {NULL} } +, { "avocado", "\u1f951", NULL, {NULL} } +, { "b", "\u1f171\ufe0f", NULL, {NULL} } +, { "baby", "\u1f476", NULL, {NULL} } +, { "baby_bottle", "\u1f37C", NULL, {NULL} } +, { "baby_chick", "\u1f424", NULL, {NULL} } +, { "baby_symbol", "\u1f6bC", NULL, {NULL} } +, { "back", "\u1f519", NULL, {NULL} } +, { "bacon", "\u1f953", NULL, {NULL} } +, { "badminton_racquet_and_shuttlecock", "\u1f3f8", NULL, {NULL} } +, { "baggage_claim", "\u1f6c4", NULL, {NULL} } +, { "baguette_bread", "\u1f956", NULL, {NULL} } +, { "balloon", "\u1f388", NULL, {NULL} } +, { "ballot_box_with_ballot", "\u1f5f3\ufe0f", NULL, {NULL} } +, { "ballot_box_with_check", "\u2611\ufe0f", NULL, {NULL} } +, { "bamboo", "\u1f38D", NULL, {NULL} } +, { "banana", "\u1f34C", NULL, {NULL} } +, { "bangbang", "\u203c\ufe0f", NULL, {NULL} } +, { "bank", "\u1f3e6", NULL, {NULL} } +, { "bar_chart", "\u1f4cA", NULL, {NULL} } +, { "barber", "\u1f488", NULL, {NULL} } +, { "barely_sunny", "\u1f325\ufe0f", NULL, {NULL} } +, { "baseball", "\u26be", NULL, {NULL} } +, { "basketball", "\u1f3c0", NULL, {NULL} } +, { "bat", "\u1f987", NULL, {NULL} } +, { "bath", "\u1f6c0", NULL, {NULL} } +, { "bathtub", "\u1f6c1", NULL, {NULL} } +, { "battery", "\u1f50B", NULL, {NULL} } +, { "beach_with_umbrella", "\u1f3d6\ufe0f", NULL, {NULL} } +, { "bear", "\u1f43B", NULL, {NULL} } +, { "bearded_person", "\u1f9d4", NULL, {NULL} } +, { "bed", "\u1f6cF\ufe0f", NULL, {NULL} } +, { "bee", "\u1f41D", NULL, {NULL} } +, { "beer", "\u1f37A", NULL, {NULL} } +, { "beers", "\u1f37B", NULL, {NULL} } +, { "beetle", "\u1f41E", NULL, {NULL} } +, { "beginner", "\u1f530", NULL, {NULL} } +, { "bell", "\u1f514", NULL, {NULL} } +, { "bellhop_bell", "\u1f6cE\ufe0f", NULL, {NULL} } +, { "bento", "\u1f371", NULL, {NULL} } +, { "bicyclist", "\u1f6b4", NULL, {NULL} } +, { "bike", "\u1f6b2", NULL, {NULL} } +, { "bikini", "\u1f459", NULL, {NULL} } +, { "billed_cap", "\u1f9e2", NULL, {NULL} } +, { "biohazard_sign", "\u2623\ufe0f", NULL, {NULL} } +, { "bird", "\u1f426", NULL, {NULL} } +, { "birthday", "\u1f382", NULL, {NULL} } +, { "black_circle", "\u26ab", NULL, {NULL} } +, { "black_circle_for_record", "\u23fa\ufe0f", NULL, {NULL} } +, { "black_heart", "\u1f5a4", NULL, {NULL} } +, { "black_joker", "\u1f0cF", NULL, {NULL} } +, { "black_large_square", "\u2b1b", NULL, {NULL} } +, { "black_left_pointing_double_triangle_with_vertical_bar", "\u23ee\ufe0f", NULL, {NULL} } +, { "black_medium_small_square", "\u25fe", NULL, {NULL} } +, { "black_medium_square", "\u25fc\ufe0f", NULL, {NULL} } +, { "black_nib", "\u2712\ufe0f", NULL, {NULL} } +, { "black_right_pointing_double_triangle_with_vertical_bar", "\u23ed\ufe0f", NULL, {NULL} } +, { "black_right_pointing_triangle_with_double_vertical_bar", "\u23ef\ufe0f", NULL, {NULL} } +, { "black_small_square", "\u25aa\ufe0f", NULL, {NULL} } +, { "black_square_button", "\u1f532", NULL, {NULL} } +, { "black_square_for_stop", "\u23f9\ufe0f", NULL, {NULL} } +, { "blond-haired-man", "\u1f471\u200d\u2642\ufe0f", NULL, {NULL} } +, { "blond-haired-woman", "\u1f471\u200d\u2640\ufe0f", NULL, {NULL} } +, { "blossom", "\u1f33C", NULL, {NULL} } +, { "blowfish", "\u1f421", NULL, {NULL} } +, { "blue_book", "\u1f4d8", NULL, {NULL} } +, { "blue_car", "\u1f699", NULL, {NULL} } +, { "blue_heart", "\u1f499", "<3", {NULL} } +, { "blush", "\u1f60A", ":)", {NULL} } +, { "boar", "\u1f417", NULL, {NULL} } +, { "boat", "\u26f5", NULL, {NULL} } +, { "bomb", "\u1f4a3", NULL, {NULL} } +, { "book", "\u1f4d6", NULL, {NULL} } +, { "bookmark", "\u1f516", NULL, {NULL} } +, { "bookmark_tabs", "\u1f4d1", NULL, {NULL} } +, { "books", "\u1f4dA", NULL, {NULL} } +, { "boom", "\u1f4a5", NULL, {NULL} } +, { "boot", "\u1f462", NULL, {NULL} } +, { "bouquet", "\u1f490", NULL, {NULL} } +, { "bow", "\u1f647", NULL, {NULL} } +, { "bow_and_arrow", "\u1f3f9", NULL, {NULL} } +, { "bowl_with_spoon", "\u1f963", NULL, {NULL} } +, { "bowling", "\u1f3b3", NULL, {NULL} } +, { "boxing_glove", "\u1f94A", NULL, {NULL} } +, { "boy", "\u1f466", NULL, {NULL} } +, { "brain", "\u1f9e0", NULL, {NULL} } +, { "bread", "\u1f35E", NULL, {NULL} } +, { "breast-feeding", "\u1f931", NULL, {NULL} } +, { "bride_with_veil", "\u1f470", NULL, {NULL} } +, { "bridge_at_night", "\u1f309", NULL, {NULL} } +, { "briefcase", "\u1f4bC", NULL, {NULL} } +, { "broccoli", "\u1f966", NULL, {NULL} } +, { "broken_heart", "\u1f494", "", ":->", NULL} } +, { "leaves", "\u1f343", NULL, {NULL} } +, { "ledger", "\u1f4d2", NULL, {NULL} } +, { "left-facing_fist", "\u1f91B", NULL, {NULL} } +, { "left_luggage", "\u1f6c5", NULL, {NULL} } +, { "left_right_arrow", "\u2194\ufe0f", NULL, {NULL} } +, { "left_speech_bubble", "\u1f5e8\ufe0f", NULL, {NULL} } +, { "leftwards_arrow_with_hook", "\u21a9\ufe0f", NULL, {NULL} } +, { "lemon", "\u1f34B", NULL, {NULL} } +, { "leo", "\u264c", NULL, {NULL} } +, { "leopard", "\u1f406", NULL, {NULL} } +, { "level_slider", "\u1f39A\ufe0f", NULL, {NULL} } +, { "libra", "\u264e", NULL, {NULL} } +, { "light_rail", "\u1f688", NULL, {NULL} } +, { "lightning", "\u1f329\ufe0f", NULL, {NULL} } +, { "lightning_cloud", "\u1f329\ufe0f", NULL, {NULL} } +, { "link", "\u1f517", NULL, {NULL} } +, { "linked_paperclips", "\u1f587\ufe0f", NULL, {NULL} } +, { "lion_face", "\u1f981", NULL, {NULL} } +, { "lips", "\u1f444", NULL, {NULL} } +, { "lipstick", "\u1f484", NULL, {NULL} } +, { "lizard", "\u1f98E", NULL, {NULL} } +, { "lock", "\u1f512", NULL, {NULL} } +, { "lock_with_ink_pen", "\u1f50F", NULL, {NULL} } +, { "lollipop", "\u1f36D", NULL, {NULL} } +, { "loop", "\u27bf", NULL, {NULL} } +, { "loud_sound", "\u1f50A", NULL, {NULL} } +, { "loudspeaker", "\u1f4e2", NULL, {NULL} } +, { "love_hotel", "\u1f3e9", NULL, {NULL} } +, { "love_letter", "\u1f48C", NULL, {NULL} } +, { "low_brightness", "\u1f505", NULL, {NULL} } +, { "lower_left_ballpoint_pen", "\u1f58A\ufe0f", NULL, {NULL} } +, { "lower_left_crayon", "\u1f58D\ufe0f", NULL, {NULL} } +, { "lower_left_fountain_pen", "\u1f58B\ufe0f", NULL, {NULL} } +, { "lower_left_paintbrush", "\u1f58C\ufe0f", NULL, {NULL} } +, { "lying_face", "\u1f925", NULL, {NULL} } +, { "m", "\u24c2\ufe0f", NULL, {NULL} } +, { "mag", "\u1f50D", NULL, {NULL} } +, { "mag_right", "\u1f50E", NULL, {NULL} } +, { "mage", "\u1f9d9", NULL, {NULL} } +, { "mahjong", "\u1f004", NULL, {NULL} } +, { "mailbox", "\u1f4eB", NULL, {NULL} } +, { "mailbox_closed", "\u1f4eA", NULL, {NULL} } +, { "mailbox_with_mail", "\u1f4eC", NULL, {NULL} } +, { "mailbox_with_no_mail", "\u1f4eD", NULL, {NULL} } +, { "male-artist", "\u1f468\u200d\u1f3a8", NULL, {NULL} } +, { "male-astronaut", "\u1f468\u200d\u1f680", NULL, {NULL} } +, { "male-construction-worker", "\u1f477\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male-cook", "\u1f468\u200d\u1f373", NULL, {NULL} } +, { "male-detective", "\u1f575\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male-doctor", "\u1f468\u200d\u2695\ufe0f", NULL, {NULL} } +, { "male-factory-worker", "\u1f468\u200d\u1f3eD", NULL, {NULL} } +, { "male-farmer", "\u1f468\u200d\u1f33E", NULL, {NULL} } +, { "male-firefighter", "\u1f468\u200d\u1f692", NULL, {NULL} } +, { "male-guard", "\u1f482\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male-judge", "\u1f468\u200d\u2696\ufe0f", NULL, {NULL} } +, { "male-mechanic", "\u1f468\u200d\u1f527", NULL, {NULL} } +, { "male-office-worker", "\u1f468\u200d\u1f4bC", NULL, {NULL} } +, { "male-pilot", "\u1f468\u200d\u2708\ufe0f", NULL, {NULL} } +, { "male-police-officer", "\u1f46E\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male-scientist", "\u1f468\u200d\u1f52C", NULL, {NULL} } +, { "male-singer", "\u1f468\u200d\u1f3a4", NULL, {NULL} } +, { "male-student", "\u1f468\u200d\u1f393", NULL, {NULL} } +, { "male-teacher", "\u1f468\u200d\u1f3eB", NULL, {NULL} } +, { "male-technologist", "\u1f468\u200d\u1f4bB", NULL, {NULL} } +, { "male_elf", "\u1f9dD\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male_fairy", "\u1f9dA\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male_genie", "\u1f9dE\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male_mage", "\u1f9d9\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male_sign", "\u2642\ufe0f", NULL, {NULL} } +, { "male_vampire", "\u1f9dB\u200d\u2642\ufe0f", NULL, {NULL} } +, { "male_zombie", "\u1f9dF\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man", "\u1f468", NULL, {NULL} } +, { "man-biking", "\u1f6b4\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-bouncing-ball", "\u26f9\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-bowing", "\u1f647\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-boy", "\u1f468\u200d\u1f466", NULL, {NULL} } +, { "man-boy-boy", "\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { "man-cartwheeling", "\u1f938\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-facepalming", "\u1f926\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-frowning", "\u1f64D\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-gesturing-no", "\u1f645\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-gesturing-ok", "\u1f646\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-getting-haircut", "\u1f487\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-getting-massage", "\u1f486\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-girl", "\u1f468\u200d\u1f467", NULL, {NULL} } +, { "man-girl-boy", "\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { "man-girl-girl", "\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { "man-golfing", "\u1f3cC\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-heart-man", "\u1f468\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } +, { "man-juggling", "\u1f939\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-kiss-man", "\u1f468\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } +, { "man-lifting-weights", "\u1f3cB\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-man-boy", "\u1f468\u200d\u1f468\u200d\u1f466", NULL, {NULL} } +, { "man-man-boy-boy", "\u1f468\u200d\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { "man-man-girl", "\u1f468\u200d\u1f468\u200d\u1f467", NULL, {NULL} } +, { "man-man-girl-boy", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { "man-man-girl-girl", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { "man-mountain-biking", "\u1f6b5\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-playing-handball", "\u1f93E\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-playing-water-polo", "\u1f93D\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-pouting", "\u1f64E\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-raising-hand", "\u1f64B\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-rowing-boat", "\u1f6a3\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-running", "\u1f3c3\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-shrugging", "\u1f937\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-surfing", "\u1f3c4\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-swimming", "\u1f3cA\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-tipping-hand", "\u1f481\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-walking", "\u1f6b6\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-wearing-turban", "\u1f473\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-with-bunny-ears-partying", "\u1f46F\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man-woman-boy", "\u1f468\u200d\u1f469\u200d\u1f466", NULL, {NULL} } +, { "man-woman-boy", "\u1f46A", NULL, {NULL} } +, { "man-woman-boy-boy", "\u1f468\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { "man-woman-girl", "\u1f468\u200d\u1f469\u200d\u1f467", NULL, {NULL} } +, { "man-woman-girl-boy", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { "man-woman-girl-girl", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { "man-wrestling", "\u1f93C\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man_and_woman_holding_hands", "\u1f46B", NULL, {NULL} } +, { "man_climbing", "\u1f9d7\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man_dancing", "\u1f57A", NULL, {NULL} } +, { "man_in_business_suit_levitating", "\u1f574\ufe0f", NULL, {NULL} } +, { "man_in_lotus_position", "\u1f9d8\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man_in_steamy_room", "\u1f9d6\u200d\u2642\ufe0f", NULL, {NULL} } +, { "man_in_tuxedo", "\u1f935", NULL, {NULL} } +, { "man_with_gua_pi_mao", "\u1f472", NULL, {NULL} } +, { "man_with_turban", "\u1f473", NULL, {NULL} } +, { "mans_shoe", "\u1f45E", NULL, {NULL} } +, { "mantelpiece_clock", "\u1f570\ufe0f", NULL, {NULL} } +, { "maple_leaf", "\u1f341", NULL, {NULL} } +, { "martial_arts_uniform", "\u1f94B", NULL, {NULL} } +, { "mask", "\u1f637", NULL, {NULL} } +, { "massage", "\u1f486", NULL, {NULL} } +, { "meat_on_bone", "\u1f356", NULL, {NULL} } +, { "medal", "\u1f396\ufe0f", NULL, {NULL} } +, { "medical_symbol", "\u2695\ufe0f", NULL, {NULL} } +, { "mega", "\u1f4e3", NULL, {NULL} } +, { "melon", "\u1f348", NULL, {NULL} } +, { "memo", "\u1f4dD", NULL, {NULL} } +, { "menorah_with_nine_branches", "\u1f54E", NULL, {NULL} } +, { "mens", "\u1f6b9", NULL, {NULL} } +, { "mermaid", "\u1f9dC\u200d\u2640\ufe0f", NULL, {NULL} } +, { "merman", "\u1f9dC\u200d\u2642\ufe0f", NULL, {NULL} } +, { "merperson", "\u1f9dC", NULL, {NULL} } +, { "metro", "\u1f687", NULL, {NULL} } +, { "microphone", "\u1f3a4", NULL, {NULL} } +, { "microscope", "\u1f52C", NULL, {NULL} } +, { "middle_finger", "\u1f595", NULL, {NULL} } +, { "milky_way", "\u1f30C", NULL, {NULL} } +, { "minibus", "\u1f690", NULL, {NULL} } +, { "minidisc", "\u1f4bD", NULL, {NULL} } +, { "mobile_phone_off", "\u1f4f4", NULL, {NULL} } +, { "money_mouth_face", "\u1f911", NULL, {NULL} } +, { "money_with_wings", "\u1f4b8", NULL, {NULL} } +, { "moneybag", "\u1f4b0", NULL, {NULL} } +, { "monkey", "\u1f412", NULL, {NULL} } +, { "monkey_face", "\u1f435", NULL, {":o)", NULL} } +, { "monorail", "\u1f69D", NULL, {NULL} } +, { "moon", "\u1f314", NULL, {NULL} } +, { "mortar_board", "\u1f393", NULL, {NULL} } +, { "mosque", "\u1f54C", NULL, {NULL} } +, { "mostly_sunny", "\u1f324\ufe0f", NULL, {NULL} } +, { "mother_christmas", "\u1f936", NULL, {NULL} } +, { "motor_boat", "\u1f6e5\ufe0f", NULL, {NULL} } +, { "motor_scooter", "\u1f6f5", NULL, {NULL} } +, { "motorway", "\u1f6e3\ufe0f", NULL, {NULL} } +, { "mount_fuji", "\u1f5fB", NULL, {NULL} } +, { "mountain", "\u26f0\ufe0f", NULL, {NULL} } +, { "mountain_bicyclist", "\u1f6b5", NULL, {NULL} } +, { "mountain_cableway", "\u1f6a0", NULL, {NULL} } +, { "mountain_railway", "\u1f69E", NULL, {NULL} } +, { "mouse", "\u1f42D", NULL, {NULL} } +, { "mouse2", "\u1f401", NULL, {NULL} } +, { "movie_camera", "\u1f3a5", NULL, {NULL} } +, { "moyai", "\u1f5fF", NULL, {NULL} } +, { "mrs_claus", "\u1f936", NULL, {NULL} } +, { "muscle", "\u1f4aA", NULL, {NULL} } +, { "mushroom", "\u1f344", NULL, {NULL} } +, { "musical_keyboard", "\u1f3b9", NULL, {NULL} } +, { "musical_note", "\u1f3b5", NULL, {NULL} } +, { "musical_score", "\u1f3bC", NULL, {NULL} } +, { "mute", "\u1f507", NULL, {NULL} } +, { "nail_care", "\u1f485", NULL, {NULL} } +, { "name_badge", "\u1f4dB", NULL, {NULL} } +, { "national_park", "\u1f3dE\ufe0f", NULL, {NULL} } +, { "nauseated_face", "\u1f922", NULL, {NULL} } +, { "necktie", "\u1f454", NULL, {NULL} } +, { "negative_squared_cross_mark", "\u274e", NULL, {NULL} } +, { "nerd_face", "\u1f913", NULL, {NULL} } +, { "neutral_face", "\u1f610", NULL, {":|", ":-|", NULL} } +, { "new", "\u1f195", NULL, {NULL} } +, { "new_moon", "\u1f311", NULL, {NULL} } +, { "new_moon_with_face", "\u1f31A", NULL, {NULL} } +, { "newspaper", "\u1f4f0", NULL, {NULL} } +, { "ng", "\u1f196", NULL, {NULL} } +, { "night_with_stars", "\u1f303", NULL, {NULL} } +, { "nine", "9\ufe0f\u20e3", NULL, {NULL} } +, { "no_bell", "\u1f515", NULL, {NULL} } +, { "no_bicycles", "\u1f6b3", NULL, {NULL} } +, { "no_entry", "\u26d4", NULL, {NULL} } +, { "no_entry_sign", "\u1f6aB", NULL, {NULL} } +, { "no_good", "\u1f645", NULL, {NULL} } +, { "no_mobile_phones", "\u1f4f5", NULL, {NULL} } +, { "no_mouth", "\u1f636", NULL, {NULL} } +, { "no_pedestrians", "\u1f6b7", NULL, {NULL} } +, { "no_smoking", "\u1f6aD", NULL, {NULL} } +, { "non-potable_water", "\u1f6b1", NULL, {NULL} } +, { "nose", "\u1f443", NULL, {NULL} } +, { "notebook", "\u1f4d3", NULL, {NULL} } +, { "notebook_with_decorative_cover", "\u1f4d4", NULL, {NULL} } +, { "notes", "\u1f3b6", NULL, {NULL} } +, { "nut_and_bolt", "\u1f529", NULL, {NULL} } +, { "o", "\u2b55", NULL, {NULL} } +, { "o2", "\u1f17E\ufe0f", NULL, {NULL} } +, { "ocean", "\u1f30A", NULL, {NULL} } +, { "octagonal_sign", "\u1f6d1", NULL, {NULL} } +, { "octopus", "\u1f419", NULL, {NULL} } +, { "oden", "\u1f362", NULL, {NULL} } +, { "office", "\u1f3e2", NULL, {NULL} } +, { "oil_drum", "\u1f6e2\ufe0f", NULL, {NULL} } +, { "ok", "\u1f197", NULL, {NULL} } +, { "ok_hand", "\u1f44C", NULL, {NULL} } +, { "ok_woman", "\u1f646", NULL, {NULL} } +, { "old_key", "\u1f5dD\ufe0f", NULL, {NULL} } +, { "older_adult", "\u1f9d3", NULL, {NULL} } +, { "older_man", "\u1f474", NULL, {NULL} } +, { "older_woman", "\u1f475", NULL, {NULL} } +, { "om_symbol", "\u1f549\ufe0f", NULL, {NULL} } +, { "on", "\u1f51B", NULL, {NULL} } +, { "oncoming_automobile", "\u1f698", NULL, {NULL} } +, { "oncoming_bus", "\u1f68D", NULL, {NULL} } +, { "oncoming_police_car", "\u1f694", NULL, {NULL} } +, { "oncoming_taxi", "\u1f696", NULL, {NULL} } +, { "one", "1\ufe0f\u20e3", NULL, {NULL} } +, { "open_book", "\u1f4d6", NULL, {NULL} } +, { "open_file_folder", "\u1f4c2", NULL, {NULL} } +, { "open_hands", "\u1f450", NULL, {NULL} } +, { "open_mouth", "\u1f62E", NULL, {":o", ":-o", ":O", ":-O", NULL} } +, { "ophiuchus", "\u26ce", NULL, {NULL} } +, { "orange_book", "\u1f4d9", NULL, {NULL} } +, { "orange_heart", "\u1f9e1", NULL, {NULL} } +, { "orthodox_cross", "\u2626\ufe0f", NULL, {NULL} } +, { "outbox_tray", "\u1f4e4", NULL, {NULL} } +, { "owl", "\u1f989", NULL, {NULL} } +, { "ox", "\u1f402", NULL, {NULL} } +, { "package", "\u1f4e6", NULL, {NULL} } +, { "page_facing_up", "\u1f4c4", NULL, {NULL} } +, { "page_with_curl", "\u1f4c3", NULL, {NULL} } +, { "pager", "\u1f4dF", NULL, {NULL} } +, { "palm_tree", "\u1f334", NULL, {NULL} } +, { "palms_up_together", "\u1f932", NULL, {NULL} } +, { "pancakes", "\u1f95E", NULL, {NULL} } +, { "panda_face", "\u1f43C", NULL, {NULL} } +, { "paperclip", "\u1f4cE", NULL, {NULL} } +, { "parking", "\u1f17F\ufe0f", NULL, {NULL} } +, { "part_alternation_mark", "\u303d\ufe0f", NULL, {NULL} } +, { "partly_sunny", "\u26c5", NULL, {NULL} } +, { "partly_sunny_rain", "\u1f326\ufe0f", NULL, {NULL} } +, { "passenger_ship", "\u1f6f3\ufe0f", NULL, {NULL} } +, { "passport_control", "\u1f6c2", NULL, {NULL} } +, { "paw_prints", "\u1f43E", NULL, {NULL} } +, { "peace_symbol", "\u262e\ufe0f", NULL, {NULL} } +, { "peach", "\u1f351", NULL, {NULL} } +, { "peanuts", "\u1f95C", NULL, {NULL} } +, { "pear", "\u1f350", NULL, {NULL} } +, { "pencil", "\u1f4dD", NULL, {NULL} } +, { "pencil2", "\u270f\ufe0f", NULL, {NULL} } +, { "penguin", "\u1f427", NULL, {NULL} } +, { "pensive", "\u1f614", NULL, {NULL} } +, { "performing_arts", "\u1f3aD", NULL, {NULL} } +, { "persevere", "\u1f623", NULL, {NULL} } +, { "person_climbing", "\u1f9d7", NULL, {NULL} } +, { "person_doing_cartwheel", "\u1f938", NULL, {NULL} } +, { "person_frowning", "\u1f64D", NULL, {NULL} } +, { "person_in_lotus_position", "\u1f9d8", NULL, {NULL} } +, { "person_in_steamy_room", "\u1f9d6", NULL, {NULL} } +, { "person_with_ball", "\u26f9\ufe0f", NULL, {NULL} } +, { "person_with_blond_hair", "\u1f471", NULL, {NULL} } +, { "person_with_headscarf", "\u1f9d5", NULL, {NULL} } +, { "person_with_pouting_face", "\u1f64E", NULL, {NULL} } +, { "phone", "\u260e\ufe0f", NULL, {NULL} } +, { "pick", "\u26cf\ufe0f", NULL, {NULL} } +, { "pie", "\u1f967", NULL, {NULL} } +, { "pig", "\u1f437", NULL, {NULL} } +, { "pig2", "\u1f416", NULL, {NULL} } +, { "pig_nose", "\u1f43D", NULL, {NULL} } +, { "pill", "\u1f48A", NULL, {NULL} } +, { "pineapple", "\u1f34D", NULL, {NULL} } +, { "pisces", "\u2653", NULL, {NULL} } +, { "pizza", "\u1f355", NULL, {NULL} } +, { "place_of_worship", "\u1f6d0", NULL, {NULL} } +, { "point_down", "\u1f447", NULL, {NULL} } +, { "point_left", "\u1f448", NULL, {NULL} } +, { "point_right", "\u1f449", NULL, {NULL} } +, { "point_up", "\u261d\ufe0f", NULL, {NULL} } +, { "point_up_2", "\u1f446", NULL, {NULL} } +, { "police_car", "\u1f693", NULL, {NULL} } +, { "poodle", "\u1f429", NULL, {NULL} } +, { "poop", "\u1f4a9", NULL, {NULL} } +, { "popcorn", "\u1f37F", NULL, {NULL} } +, { "post_office", "\u1f3e3", NULL, {NULL} } +, { "postal_horn", "\u1f4eF", NULL, {NULL} } +, { "postbox", "\u1f4eE", NULL, {NULL} } +, { "potable_water", "\u1f6b0", NULL, {NULL} } +, { "potato", "\u1f954", NULL, {NULL} } +, { "pouch", "\u1f45D", NULL, {NULL} } +, { "poultry_leg", "\u1f357", NULL, {NULL} } +, { "pound", "\u1f4b7", NULL, {NULL} } +, { "pouting_cat", "\u1f63E", NULL, {NULL} } +, { "pray", "\u1f64F", NULL, {NULL} } +, { "prayer_beads", "\u1f4fF", NULL, {NULL} } +, { "pregnant_woman", "\u1f930", NULL, {NULL} } +, { "pretzel", "\u1f968", NULL, {NULL} } +, { "prince", "\u1f934", NULL, {NULL} } +, { "princess", "\u1f478", NULL, {NULL} } +, { "printer", "\u1f5a8\ufe0f", NULL, {NULL} } +, { "punch", "\u1f44A", NULL, {NULL} } +, { "purple_heart", "\u1f49C", "<3", {NULL} } +, { "purse", "\u1f45B", NULL, {NULL} } +, { "pushpin", "\u1f4cC", NULL, {NULL} } +, { "put_litter_in_its_place", "\u1f6aE", NULL, {NULL} } +, { "question", "\u2753", NULL, {NULL} } +, { "rabbit", "\u1f430", NULL, {NULL} } +, { "rabbit2", "\u1f407", NULL, {NULL} } +, { "racehorse", "\u1f40E", NULL, {NULL} } +, { "racing_car", "\u1f3cE\ufe0f", NULL, {NULL} } +, { "racing_motorcycle", "\u1f3cD\ufe0f", NULL, {NULL} } +, { "radio", "\u1f4fB", NULL, {NULL} } +, { "radio_button", "\u1f518", NULL, {NULL} } +, { "radioactive_sign", "\u2622\ufe0f", NULL, {NULL} } +, { "rage", "\u1f621", NULL, {NULL} } +, { "railway_car", "\u1f683", NULL, {NULL} } +, { "railway_track", "\u1f6e4\ufe0f", NULL, {NULL} } +, { "rain_cloud", "\u1f327\ufe0f", NULL, {NULL} } +, { "rainbow", "\u1f308", NULL, {NULL} } +, { "rainbow-flag", "\u1f3f3\ufe0f\u200d\u1f308", NULL, {NULL} } +, { "raised_back_of_hand", "\u1f91A", NULL, {NULL} } +, { "raised_hand", "\u270b", NULL, {NULL} } +, { "raised_hand_with_fingers_splayed", "\u1f590\ufe0f", NULL, {NULL} } +, { "raised_hands", "\u1f64C", NULL, {NULL} } +, { "raising_hand", "\u1f64B", NULL, {NULL} } +, { "ram", "\u1f40F", NULL, {NULL} } +, { "ramen", "\u1f35C", NULL, {NULL} } +, { "rat", "\u1f400", NULL, {NULL} } +, { "recycle", "\u267b\ufe0f", NULL, {NULL} } +, { "red_car", "\u1f697", NULL, {NULL} } +, { "red_circle", "\u1f534", NULL, {NULL} } +, { "registered", "\u00ae\ufe0f", NULL, {NULL} } +, { "relaxed", "\u263a\ufe0f", NULL, {NULL} } +, { "relieved", "\u1f60C", NULL, {NULL} } +, { "reminder_ribbon", "\u1f397\ufe0f", NULL, {NULL} } +, { "repeat", "\u1f501", NULL, {NULL} } +, { "repeat_one", "\u1f502", NULL, {NULL} } +, { "restroom", "\u1f6bB", NULL, {NULL} } +, { "reversed_hand_with_middle_finger_extended", "\u1f595", NULL, {NULL} } +, { "revolving_hearts", "\u1f49E", NULL, {NULL} } +, { "rewind", "\u23ea", NULL, {NULL} } +, { "rhinoceros", "\u1f98F", NULL, {NULL} } +, { "ribbon", "\u1f380", NULL, {NULL} } +, { "rice", "\u1f35A", NULL, {NULL} } +, { "rice_ball", "\u1f359", NULL, {NULL} } +, { "rice_cracker", "\u1f358", NULL, {NULL} } +, { "rice_scene", "\u1f391", NULL, {NULL} } +, { "right-facing_fist", "\u1f91C", NULL, {NULL} } +, { "right_anger_bubble", "\u1f5eF\ufe0f", NULL, {NULL} } +, { "ring", "\u1f48D", NULL, {NULL} } +, { "robot_face", "\u1f916", NULL, {NULL} } +, { "rocket", "\u1f680", NULL, {NULL} } +, { "rolled_up_newspaper", "\u1f5dE\ufe0f", NULL, {NULL} } +, { "roller_coaster", "\u1f3a2", NULL, {NULL} } +, { "rolling_on_the_floor_laughing", "\u1f923", NULL, {NULL} } +, { "rooster", "\u1f413", NULL, {NULL} } +, { "rose", "\u1f339", NULL, {NULL} } +, { "rosette", "\u1f3f5\ufe0f", NULL, {NULL} } +, { "rotating_light", "\u1f6a8", NULL, {NULL} } +, { "round_pushpin", "\u1f4cD", NULL, {NULL} } +, { "rowboat", "\u1f6a3", NULL, {NULL} } +, { "ru", "\u1f1f7\u1f1fA", NULL, {NULL} } +, { "rugby_football", "\u1f3c9", NULL, {NULL} } +, { "runner", "\u1f3c3", NULL, {NULL} } +, { "running", "\u1f3c3", NULL, {NULL} } +, { "running_shirt_with_sash", "\u1f3bD", NULL, {NULL} } +, { "sa", "\u1f202\ufe0f", NULL, {NULL} } +, { "sagittarius", "\u2650", NULL, {NULL} } +, { "sailboat", "\u26f5", NULL, {NULL} } +, { "sake", "\u1f376", NULL, {NULL} } +, { "sandal", "\u1f461", NULL, {NULL} } +, { "sandwich", "\u1f96A", NULL, {NULL} } +, { "santa", "\u1f385", NULL, {NULL} } +, { "satellite", "\u1f6f0\ufe0f", NULL, {NULL} } +, { "satellite_antenna", "\u1f4e1", NULL, {NULL} } +, { "satisfied", "\u1f606", NULL, {":>", ":->", NULL} } +, { "sauropod", "\u1f995", NULL, {NULL} } +, { "saxophone", "\u1f3b7", NULL, {NULL} } +, { "scales", "\u2696\ufe0f", NULL, {NULL} } +, { "scarf", "\u1f9e3", NULL, {NULL} } +, { "school", "\u1f3eB", NULL, {NULL} } +, { "school_satchel", "\u1f392", NULL, {NULL} } +, { "scissors", "\u2702\ufe0f", NULL, {NULL} } +, { "scooter", "\u1f6f4", NULL, {NULL} } +, { "scorpion", "\u1f982", NULL, {NULL} } +, { "scorpius", "\u264f", NULL, {NULL} } +, { "scream", "\u1f631", NULL, {NULL} } +, { "scream_cat", "\u1f640", NULL, {NULL} } +, { "scroll", "\u1f4dC", NULL, {NULL} } +, { "seat", "\u1f4bA", NULL, {NULL} } +, { "second_place_medal", "\u1f948", NULL, {NULL} } +, { "secret", "\u3299\ufe0f", NULL, {NULL} } +, { "see_no_evil", "\u1f648", NULL, {NULL} } +, { "seedling", "\u1f331", NULL, {NULL} } +, { "selfie", "\u1f933", NULL, {NULL} } +, { "serious_face_with_symbols_covering_mouth", "\u1f92C", NULL, {NULL} } +, { "seven", "7\ufe0f\u20e3", NULL, {NULL} } +, { "shallow_pan_of_food", "\u1f958", NULL, {NULL} } +, { "shamrock", "\u2618\ufe0f", NULL, {NULL} } +, { "shark", "\u1f988", NULL, {NULL} } +, { "shaved_ice", "\u1f367", NULL, {NULL} } +, { "sheep", "\u1f411", NULL, {NULL} } +, { "shell", "\u1f41A", NULL, {NULL} } +, { "shield", "\u1f6e1\ufe0f", NULL, {NULL} } +, { "shinto_shrine", "\u26e9\ufe0f", NULL, {NULL} } +, { "ship", "\u1f6a2", NULL, {NULL} } +, { "shirt", "\u1f455", NULL, {NULL} } +, { "shit", "\u1f4a9", NULL, {NULL} } +, { "shocked_face_with_exploding_head", "\u1f92F", NULL, {NULL} } +, { "shoe", "\u1f45E", NULL, {NULL} } +, { "shopping_bags", "\u1f6cD\ufe0f", NULL, {NULL} } +, { "shopping_trolley", "\u1f6d2", NULL, {NULL} } +, { "shower", "\u1f6bF", NULL, {NULL} } +, { "shrimp", "\u1f990", NULL, {NULL} } +, { "shrug", "\u1f937", NULL, {NULL} } +, { "shushing_face", "\u1f92B", NULL, {NULL} } +, { "sign_of_the_horns", "\u1f918", NULL, {NULL} } +, { "signal_strength", "\u1f4f6", NULL, {NULL} } +, { "six", "6\ufe0f\u20e3", NULL, {NULL} } +, { "six_pointed_star", "\u1f52F", NULL, {NULL} } +, { "ski", "\u1f3bF", NULL, {NULL} } +, { "skier", "\u26f7\ufe0f", NULL, {NULL} } +, { "skin-tone-2", "\u1f3fB", NULL, {NULL} } +, { "skin-tone-3", "\u1f3fC", NULL, {NULL} } +, { "skin-tone-4", "\u1f3fD", NULL, {NULL} } +, { "skin-tone-5", "\u1f3fE", NULL, {NULL} } +, { "skin-tone-6", "\u1f3fF", NULL, {NULL} } +, { "skull", "\u1f480", NULL, {NULL} } +, { "skull_and_crossbones", "\u2620\ufe0f", NULL, {NULL} } +, { "sled", "\u1f6f7", NULL, {NULL} } +, { "sleeping", "\u1f634", NULL, {NULL} } +, { "sleeping_accommodation", "\u1f6cC", NULL, {NULL} } +, { "sleepy", "\u1f62A", NULL, {NULL} } +, { "sleuth_or_spy", "\u1f575\ufe0f", NULL, {NULL} } +, { "slightly_frowning_face", "\u1f641", NULL, {NULL} } +, { "slightly_smiling_face", "\u1f642", NULL, {":)", "(:", ":-)", NULL} } +, { "slot_machine", "\u1f3b0", NULL, {NULL} } +, { "small_airplane", "\u1f6e9\ufe0f", NULL, {NULL} } +, { "small_blue_diamond", "\u1f539", NULL, {NULL} } +, { "small_orange_diamond", "\u1f538", NULL, {NULL} } +, { "small_red_triangle", "\u1f53A", NULL, {NULL} } +, { "small_red_triangle_down", "\u1f53B", NULL, {NULL} } +, { "smile", "\u1f604", ":)", {"C:", "c:", ":D", ":-D", NULL} } +, { "smile_cat", "\u1f638", NULL, {NULL} } +, { "smiley", "\u1f603", ":)", {"=)", "=-)", NULL} } +, { "smiley_cat", "\u1f63A", NULL, {NULL} } +, { "smiling_face_with_smiling_eyes_and_hand_covering_mouth", "\u1f92D", NULL, {NULL} } +, { "smiling_imp", "\u1f608", NULL, {NULL} } +, { "smirk", "\u1f60F", NULL, {NULL} } +, { "smirk_cat", "\u1f63C", NULL, {NULL} } +, { "smoking", "\u1f6aC", NULL, {NULL} } +, { "snail", "\u1f40C", NULL, {NULL} } +, { "snake", "\u1f40D", NULL, {NULL} } +, { "sneezing_face", "\u1f927", NULL, {NULL} } +, { "snow_capped_mountain", "\u1f3d4\ufe0f", NULL, {NULL} } +, { "snow_cloud", "\u1f328\ufe0f", NULL, {NULL} } +, { "snowboarder", "\u1f3c2", NULL, {NULL} } +, { "snowflake", "\u2744\ufe0f", NULL, {NULL} } +, { "snowman", "\u2603\ufe0f", NULL, {NULL} } +, { "snowman_without_snow", "\u26c4", NULL, {NULL} } +, { "sob", "\u1f62D", ":'(", {NULL} } +, { "soccer", "\u26bd", NULL, {NULL} } +, { "socks", "\u1f9e6", NULL, {NULL} } +, { "soon", "\u1f51C", NULL, {NULL} } +, { "sos", "\u1f198", NULL, {NULL} } +, { "sound", "\u1f509", NULL, {NULL} } +, { "space_invader", "\u1f47E", NULL, {NULL} } +, { "spades", "\u2660\ufe0f", NULL, {NULL} } +, { "spaghetti", "\u1f35D", NULL, {NULL} } +, { "sparkle", "\u2747\ufe0f", NULL, {NULL} } +, { "sparkler", "\u1f387", NULL, {NULL} } +, { "sparkles", "\u2728", NULL, {NULL} } +, { "sparkling_heart", "\u1f496", NULL, {NULL} } +, { "speak_no_evil", "\u1f64A", NULL, {NULL} } +, { "speaker", "\u1f508", NULL, {NULL} } +, { "speaking_head_in_silhouette", "\u1f5e3\ufe0f", NULL, {NULL} } +, { "speech_balloon", "\u1f4aC", NULL, {NULL} } +, { "speedboat", "\u1f6a4", NULL, {NULL} } +, { "spider", "\u1f577\ufe0f", NULL, {NULL} } +, { "spider_web", "\u1f578\ufe0f", NULL, {NULL} } +, { "spiral_calendar_pad", "\u1f5d3\ufe0f", NULL, {NULL} } +, { "spiral_note_pad", "\u1f5d2\ufe0f", NULL, {NULL} } +, { "spock-hand", "\u1f596", NULL, {NULL} } +, { "spoon", "\u1f944", NULL, {NULL} } +, { "sports_medal", "\u1f3c5", NULL, {NULL} } +, { "squid", "\u1f991", NULL, {NULL} } +, { "stadium", "\u1f3dF\ufe0f", NULL, {NULL} } +, { "staff_of_aesculapius", "\u2695\ufe0f", NULL, {NULL} } +, { "star", "\u2b50", NULL, {NULL} } +, { "star-struck", "\u1f929", NULL, {NULL} } +, { "star2", "\u1f31F", NULL, {NULL} } +, { "star_and_crescent", "\u262a\ufe0f", NULL, {NULL} } +, { "star_of_david", "\u2721\ufe0f", NULL, {NULL} } +, { "stars", "\u1f320", NULL, {NULL} } +, { "station", "\u1f689", NULL, {NULL} } +, { "statue_of_liberty", "\u1f5fD", NULL, {NULL} } +, { "steam_locomotive", "\u1f682", NULL, {NULL} } +, { "stew", "\u1f372", NULL, {NULL} } +, { "stopwatch", "\u23f1\ufe0f", NULL, {NULL} } +, { "straight_ruler", "\u1f4cF", NULL, {NULL} } +, { "strawberry", "\u1f353", NULL, {NULL} } +, { "stuck_out_tongue", "\u1f61B", ":p", {":p", ":-p", ":P", ":-P", ":b", ":-b", NULL} } +, { "stuck_out_tongue_closed_eyes", "\u1f61D", NULL, {NULL} } +, { "stuck_out_tongue_winking_eye", "\u1f61C", ";p", {";p", ";-p", ";b", ";-b", ";P", ";-P", NULL} } +, { "studio_microphone", "\u1f399\ufe0f", NULL, {NULL} } +, { "stuffed_flatbread", "\u1f959", NULL, {NULL} } +, { "sun_behind_cloud", "\u1f325\ufe0f", NULL, {NULL} } +, { "sun_behind_rain_cloud", "\u1f326\ufe0f", NULL, {NULL} } +, { "sun_small_cloud", "\u1f324\ufe0f", NULL, {NULL} } +, { "sun_with_face", "\u1f31E", NULL, {NULL} } +, { "sunflower", "\u1f33B", NULL, {NULL} } +, { "sunglasses", "\u1f60E", NULL, {"8)", NULL} } +, { "sunny", "\u2600\ufe0f", NULL, {NULL} } +, { "sunrise", "\u1f305", NULL, {NULL} } +, { "sunrise_over_mountains", "\u1f304", NULL, {NULL} } +, { "surfer", "\u1f3c4", NULL, {NULL} } +, { "sushi", "\u1f363", NULL, {NULL} } +, { "suspension_railway", "\u1f69F", NULL, {NULL} } +, { "sweat", "\u1f613", NULL, {NULL} } +, { "sweat_drops", "\u1f4a6", NULL, {NULL} } +, { "sweat_smile", "\u1f605", NULL, {NULL} } +, { "sweet_potato", "\u1f360", NULL, {NULL} } +, { "swimmer", "\u1f3cA", NULL, {NULL} } +, { "symbols", "\u1f523", NULL, {NULL} } +, { "synagogue", "\u1f54D", NULL, {NULL} } +, { "syringe", "\u1f489", NULL, {NULL} } +, { "t-rex", "\u1f996", NULL, {NULL} } +, { "table_tennis_paddle_and_ball", "\u1f3d3", NULL, {NULL} } +, { "taco", "\u1f32E", NULL, {NULL} } +, { "tada", "\u1f389", NULL, {NULL} } +, { "takeout_box", "\u1f961", NULL, {NULL} } +, { "tanabata_tree", "\u1f38B", NULL, {NULL} } +, { "tangerine", "\u1f34A", NULL, {NULL} } +, { "taurus", "\u2649", NULL, {NULL} } +, { "taxi", "\u1f695", NULL, {NULL} } +, { "tea", "\u1f375", NULL, {NULL} } +, { "telephone", "\u260e\ufe0f", NULL, {NULL} } +, { "telephone_receiver", "\u1f4dE", NULL, {NULL} } +, { "telescope", "\u1f52D", NULL, {NULL} } +, { "tennis", "\u1f3bE", NULL, {NULL} } +, { "tent", "\u26fa", NULL, {NULL} } +, { "the_horns", "\u1f918", NULL, {NULL} } +, { "thermometer", "\u1f321\ufe0f", NULL, {NULL} } +, { "thinking_face", "\u1f914", NULL, {NULL} } +, { "third_place_medal", "\u1f949", NULL, {NULL} } +, { "thought_balloon", "\u1f4aD", NULL, {NULL} } +, { "three", "3\ufe0f\u20e3", NULL, {NULL} } +, { "three_button_mouse", "\u1f5b1\ufe0f", NULL, {NULL} } +, { "thumbsdown", "\u1f44E", NULL, {NULL} } +, { "thumbsup", "\u1f44D", NULL, {NULL} } +, { "thunder_cloud_and_rain", "\u26c8\ufe0f", NULL, {NULL} } +, { "ticket", "\u1f3aB", NULL, {NULL} } +, { "tiger", "\u1f42F", NULL, {NULL} } +, { "tiger2", "\u1f405", NULL, {NULL} } +, { "timer_clock", "\u23f2\ufe0f", NULL, {NULL} } +, { "tired_face", "\u1f62B", NULL, {NULL} } +, { "tm", "\u2122\ufe0f", NULL, {NULL} } +, { "toilet", "\u1f6bD", NULL, {NULL} } +, { "tokyo_tower", "\u1f5fC", NULL, {NULL} } +, { "tomato", "\u1f345", NULL, {NULL} } +, { "tongue", "\u1f445", NULL, {NULL} } +, { "top", "\u1f51D", NULL, {NULL} } +, { "tophat", "\u1f3a9", NULL, {NULL} } +, { "tornado", "\u1f32A\ufe0f", NULL, {NULL} } +, { "tornado_cloud", "\u1f32A\ufe0f", NULL, {NULL} } +, { "trackball", "\u1f5b2\ufe0f", NULL, {NULL} } +, { "tractor", "\u1f69C", NULL, {NULL} } +, { "traffic_light", "\u1f6a5", NULL, {NULL} } +, { "train", "\u1f68B", NULL, {NULL} } +, { "train2", "\u1f686", NULL, {NULL} } +, { "tram", "\u1f68A", NULL, {NULL} } +, { "triangular_flag_on_post", "\u1f6a9", NULL, {NULL} } +, { "triangular_ruler", "\u1f4d0", NULL, {NULL} } +, { "trident", "\u1f531", NULL, {NULL} } +, { "triumph", "\u1f624", NULL, {NULL} } +, { "trolleybus", "\u1f68E", NULL, {NULL} } +, { "trophy", "\u1f3c6", NULL, {NULL} } +, { "tropical_drink", "\u1f379", NULL, {NULL} } +, { "tropical_fish", "\u1f420", NULL, {NULL} } +, { "truck", "\u1f69A", NULL, {NULL} } +, { "trumpet", "\u1f3bA", NULL, {NULL} } +, { "tshirt", "\u1f455", NULL, {NULL} } +, { "tulip", "\u1f337", NULL, {NULL} } +, { "tumbler_glass", "\u1f943", NULL, {NULL} } +, { "turkey", "\u1f983", NULL, {NULL} } +, { "turtle", "\u1f422", NULL, {NULL} } +, { "tv", "\u1f4fA", NULL, {NULL} } +, { "twisted_rightwards_arrows", "\u1f500", NULL, {NULL} } +, { "two", "2\ufe0f\u20e3", NULL, {NULL} } +, { "two_hearts", "\u1f495", NULL, {NULL} } +, { "two_men_holding_hands", "\u1f46C", NULL, {NULL} } +, { "two_women_holding_hands", "\u1f46D", NULL, {NULL} } +, { "u5272", "\u1f239", NULL, {NULL} } +, { "u5408", "\u1f234", NULL, {NULL} } +, { "u55b6", "\u1f23A", NULL, {NULL} } +, { "u6307", "\u1f22F", NULL, {NULL} } +, { "u6708", "\u1f237\ufe0f", NULL, {NULL} } +, { "u6709", "\u1f236", NULL, {NULL} } +, { "u6e80", "\u1f235", NULL, {NULL} } +, { "u7121", "\u1f21A", NULL, {NULL} } +, { "u7533", "\u1f238", NULL, {NULL} } +, { "u7981", "\u1f232", NULL, {NULL} } +, { "u7a7a", "\u1f233", NULL, {NULL} } +, { "uk", "\u1f1eC\u1f1e7", NULL, {NULL} } +, { "umbrella", "\u2602\ufe0f", NULL, {NULL} } +, { "umbrella_on_ground", "\u26f1\ufe0f", NULL, {NULL} } +, { "umbrella_with_rain_drops", "\u2614", NULL, {NULL} } +, { "unamused", "\u1f612", ":(", {NULL} } +, { "underage", "\u1f51E", NULL, {NULL} } +, { "unicorn_face", "\u1f984", NULL, {NULL} } +, { "unlock", "\u1f513", NULL, {NULL} } +, { "up", "\u1f199", NULL, {NULL} } +, { "upside_down_face", "\u1f643", NULL, {NULL} } +, { "us", "\u1f1fA\u1f1f8", NULL, {NULL} } +, { "v", "\u270c\ufe0f", NULL, {NULL} } +, { "vampire", "\u1f9dB", NULL, {NULL} } +, { "vertical_traffic_light", "\u1f6a6", NULL, {NULL} } +, { "vhs", "\u1f4fC", NULL, {NULL} } +, { "vibration_mode", "\u1f4f3", NULL, {NULL} } +, { "video_camera", "\u1f4f9", NULL, {NULL} } +, { "video_game", "\u1f3aE", NULL, {NULL} } +, { "violin", "\u1f3bB", NULL, {NULL} } +, { "virgo", "\u264d", NULL, {NULL} } +, { "volcano", "\u1f30B", NULL, {NULL} } +, { "volleyball", "\u1f3d0", NULL, {NULL} } +, { "vs", "\u1f19A", NULL, {NULL} } +, { "walking", "\u1f6b6", NULL, {NULL} } +, { "waning_crescent_moon", "\u1f318", NULL, {NULL} } +, { "waning_gibbous_moon", "\u1f316", NULL, {NULL} } +, { "warning", "\u26a0\ufe0f", NULL, {NULL} } +, { "wastebasket", "\u1f5d1\ufe0f", NULL, {NULL} } +, { "watch", "\u231a", NULL, {NULL} } +, { "water_buffalo", "\u1f403", NULL, {NULL} } +, { "water_polo", "\u1f93D", NULL, {NULL} } +, { "watermelon", "\u1f349", NULL, {NULL} } +, { "wave", "\u1f44B", NULL, {NULL} } +, { "waving_black_flag", "\u1f3f4", NULL, {NULL} } +, { "waving_white_flag", "\u1f3f3\ufe0f", NULL, {NULL} } +, { "wavy_dash", "\u3030\ufe0f", NULL, {NULL} } +, { "waxing_crescent_moon", "\u1f312", NULL, {NULL} } +, { "waxing_gibbous_moon", "\u1f314", NULL, {NULL} } +, { "wc", "\u1f6bE", NULL, {NULL} } +, { "weary", "\u1f629", NULL, {NULL} } +, { "wedding", "\u1f492", NULL, {NULL} } +, { "weight_lifter", "\u1f3cB\ufe0f", NULL, {NULL} } +, { "whale", "\u1f433", NULL, {NULL} } +, { "whale2", "\u1f40B", NULL, {NULL} } +, { "wheel_of_dharma", "\u2638\ufe0f", NULL, {NULL} } +, { "wheelchair", "\u267f", NULL, {NULL} } +, { "white_check_mark", "\u2705", NULL, {NULL} } +, { "white_circle", "\u26aa", NULL, {NULL} } +, { "white_flower", "\u1f4aE", NULL, {NULL} } +, { "white_frowning_face", "\u2639\ufe0f", NULL, {NULL} } +, { "white_large_square", "\u2b1c", NULL, {NULL} } +, { "white_medium_small_square", "\u25fd", NULL, {NULL} } +, { "white_medium_square", "\u25fb\ufe0f", NULL, {NULL} } +, { "white_small_square", "\u25ab\ufe0f", NULL, {NULL} } +, { "white_square_button", "\u1f533", NULL, {NULL} } +, { "wilted_flower", "\u1f940", NULL, {NULL} } +, { "wind_blowing_face", "\u1f32C\ufe0f", NULL, {NULL} } +, { "wind_chime", "\u1f390", NULL, {NULL} } +, { "wine_glass", "\u1f377", NULL, {NULL} } +, { "wink", "\u1f609", ";)", {";)", ";-)", NULL} } +, { "wolf", "\u1f43A", NULL, {NULL} } +, { "woman", "\u1f469", NULL, {NULL} } +, { "woman-biking", "\u1f6b4\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-bouncing-ball", "\u26f9\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-bowing", "\u1f647\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-boy", "\u1f469\u200d\u1f466", NULL, {NULL} } +, { "woman-boy-boy", "\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { "woman-cartwheeling", "\u1f938\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-facepalming", "\u1f926\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-frowning", "\u1f64D\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-gesturing-no", "\u1f645\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-gesturing-ok", "\u1f646\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-getting-haircut", "\u1f487\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-getting-massage", "\u1f486\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-girl", "\u1f469\u200d\u1f467", NULL, {NULL} } +, { "woman-girl-boy", "\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { "woman-girl-girl", "\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { "woman-golfing", "\u1f3cC\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-heart-man", "\u1f469\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } +, { "woman-heart-woman", "\u1f469\u200d\u2764\ufe0f\u200d\u1f469", NULL, {NULL} } +, { "woman-juggling", "\u1f939\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-kiss-man", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } +, { "woman-kiss-woman", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f469", NULL, {NULL} } +, { "woman-lifting-weights", "\u1f3cB\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-mountain-biking", "\u1f6b5\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-playing-handball", "\u1f93E\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-playing-water-polo", "\u1f93D\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-pouting", "\u1f64E\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-raising-hand", "\u1f64B\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-rowing-boat", "\u1f6a3\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-running", "\u1f3c3\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-shrugging", "\u1f937\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-surfing", "\u1f3c4\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-swimming", "\u1f3cA\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-tipping-hand", "\u1f481\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-walking", "\u1f6b6\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-wearing-turban", "\u1f473\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-with-bunny-ears-partying", "\u1f46F\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman-woman-boy", "\u1f469\u200d\u1f469\u200d\u1f466", NULL, {NULL} } +, { "woman-woman-boy-boy", "\u1f469\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { "woman-woman-girl", "\u1f469\u200d\u1f469\u200d\u1f467", NULL, {NULL} } +, { "woman-woman-girl-boy", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { "woman-woman-girl-girl", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { "woman-wrestling", "\u1f93C\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman_climbing", "\u1f9d7\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman_in_lotus_position", "\u1f9d8\u200d\u2640\ufe0f", NULL, {NULL} } +, { "woman_in_steamy_room", "\u1f9d6\u200d\u2640\ufe0f", NULL, {NULL} } +, { "womans_clothes", "\u1f45A", NULL, {NULL} } +, { "womans_hat", "\u1f452", NULL, {NULL} } +, { "womens", "\u1f6bA", NULL, {NULL} } +, { "world_map", "\u1f5fA\ufe0f", NULL, {NULL} } +, { "worried", "\u1f61F", NULL, {NULL} } +, { "wrench", "\u1f527", NULL, {NULL} } +, { "wrestlers", "\u1f93C", NULL, {NULL} } +, { "writing_hand", "\u270d\ufe0f", NULL, {NULL} } +, { "x", "\u274c", NULL, {NULL} } +, { "yellow_heart", "\u1f49B", "<3", {NULL} } +, { "yen", "\u1f4b4", NULL, {NULL} } +, { "yin_yang", "\u262f\ufe0f", NULL, {NULL} } +, { "yum", "\u1f60B", NULL, {NULL} } +, { "zany_face", "\u1f92A", NULL, {NULL} } +, { "zap", "\u26a1", NULL, {NULL} } +, { "zebra_face", "\u1f993", NULL, {NULL} } +, { "zero", "0\ufe0f\u20e3", NULL, {NULL} } +, { "zipper_mouth_face", "\u1f910", NULL, {NULL} } +, { "zombie", "\u1f9dF", NULL, {NULL} } +, { "zzz", "\u1f4a4", NULL, {NULL} } +}; + +static struct t_slack_emoji_by_text slack_emoji_by_text[] = +{ { "(:", "\u1f642", "slightly_smiling_face", {"slightly_smiling_face", NULL} } +, { "):", "\u1f61E", "disappointed", {"disappointed", NULL} } +, { "8)", "\u1f60E", "sunglasses", {"sunglasses", NULL} } +, { ":'(", "\u1f622", "cry", {"cry", NULL} } +, { ":(", "\u1f61E", "disappointed", {"disappointed", NULL} } +, { ":)", "\u1f642", "slightly_smiling_face", {"slightly_smiling_face", NULL} } +, { ":*", "\u1f618", "kissing_heart", {"kissing_heart", NULL} } +, { ":-(", "\u1f61E", "disappointed", {"disappointed", NULL} } +, { ":-)", "\u1f642", "slightly_smiling_face", {"slightly_smiling_face", NULL} } +, { ":-*", "\u1f618", "kissing_heart", {"kissing_heart", NULL} } +, { ":-/", "\u1f615", "confused", {"confused", NULL} } +, { ":->", "\u1f606", "laughing", {"laughing", "satisfied", NULL} } +, { ":-D", "\u1f604", "smile", {"smile", NULL} } +, { ":-O", "\u1f62E", "open_mouth", {"open_mouth", NULL} } +, { ":-P", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } +, { ":-\\", "\u1f615", "confused", {"confused", NULL} } +, { ":-b", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } +, { ":-o", "\u1f62E", "open_mouth", {"open_mouth", NULL} } +, { ":-p", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } +, { ":-|", "\u1f610", "neutral_face", {"neutral_face", NULL} } +, { ":/", "\u1f615", "confused", {"confused", NULL} } +, { ":>", "\u1f606", "laughing", {"laughing", "satisfied", NULL} } +, { ":D", "\u1f604", "smile", {"smile", NULL} } +, { ":O", "\u1f62E", "open_mouth", {"open_mouth", NULL} } +, { ":P", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } +, { ":\\", "\u1f615", "confused", {"confused", NULL} } +, { ":b", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } +, { ":o", "\u1f62E", "open_mouth", {"open_mouth", NULL} } +, { ":o)", "\u1f435", "monkey_face", {"monkey_face", NULL} } +, { ":p", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } +, { ":|", "\u1f610", "neutral_face", {"neutral_face", NULL} } +, { ";)", "\u1f609", "wink", {"wink", NULL} } +, { ";-)", "\u1f609", "wink", {"wink", NULL} } +, { ";-P", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } +, { ";-b", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } +, { ";-p", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } +, { ";P", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } +, { ";b", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } +, { ";p", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } +, { ":(", "\u1f620", "angry", {"angry", NULL} } +, { ">:-(", "\u1f620", "angry", {"angry", NULL} } +, { "C:", "\u1f604", "smile", {"smile", NULL} } +, { "D:", "\u1f627", "anguished", {"anguished", NULL} } +, { "c:", "\u1f604", "smile", {"smile", NULL} } +}; diff --git a/slack-emoji.py b/slack-emoji.py new file mode 100755 index 0000000..f6fcbd9 --- /dev/null +++ b/slack-emoji.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import requests +import json +import ast + +emoji = requests.get("https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json").json() + +print(""" +#include + +#define MAX_TEXTS %d +#define MAX_NAMES %d + +struct t_slack_emoji_by_name { + const char *name; + const char *unicode; + const char *text_to; + const char *text_from[MAX_TEXTS]; +}; + +struct t_slack_emoji_by_text { + const char *text; + const char *unicode; + const char *name_to; + const char *name_from[MAX_NAMES]; +}; +"""%(max(len(o['texts'] if o['texts'] else []) for o in emoji) + 1, + max(len(o['short_names'] if o['short_names'] else []) for o in emoji) + 1)) +print("static struct t_slack_emoji_by_name slack_emoji_by_name[] =") +print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format( + json.dumps(name), + json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s), + json.dumps(o['text']), + "{"+json.dumps(o['texts']+[None] if o['texts'] else [None])[1:-1]+"}") + for o,name in sorted(((o,name) for o in emoji for name in o['short_names']), + key=lambda x: x[1]) +).replace("null", "NULL")[1:]) +print("};") +print("") +print("static struct t_slack_emoji_by_text slack_emoji_by_text[] =") +print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format( + json.dumps(text), + json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s), + json.dumps(o['short_name']), + "{"+json.dumps(o['short_names']+[None] if o['short_names'] else [None])[1:-1]+"}") + for o,text in sorted(((o,text) for o in emoji if o['texts'] for text in o['texts']), + key=lambda x:x[1]) +).replace("null", "NULL")[1:]) +print("};") From c1e7e096d0e9d7f1c556a7e72692255fd2afd759 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 11 May 2018 22:04:06 +0100 Subject: [PATCH 046/118] Add perl emoji generation as option instead of python --- Makefile | 9 +++++- debian/control | 3 +- slack-emoji.pl | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ slack-emoji.py | 3 +- 4 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 slack-emoji.pl diff --git a/Makefile b/Makefile index 621ad4a..9480a0f 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ endif RM=rm -f CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) -LDLIBS=-Wl,--push-state,--as-needed -lgnutls +LDLIBS=-lgnutls PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -47,8 +47,15 @@ all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack weechat-slack: $(OBJS) $(CXX) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) +ifeq ($(shell which python),) +slack-emoji.inc: slack-emoji.pl + cpan LWP::Simple + cpan JSON + perl slack-emoji.pl > slack-emoji.inc +else slack-emoji.inc: slack-emoji.py env python3 slack-emoji.py > slack-emoji.inc +endif libwebsockets/lib/libwebsockets.a: cd libwebsockets && env CFLAGS= LDFLAGS= cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . diff --git a/debian/control b/debian/control index 5d845d0..71cf7cc 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,8 @@ Build-Depends: cmake, pkg-config, debhelper (>= 11), libssl-dev, - libgnutls28-dev + libgnutls28-dev, + perl Standards-Version: 4.0.0 Homepage: https://weechat.org/ Vcs-Git: https://github.com/bqv/weechat-slack.git diff --git a/slack-emoji.pl b/slack-emoji.pl new file mode 100644 index 0000000..4d500fb --- /dev/null +++ b/slack-emoji.pl @@ -0,0 +1,80 @@ +#!/usr/bin/perl -l + +use strict; +use warnings; + +use LWP::Simple; +use Data::Dumper; +use JSON qw (decode_json); +use List::Util qw (max); + +our ($json, @array); + +$json = get('https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json'); +@array = @{ decode_json($json) }; + +my $maxtexts = max (map { 1 + @{$_} } (grep defined, map { $_->{'texts'} } @array)); +my $maxnames = max (map { 1 + @{$_} } (grep defined, map { $_->{'short_names'} } @array)); + +print " +#include + +#define MAX_TEXTS $maxtexts +#define MAX_NAMES $maxnames + +struct t_slack_emoji_by_name { + const char *name; + const char *unicode; + const char *text_to; + const char *text_from[MAX_TEXTS]; +}; + +struct t_slack_emoji_by_text { + const char *text; + const char *unicode; + const char *name_to; + const char *name_from[MAX_NAMES]; +}; +"; + +print "static struct t_slack_emoji_by_name slack_emoji_by_name[] ="; +my $c = '{'; +my %byname = map { my $o = $_; map {($_, $o)} @{$o->{'short_names'}} } @array; +my @sortedbyname = sort { $a cmp $b } keys %byname; +foreach my $name (@sortedbyname) +{ + my $_0 = "\"$name\""; + my @_1 = split /-/, $byname{$name}->{'unified'}; + my $_1 = "\""; + foreach my $codepoint (@_1) { $_1 .= "\\u$codepoint" }; + $_1 .= "\""; + my $_2 = $byname{$name}->{'text'}; + if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" }; + my $_3 = "{"; + foreach my $text (@{$byname{$name}->{'texts'}}) { if (defined $text) { $_3 .= "\"$text\", " } }; + $_3 .= "NULL}"; + print "$c { $_0, $_1, $_2, $_3 }"; + $c = ','; +} +print "};"; +print ""; +print "static struct t_slack_emoji_by_text slack_emoji_by_text[] ="; +$c = '{'; +my %bytext = map { my $o = $_; map {($_, $o)} @{$o->{'texts'}} } @array; +my @sortedbytext = sort { $a cmp $b } keys %bytext; +foreach my $text (@sortedbytext) +{ + my $_0 = "\"$text\""; + my @_1 = split /-/, $bytext{$text}->{'unified'}; + my $_1 = "\""; + foreach my $codepoint (@_1) { $_1 .= "\\u$codepoint" }; + $_1 .= "\""; + my $_2 = $bytext{$text}->{'short_name'}; + if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" }; + my $_3 = "{"; + foreach my $name (@{$bytext{$text}->{'short_names'}}) { if (defined $name) { $_3 .= "\"$name\", " } }; + $_3 .= "NULL}"; + print "$c { $_0, $_1, $_2, $_3 }"; + $c = ','; +} +print "};"; diff --git a/slack-emoji.py b/slack-emoji.py index f6fcbd9..36e3eef 100755 --- a/slack-emoji.py +++ b/slack-emoji.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +#!/usr/bin/python +# Compatible with python v2 and v3 import requests import json From 48257b7cc105be24118ae24b7860f2dc7a33217f Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 11 May 2018 22:41:15 +0100 Subject: [PATCH 047/118] Implement emoji exact search functions --- .gitattributes | 1 + slack-emoji.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ slack-emoji.h | 6 ++++ slack-emoji.inc | 4 +++ slack-emoji.pl | 8 ++++++ slack-emoji.py | 8 ++++++ 6 files changed, 102 insertions(+) diff --git a/.gitattributes b/.gitattributes index 51f39db..11bf075 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ # Github language display *.h linguist-language=C +*.inc linguist-language=C diff --git a/slack-emoji.c b/slack-emoji.c index 21983cf..1c7e6ba 100644 --- a/slack-emoji.c +++ b/slack-emoji.c @@ -10,3 +10,78 @@ #include "slack-emoji.inc" +static int emoji_byname_cmp(const void *p1, const void *p2) +{ + return strcasecmp(((struct t_slack_emoji_by_name *)p1)->name, + ((struct t_slack_emoji_by_name *)p2)->name); +} + +static int emoji_bytext_cmp(const void *p1, const void *p2) +{ + return strcasecmp(((struct t_slack_emoji_by_text *)p1)->text, + ((struct t_slack_emoji_by_text *)p2)->text); +} + +const char *slack_emoji_get_unicode_by_name(const char *name) +{ + struct t_slack_emoji_by_name *result; + struct t_slack_emoji_by_name key; + key.name = name; + + size_t emoji_count = sizeof(slack_emoji_by_name) + / sizeof(struct t_slack_emoji_by_name); + result = (struct t_slack_emoji_by_name *)bsearch( + &key, slack_emoji_by_name, emoji_count, + sizeof(struct t_slack_emoji_by_name), + emoji_byname_cmp); + + return result->unicode; +} + +const char *slack_emoji_get_unicode_by_text(const char *text) +{ + struct t_slack_emoji_by_text *result; + struct t_slack_emoji_by_text key; + key.text = text; + + size_t emoji_count = sizeof(slack_emoji_by_text) + / sizeof(struct t_slack_emoji_by_text); + result = (struct t_slack_emoji_by_text *)bsearch( + &key, slack_emoji_by_text, emoji_count, + sizeof(struct t_slack_emoji_by_text), + emoji_bytext_cmp); + + return result->unicode; +} + +const char *slack_emoji_get_text_by_name(const char *name) +{ + struct t_slack_emoji_by_name *result; + struct t_slack_emoji_by_name key; + key.name = name; + + size_t emoji_count = sizeof(slack_emoji_by_name) + / sizeof(struct t_slack_emoji_by_name); + result = (struct t_slack_emoji_by_name *)bsearch( + &key, slack_emoji_by_name, emoji_count, + sizeof(struct t_slack_emoji_by_name), + emoji_byname_cmp); + + return result->text_to; +} + +const char *slack_emoji_get_text_by_text(const char *text) +{ + struct t_slack_emoji_by_text *result; + struct t_slack_emoji_by_text key; + key.text = text; + + size_t emoji_count = sizeof(slack_emoji_by_text) + / sizeof(struct t_slack_emoji_by_text); + result = (struct t_slack_emoji_by_text *)bsearch( + &key, slack_emoji_by_text, emoji_count, + sizeof(struct t_slack_emoji_by_text), + emoji_bytext_cmp); + + return result->text_to; +} diff --git a/slack-emoji.h b/slack-emoji.h index 26ae2c4..aab3445 100644 --- a/slack-emoji.h +++ b/slack-emoji.h @@ -5,6 +5,12 @@ #ifndef _SLACK_EMOJI_H_ #define _SLACK_EMOJI_H_ +const char *slack_emoji_get_unicode_by_name(const char *name); +const char *slack_emoji_get_unicode_by_text(const char *text); + +const char *slack_emoji_get_text_by_name(const char *name); + +const char *slack_emoji_get_text_by_text(const char *text); #endif /*SLACK_EMOJI_H*/ diff --git a/slack-emoji.inc b/slack-emoji.inc index 743c407..de277af 100644 --- a/slack-emoji.inc +++ b/slack-emoji.inc @@ -1,4 +1,8 @@ +// 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 #define MAX_TEXTS 7 diff --git a/slack-emoji.pl b/slack-emoji.pl index 4d500fb..357f528 100644 --- a/slack-emoji.pl +++ b/slack-emoji.pl @@ -1,5 +1,9 @@ #!/usr/bin/perl -l +# 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/. + use strict; use warnings; @@ -17,6 +21,10 @@ my $maxtexts = max (map { 1 + @{$_} } (grep defined, map { $_->{'texts'} } @arra my $maxnames = max (map { 1 + @{$_} } (grep defined, map { $_->{'short_names'} } @array)); print " +// 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 #define MAX_TEXTS $maxtexts diff --git a/slack-emoji.py b/slack-emoji.py index 36e3eef..558ce9b 100755 --- a/slack-emoji.py +++ b/slack-emoji.py @@ -1,6 +1,10 @@ #!/usr/bin/python # Compatible with python v2 and v3 +# 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/. + import requests import json import ast @@ -8,6 +12,10 @@ import ast emoji = requests.get("https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json").json() print(""" +// 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 #define MAX_TEXTS %d From 5217251e94b2e5ea54a48ac660cb303257489f91 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 12 May 2018 18:22:18 +0100 Subject: [PATCH 048/118] Add Completion module and emoji completion hook Note: this doesn't enable emoji completion. Weechat seems to require hooking on the commands /input complete_* rather than just invoking hook_completion. --- Makefile | 1 + slack-completion.c | 20 + slack-completion.h | 10 + slack-emoji.c | 89 +- slack-emoji.h | 7 +- slack-emoji.inc | 3346 ++++++++++++++++++++++---------------------- slack-emoji.pl | 19 +- slack-emoji.py | 10 +- slack.c | 5 +- 9 files changed, 1820 insertions(+), 1687 deletions(-) create mode 100644 slack-completion.c create mode 100644 slack-completion.h diff --git a/Makefile b/Makefile index 9480a0f..4568e53 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ SRCS=slack.c \ slack-channel.c \ slack-config.c \ slack-command.c \ + slack-completion.c \ slack-emoji.c \ slack-input.c \ slack-message.c \ diff --git a/slack-completion.c b/slack-completion.c new file mode 100644 index 0000000..8cd19a2 --- /dev/null +++ b/slack-completion.c @@ -0,0 +1,20 @@ +// 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 "weechat-plugin.h" +#include "slack.h" +#include "slack-emoji.h" +#include "slack-workspace.h" +#include "slack-channel.h" +#include "slack-completion.h" + +void slack_completion_init() +{ + weechat_hook_completion("slack_emoji", + N_("slack emoji"), + &slack_emoji_complete_by_name_cb, + NULL, NULL); +} diff --git a/slack-completion.h b/slack-completion.h new file mode 100644 index 0000000..5ae559f --- /dev/null +++ b/slack-completion.h @@ -0,0 +1,10 @@ +// 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/. + +#ifndef _SLACK_COMPLETION_H_ +#define _SLACK_COMPLETION_H_ + +void slack_completion_init(); + +#endif /*SLACK_COMPLETION_H*/ diff --git a/slack-emoji.c b/slack-emoji.c index 1c7e6ba..8de99ba 100644 --- a/slack-emoji.c +++ b/slack-emoji.c @@ -2,6 +2,7 @@ // 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 "weechat-plugin.h" @@ -10,6 +11,8 @@ #include "slack-emoji.inc" +#define MIN(a,b) (((a)<(b))?(a):(b)) + static int emoji_byname_cmp(const void *p1, const void *p2) { return strcasecmp(((struct t_slack_emoji_by_name *)p1)->name, @@ -22,6 +25,88 @@ static int emoji_bytext_cmp(const void *p1, const void *p2) ((struct t_slack_emoji_by_text *)p2)->text); } +static size_t levenshtein_dist(const char *s, size_t len_s, const char *t, size_t len_t) +{ + size_t cost; + + /* base case: empty strings */ + if (len_s == 0) return len_t; + if (len_t == 0) return len_s; + + /* test if last characters of the strings match */ + if (s[len_s-1] == t[len_t-1]) + cost = 0; + else + cost = 1; + + /* delete char from s, delete char from t, and delete char from both */ + size_t delete = levenshtein_dist(s, len_s - 1, t, len_t ) + 1; + size_t insert = levenshtein_dist(s, len_s , t, len_t - 1) + 1; + size_t replace = levenshtein_dist(s, len_s - 1, t, len_t - 1) + cost; + return MIN( MIN( delete, insert ), replace ); +} + +static size_t wagner_fischer(const char *src, const char *targ) +{ + size_t len = strlen(targ) + 1; + size_t above[len], below[len]; + for (size_t *k = above, c = 0; k < above+len; ++k, ++c) *k=c; + + const char *src_at = src, *targ_at; + for (size_t j = 1; j < strlen(src)+1; ++j) + { + *below = j; + targ_at = targ; + for (size_t *d = above, *a = above+1, *l = below, *c = below + 1; + c < below + len; ++d, ++a, ++l, ++c) + { + *c = MIN( *src_at == *targ_at ? *d : *d + 1, MIN( *a + 1, *l + 1 ) ); + ++targ_at; + } + for (size_t *a = above, *b = below; a < above + len; ++a, ++b) *a = *b; + ++src_at; + } + + return above[len-1]; +} + +int slack_emoji_complete_by_name_cb(const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_slack_emoji_by_name *closest_emoji; + + (void) pointer; + (void) data; + + weechat_printf(NULL, "Completing!"); + + size_t i, emoji_count = sizeof(slack_emoji_by_name) + / sizeof(struct t_slack_emoji_by_name); + closest_emoji = malloc(sizeof(slack_emoji_by_name)); + memcpy(closest_emoji, slack_emoji_by_name, + sizeof(slack_emoji_by_name)); + + int edit_dist_cmp(const void *p1, const void *p2) + { + return 0; + }; + qsort(closest_emoji, emoji_count, + sizeof(struct t_slack_emoji_by_name), + edit_dist_cmp); + + for (i = 0; i < emoji_count; i++) + { + weechat_printf(NULL, closest_emoji[i].name); + weechat_hook_completion_list_add(completion, closest_emoji[i].name, + 0, WEECHAT_LIST_POS_END); + } + + free(closest_emoji); + return WEECHAT_RC_OK; +} + const char *slack_emoji_get_unicode_by_name(const char *name) { struct t_slack_emoji_by_name *result; @@ -70,7 +155,7 @@ const char *slack_emoji_get_text_by_name(const char *name) return result->text_to; } -const char *slack_emoji_get_text_by_text(const char *text) +const char *slack_emoji_get_name_by_text(const char *text) { struct t_slack_emoji_by_text *result; struct t_slack_emoji_by_text key; @@ -83,5 +168,5 @@ const char *slack_emoji_get_text_by_text(const char *text) sizeof(struct t_slack_emoji_by_text), emoji_bytext_cmp); - return result->text_to; + return result->name_to; } diff --git a/slack-emoji.h b/slack-emoji.h index aab3445..906c684 100644 --- a/slack-emoji.h +++ b/slack-emoji.h @@ -5,12 +5,17 @@ #ifndef _SLACK_EMOJI_H_ #define _SLACK_EMOJI_H_ +int slack_emoji_complete_by_name_cb(const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion); + const char *slack_emoji_get_unicode_by_name(const char *name); const char *slack_emoji_get_unicode_by_text(const char *text); const char *slack_emoji_get_text_by_name(const char *name); -const char *slack_emoji_get_text_by_text(const char *text); +const char *slack_emoji_get_name_by_text(const char *text); #endif /*SLACK_EMOJI_H*/ diff --git a/slack-emoji.inc b/slack-emoji.inc index de277af..23f0588 100644 --- a/slack-emoji.inc +++ b/slack-emoji.inc @@ -23,1680 +23,1680 @@ struct t_slack_emoji_by_text { }; static struct t_slack_emoji_by_name slack_emoji_by_name[] = -{ { "+1", "\u1f44D", NULL, {NULL} } -, { "-1", "\u1f44E", NULL, {NULL} } -, { "100", "\u1f4aF", NULL, {NULL} } -, { "1234", "\u1f522", NULL, {NULL} } -, { "8ball", "\u1f3b1", NULL, {NULL} } -, { "a", "\u1f170\ufe0f", NULL, {NULL} } -, { "ab", "\u1f18E", NULL, {NULL} } -, { "abc", "\u1f524", NULL, {NULL} } -, { "abcd", "\u1f521", NULL, {NULL} } -, { "accept", "\u1f251", NULL, {NULL} } -, { "admission_tickets", "\u1f39F\ufe0f", NULL, {NULL} } -, { "adult", "\u1f9d1", NULL, {NULL} } -, { "aerial_tramway", "\u1f6a1", NULL, {NULL} } -, { "airplane", "\u2708\ufe0f", NULL, {NULL} } -, { "airplane_arriving", "\u1f6eC", NULL, {NULL} } -, { "airplane_departure", "\u1f6eB", NULL, {NULL} } -, { "alarm_clock", "\u23f0", NULL, {NULL} } -, { "alembic", "\u2697\ufe0f", NULL, {NULL} } -, { "alien", "\u1f47D", NULL, {NULL} } -, { "ambulance", "\u1f691", NULL, {NULL} } -, { "amphora", "\u1f3fA", NULL, {NULL} } -, { "anchor", "\u2693", NULL, {NULL} } -, { "angel", "\u1f47C", NULL, {NULL} } -, { "anger", "\u1f4a2", NULL, {NULL} } -, { "angry", "\u1f620", NULL, {">:(", ">:-(", NULL} } -, { "anguished", "\u1f627", NULL, {"D:", NULL} } -, { "ant", "\u1f41C", NULL, {NULL} } -, { "apple", "\u1f34E", NULL, {NULL} } -, { "aquarius", "\u2652", NULL, {NULL} } -, { "aries", "\u2648", NULL, {NULL} } -, { "arrow_backward", "\u25c0\ufe0f", NULL, {NULL} } -, { "arrow_double_down", "\u23ec", NULL, {NULL} } -, { "arrow_double_up", "\u23eb", NULL, {NULL} } -, { "arrow_down", "\u2b07\ufe0f", NULL, {NULL} } -, { "arrow_down_small", "\u1f53D", NULL, {NULL} } -, { "arrow_forward", "\u25b6\ufe0f", NULL, {NULL} } -, { "arrow_heading_down", "\u2935\ufe0f", NULL, {NULL} } -, { "arrow_heading_up", "\u2934\ufe0f", NULL, {NULL} } -, { "arrow_left", "\u2b05\ufe0f", NULL, {NULL} } -, { "arrow_lower_left", "\u2199\ufe0f", NULL, {NULL} } -, { "arrow_lower_right", "\u2198\ufe0f", NULL, {NULL} } -, { "arrow_right", "\u27a1\ufe0f", NULL, {NULL} } -, { "arrow_right_hook", "\u21aa\ufe0f", NULL, {NULL} } -, { "arrow_up", "\u2b06\ufe0f", NULL, {NULL} } -, { "arrow_up_down", "\u2195\ufe0f", NULL, {NULL} } -, { "arrow_up_small", "\u1f53C", NULL, {NULL} } -, { "arrow_upper_left", "\u2196\ufe0f", NULL, {NULL} } -, { "arrow_upper_right", "\u2197\ufe0f", NULL, {NULL} } -, { "arrows_clockwise", "\u1f503", NULL, {NULL} } -, { "arrows_counterclockwise", "\u1f504", NULL, {NULL} } -, { "art", "\u1f3a8", NULL, {NULL} } -, { "articulated_lorry", "\u1f69B", NULL, {NULL} } -, { "astonished", "\u1f632", NULL, {NULL} } -, { "athletic_shoe", "\u1f45F", NULL, {NULL} } -, { "atm", "\u1f3e7", NULL, {NULL} } -, { "atom_symbol", "\u269b\ufe0f", NULL, {NULL} } -, { "avocado", "\u1f951", NULL, {NULL} } -, { "b", "\u1f171\ufe0f", NULL, {NULL} } -, { "baby", "\u1f476", NULL, {NULL} } -, { "baby_bottle", "\u1f37C", NULL, {NULL} } -, { "baby_chick", "\u1f424", NULL, {NULL} } -, { "baby_symbol", "\u1f6bC", NULL, {NULL} } -, { "back", "\u1f519", NULL, {NULL} } -, { "bacon", "\u1f953", NULL, {NULL} } -, { "badminton_racquet_and_shuttlecock", "\u1f3f8", NULL, {NULL} } -, { "baggage_claim", "\u1f6c4", NULL, {NULL} } -, { "baguette_bread", "\u1f956", NULL, {NULL} } -, { "balloon", "\u1f388", NULL, {NULL} } -, { "ballot_box_with_ballot", "\u1f5f3\ufe0f", NULL, {NULL} } -, { "ballot_box_with_check", "\u2611\ufe0f", NULL, {NULL} } -, { "bamboo", "\u1f38D", NULL, {NULL} } -, { "banana", "\u1f34C", NULL, {NULL} } -, { "bangbang", "\u203c\ufe0f", NULL, {NULL} } -, { "bank", "\u1f3e6", NULL, {NULL} } -, { "bar_chart", "\u1f4cA", NULL, {NULL} } -, { "barber", "\u1f488", NULL, {NULL} } -, { "barely_sunny", "\u1f325\ufe0f", NULL, {NULL} } -, { "baseball", "\u26be", NULL, {NULL} } -, { "basketball", "\u1f3c0", NULL, {NULL} } -, { "bat", "\u1f987", NULL, {NULL} } -, { "bath", "\u1f6c0", NULL, {NULL} } -, { "bathtub", "\u1f6c1", NULL, {NULL} } -, { "battery", "\u1f50B", NULL, {NULL} } -, { "beach_with_umbrella", "\u1f3d6\ufe0f", NULL, {NULL} } -, { "bear", "\u1f43B", NULL, {NULL} } -, { "bearded_person", "\u1f9d4", NULL, {NULL} } -, { "bed", "\u1f6cF\ufe0f", NULL, {NULL} } -, { "bee", "\u1f41D", NULL, {NULL} } -, { "beer", "\u1f37A", NULL, {NULL} } -, { "beers", "\u1f37B", NULL, {NULL} } -, { "beetle", "\u1f41E", NULL, {NULL} } -, { "beginner", "\u1f530", NULL, {NULL} } -, { "bell", "\u1f514", NULL, {NULL} } -, { "bellhop_bell", "\u1f6cE\ufe0f", NULL, {NULL} } -, { "bento", "\u1f371", NULL, {NULL} } -, { "bicyclist", "\u1f6b4", NULL, {NULL} } -, { "bike", "\u1f6b2", NULL, {NULL} } -, { "bikini", "\u1f459", NULL, {NULL} } -, { "billed_cap", "\u1f9e2", NULL, {NULL} } -, { "biohazard_sign", "\u2623\ufe0f", NULL, {NULL} } -, { "bird", "\u1f426", NULL, {NULL} } -, { "birthday", "\u1f382", NULL, {NULL} } -, { "black_circle", "\u26ab", NULL, {NULL} } -, { "black_circle_for_record", "\u23fa\ufe0f", NULL, {NULL} } -, { "black_heart", "\u1f5a4", NULL, {NULL} } -, { "black_joker", "\u1f0cF", NULL, {NULL} } -, { "black_large_square", "\u2b1b", NULL, {NULL} } -, { "black_left_pointing_double_triangle_with_vertical_bar", "\u23ee\ufe0f", NULL, {NULL} } -, { "black_medium_small_square", "\u25fe", NULL, {NULL} } -, { "black_medium_square", "\u25fc\ufe0f", NULL, {NULL} } -, { "black_nib", "\u2712\ufe0f", NULL, {NULL} } -, { "black_right_pointing_double_triangle_with_vertical_bar", "\u23ed\ufe0f", NULL, {NULL} } -, { "black_right_pointing_triangle_with_double_vertical_bar", "\u23ef\ufe0f", NULL, {NULL} } -, { "black_small_square", "\u25aa\ufe0f", NULL, {NULL} } -, { "black_square_button", "\u1f532", NULL, {NULL} } -, { "black_square_for_stop", "\u23f9\ufe0f", NULL, {NULL} } -, { "blond-haired-man", "\u1f471\u200d\u2642\ufe0f", NULL, {NULL} } -, { "blond-haired-woman", "\u1f471\u200d\u2640\ufe0f", NULL, {NULL} } -, { "blossom", "\u1f33C", NULL, {NULL} } -, { "blowfish", "\u1f421", NULL, {NULL} } -, { "blue_book", "\u1f4d8", NULL, {NULL} } -, { "blue_car", "\u1f699", NULL, {NULL} } -, { "blue_heart", "\u1f499", "<3", {NULL} } -, { "blush", "\u1f60A", ":)", {NULL} } -, { "boar", "\u1f417", NULL, {NULL} } -, { "boat", "\u26f5", NULL, {NULL} } -, { "bomb", "\u1f4a3", NULL, {NULL} } -, { "book", "\u1f4d6", NULL, {NULL} } -, { "bookmark", "\u1f516", NULL, {NULL} } -, { "bookmark_tabs", "\u1f4d1", NULL, {NULL} } -, { "books", "\u1f4dA", NULL, {NULL} } -, { "boom", "\u1f4a5", NULL, {NULL} } -, { "boot", "\u1f462", NULL, {NULL} } -, { "bouquet", "\u1f490", NULL, {NULL} } -, { "bow", "\u1f647", NULL, {NULL} } -, { "bow_and_arrow", "\u1f3f9", NULL, {NULL} } -, { "bowl_with_spoon", "\u1f963", NULL, {NULL} } -, { "bowling", "\u1f3b3", NULL, {NULL} } -, { "boxing_glove", "\u1f94A", NULL, {NULL} } -, { "boy", "\u1f466", NULL, {NULL} } -, { "brain", "\u1f9e0", NULL, {NULL} } -, { "bread", "\u1f35E", NULL, {NULL} } -, { "breast-feeding", "\u1f931", NULL, {NULL} } -, { "bride_with_veil", "\u1f470", NULL, {NULL} } -, { "bridge_at_night", "\u1f309", NULL, {NULL} } -, { "briefcase", "\u1f4bC", NULL, {NULL} } -, { "broccoli", "\u1f966", NULL, {NULL} } -, { "broken_heart", "\u1f494", "", ":->", NULL} } -, { "leaves", "\u1f343", NULL, {NULL} } -, { "ledger", "\u1f4d2", NULL, {NULL} } -, { "left-facing_fist", "\u1f91B", NULL, {NULL} } -, { "left_luggage", "\u1f6c5", NULL, {NULL} } -, { "left_right_arrow", "\u2194\ufe0f", NULL, {NULL} } -, { "left_speech_bubble", "\u1f5e8\ufe0f", NULL, {NULL} } -, { "leftwards_arrow_with_hook", "\u21a9\ufe0f", NULL, {NULL} } -, { "lemon", "\u1f34B", NULL, {NULL} } -, { "leo", "\u264c", NULL, {NULL} } -, { "leopard", "\u1f406", NULL, {NULL} } -, { "level_slider", "\u1f39A\ufe0f", NULL, {NULL} } -, { "libra", "\u264e", NULL, {NULL} } -, { "light_rail", "\u1f688", NULL, {NULL} } -, { "lightning", "\u1f329\ufe0f", NULL, {NULL} } -, { "lightning_cloud", "\u1f329\ufe0f", NULL, {NULL} } -, { "link", "\u1f517", NULL, {NULL} } -, { "linked_paperclips", "\u1f587\ufe0f", NULL, {NULL} } -, { "lion_face", "\u1f981", NULL, {NULL} } -, { "lips", "\u1f444", NULL, {NULL} } -, { "lipstick", "\u1f484", NULL, {NULL} } -, { "lizard", "\u1f98E", NULL, {NULL} } -, { "lock", "\u1f512", NULL, {NULL} } -, { "lock_with_ink_pen", "\u1f50F", NULL, {NULL} } -, { "lollipop", "\u1f36D", NULL, {NULL} } -, { "loop", "\u27bf", NULL, {NULL} } -, { "loud_sound", "\u1f50A", NULL, {NULL} } -, { "loudspeaker", "\u1f4e2", NULL, {NULL} } -, { "love_hotel", "\u1f3e9", NULL, {NULL} } -, { "love_letter", "\u1f48C", NULL, {NULL} } -, { "low_brightness", "\u1f505", NULL, {NULL} } -, { "lower_left_ballpoint_pen", "\u1f58A\ufe0f", NULL, {NULL} } -, { "lower_left_crayon", "\u1f58D\ufe0f", NULL, {NULL} } -, { "lower_left_fountain_pen", "\u1f58B\ufe0f", NULL, {NULL} } -, { "lower_left_paintbrush", "\u1f58C\ufe0f", NULL, {NULL} } -, { "lying_face", "\u1f925", NULL, {NULL} } -, { "m", "\u24c2\ufe0f", NULL, {NULL} } -, { "mag", "\u1f50D", NULL, {NULL} } -, { "mag_right", "\u1f50E", NULL, {NULL} } -, { "mage", "\u1f9d9", NULL, {NULL} } -, { "mahjong", "\u1f004", NULL, {NULL} } -, { "mailbox", "\u1f4eB", NULL, {NULL} } -, { "mailbox_closed", "\u1f4eA", NULL, {NULL} } -, { "mailbox_with_mail", "\u1f4eC", NULL, {NULL} } -, { "mailbox_with_no_mail", "\u1f4eD", NULL, {NULL} } -, { "male-artist", "\u1f468\u200d\u1f3a8", NULL, {NULL} } -, { "male-astronaut", "\u1f468\u200d\u1f680", NULL, {NULL} } -, { "male-construction-worker", "\u1f477\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male-cook", "\u1f468\u200d\u1f373", NULL, {NULL} } -, { "male-detective", "\u1f575\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male-doctor", "\u1f468\u200d\u2695\ufe0f", NULL, {NULL} } -, { "male-factory-worker", "\u1f468\u200d\u1f3eD", NULL, {NULL} } -, { "male-farmer", "\u1f468\u200d\u1f33E", NULL, {NULL} } -, { "male-firefighter", "\u1f468\u200d\u1f692", NULL, {NULL} } -, { "male-guard", "\u1f482\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male-judge", "\u1f468\u200d\u2696\ufe0f", NULL, {NULL} } -, { "male-mechanic", "\u1f468\u200d\u1f527", NULL, {NULL} } -, { "male-office-worker", "\u1f468\u200d\u1f4bC", NULL, {NULL} } -, { "male-pilot", "\u1f468\u200d\u2708\ufe0f", NULL, {NULL} } -, { "male-police-officer", "\u1f46E\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male-scientist", "\u1f468\u200d\u1f52C", NULL, {NULL} } -, { "male-singer", "\u1f468\u200d\u1f3a4", NULL, {NULL} } -, { "male-student", "\u1f468\u200d\u1f393", NULL, {NULL} } -, { "male-teacher", "\u1f468\u200d\u1f3eB", NULL, {NULL} } -, { "male-technologist", "\u1f468\u200d\u1f4bB", NULL, {NULL} } -, { "male_elf", "\u1f9dD\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male_fairy", "\u1f9dA\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male_genie", "\u1f9dE\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male_mage", "\u1f9d9\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male_sign", "\u2642\ufe0f", NULL, {NULL} } -, { "male_vampire", "\u1f9dB\u200d\u2642\ufe0f", NULL, {NULL} } -, { "male_zombie", "\u1f9dF\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man", "\u1f468", NULL, {NULL} } -, { "man-biking", "\u1f6b4\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-bouncing-ball", "\u26f9\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-bowing", "\u1f647\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-boy", "\u1f468\u200d\u1f466", NULL, {NULL} } -, { "man-boy-boy", "\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { "man-cartwheeling", "\u1f938\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-facepalming", "\u1f926\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-frowning", "\u1f64D\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-gesturing-no", "\u1f645\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-gesturing-ok", "\u1f646\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-getting-haircut", "\u1f487\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-getting-massage", "\u1f486\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-girl", "\u1f468\u200d\u1f467", NULL, {NULL} } -, { "man-girl-boy", "\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { "man-girl-girl", "\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { "man-golfing", "\u1f3cC\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-heart-man", "\u1f468\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } -, { "man-juggling", "\u1f939\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-kiss-man", "\u1f468\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } -, { "man-lifting-weights", "\u1f3cB\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-man-boy", "\u1f468\u200d\u1f468\u200d\u1f466", NULL, {NULL} } -, { "man-man-boy-boy", "\u1f468\u200d\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { "man-man-girl", "\u1f468\u200d\u1f468\u200d\u1f467", NULL, {NULL} } -, { "man-man-girl-boy", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { "man-man-girl-girl", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { "man-mountain-biking", "\u1f6b5\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-playing-handball", "\u1f93E\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-playing-water-polo", "\u1f93D\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-pouting", "\u1f64E\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-raising-hand", "\u1f64B\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-rowing-boat", "\u1f6a3\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-running", "\u1f3c3\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-shrugging", "\u1f937\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-surfing", "\u1f3c4\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-swimming", "\u1f3cA\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-tipping-hand", "\u1f481\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-walking", "\u1f6b6\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-wearing-turban", "\u1f473\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-with-bunny-ears-partying", "\u1f46F\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man-woman-boy", "\u1f468\u200d\u1f469\u200d\u1f466", NULL, {NULL} } -, { "man-woman-boy", "\u1f46A", NULL, {NULL} } -, { "man-woman-boy-boy", "\u1f468\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { "man-woman-girl", "\u1f468\u200d\u1f469\u200d\u1f467", NULL, {NULL} } -, { "man-woman-girl-boy", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { "man-woman-girl-girl", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { "man-wrestling", "\u1f93C\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man_and_woman_holding_hands", "\u1f46B", NULL, {NULL} } -, { "man_climbing", "\u1f9d7\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man_dancing", "\u1f57A", NULL, {NULL} } -, { "man_in_business_suit_levitating", "\u1f574\ufe0f", NULL, {NULL} } -, { "man_in_lotus_position", "\u1f9d8\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man_in_steamy_room", "\u1f9d6\u200d\u2642\ufe0f", NULL, {NULL} } -, { "man_in_tuxedo", "\u1f935", NULL, {NULL} } -, { "man_with_gua_pi_mao", "\u1f472", NULL, {NULL} } -, { "man_with_turban", "\u1f473", NULL, {NULL} } -, { "mans_shoe", "\u1f45E", NULL, {NULL} } -, { "mantelpiece_clock", "\u1f570\ufe0f", NULL, {NULL} } -, { "maple_leaf", "\u1f341", NULL, {NULL} } -, { "martial_arts_uniform", "\u1f94B", NULL, {NULL} } -, { "mask", "\u1f637", NULL, {NULL} } -, { "massage", "\u1f486", NULL, {NULL} } -, { "meat_on_bone", "\u1f356", NULL, {NULL} } -, { "medal", "\u1f396\ufe0f", NULL, {NULL} } -, { "medical_symbol", "\u2695\ufe0f", NULL, {NULL} } -, { "mega", "\u1f4e3", NULL, {NULL} } -, { "melon", "\u1f348", NULL, {NULL} } -, { "memo", "\u1f4dD", NULL, {NULL} } -, { "menorah_with_nine_branches", "\u1f54E", NULL, {NULL} } -, { "mens", "\u1f6b9", NULL, {NULL} } -, { "mermaid", "\u1f9dC\u200d\u2640\ufe0f", NULL, {NULL} } -, { "merman", "\u1f9dC\u200d\u2642\ufe0f", NULL, {NULL} } -, { "merperson", "\u1f9dC", NULL, {NULL} } -, { "metro", "\u1f687", NULL, {NULL} } -, { "microphone", "\u1f3a4", NULL, {NULL} } -, { "microscope", "\u1f52C", NULL, {NULL} } -, { "middle_finger", "\u1f595", NULL, {NULL} } -, { "milky_way", "\u1f30C", NULL, {NULL} } -, { "minibus", "\u1f690", NULL, {NULL} } -, { "minidisc", "\u1f4bD", NULL, {NULL} } -, { "mobile_phone_off", "\u1f4f4", NULL, {NULL} } -, { "money_mouth_face", "\u1f911", NULL, {NULL} } -, { "money_with_wings", "\u1f4b8", NULL, {NULL} } -, { "moneybag", "\u1f4b0", NULL, {NULL} } -, { "monkey", "\u1f412", NULL, {NULL} } -, { "monkey_face", "\u1f435", NULL, {":o)", NULL} } -, { "monorail", "\u1f69D", NULL, {NULL} } -, { "moon", "\u1f314", NULL, {NULL} } -, { "mortar_board", "\u1f393", NULL, {NULL} } -, { "mosque", "\u1f54C", NULL, {NULL} } -, { "mostly_sunny", "\u1f324\ufe0f", NULL, {NULL} } -, { "mother_christmas", "\u1f936", NULL, {NULL} } -, { "motor_boat", "\u1f6e5\ufe0f", NULL, {NULL} } -, { "motor_scooter", "\u1f6f5", NULL, {NULL} } -, { "motorway", "\u1f6e3\ufe0f", NULL, {NULL} } -, { "mount_fuji", "\u1f5fB", NULL, {NULL} } -, { "mountain", "\u26f0\ufe0f", NULL, {NULL} } -, { "mountain_bicyclist", "\u1f6b5", NULL, {NULL} } -, { "mountain_cableway", "\u1f6a0", NULL, {NULL} } -, { "mountain_railway", "\u1f69E", NULL, {NULL} } -, { "mouse", "\u1f42D", NULL, {NULL} } -, { "mouse2", "\u1f401", NULL, {NULL} } -, { "movie_camera", "\u1f3a5", NULL, {NULL} } -, { "moyai", "\u1f5fF", NULL, {NULL} } -, { "mrs_claus", "\u1f936", NULL, {NULL} } -, { "muscle", "\u1f4aA", NULL, {NULL} } -, { "mushroom", "\u1f344", NULL, {NULL} } -, { "musical_keyboard", "\u1f3b9", NULL, {NULL} } -, { "musical_note", "\u1f3b5", NULL, {NULL} } -, { "musical_score", "\u1f3bC", NULL, {NULL} } -, { "mute", "\u1f507", NULL, {NULL} } -, { "nail_care", "\u1f485", NULL, {NULL} } -, { "name_badge", "\u1f4dB", NULL, {NULL} } -, { "national_park", "\u1f3dE\ufe0f", NULL, {NULL} } -, { "nauseated_face", "\u1f922", NULL, {NULL} } -, { "necktie", "\u1f454", NULL, {NULL} } -, { "negative_squared_cross_mark", "\u274e", NULL, {NULL} } -, { "nerd_face", "\u1f913", NULL, {NULL} } -, { "neutral_face", "\u1f610", NULL, {":|", ":-|", NULL} } -, { "new", "\u1f195", NULL, {NULL} } -, { "new_moon", "\u1f311", NULL, {NULL} } -, { "new_moon_with_face", "\u1f31A", NULL, {NULL} } -, { "newspaper", "\u1f4f0", NULL, {NULL} } -, { "ng", "\u1f196", NULL, {NULL} } -, { "night_with_stars", "\u1f303", NULL, {NULL} } -, { "nine", "9\ufe0f\u20e3", NULL, {NULL} } -, { "no_bell", "\u1f515", NULL, {NULL} } -, { "no_bicycles", "\u1f6b3", NULL, {NULL} } -, { "no_entry", "\u26d4", NULL, {NULL} } -, { "no_entry_sign", "\u1f6aB", NULL, {NULL} } -, { "no_good", "\u1f645", NULL, {NULL} } -, { "no_mobile_phones", "\u1f4f5", NULL, {NULL} } -, { "no_mouth", "\u1f636", NULL, {NULL} } -, { "no_pedestrians", "\u1f6b7", NULL, {NULL} } -, { "no_smoking", "\u1f6aD", NULL, {NULL} } -, { "non-potable_water", "\u1f6b1", NULL, {NULL} } -, { "nose", "\u1f443", NULL, {NULL} } -, { "notebook", "\u1f4d3", NULL, {NULL} } -, { "notebook_with_decorative_cover", "\u1f4d4", NULL, {NULL} } -, { "notes", "\u1f3b6", NULL, {NULL} } -, { "nut_and_bolt", "\u1f529", NULL, {NULL} } -, { "o", "\u2b55", NULL, {NULL} } -, { "o2", "\u1f17E\ufe0f", NULL, {NULL} } -, { "ocean", "\u1f30A", NULL, {NULL} } -, { "octagonal_sign", "\u1f6d1", NULL, {NULL} } -, { "octopus", "\u1f419", NULL, {NULL} } -, { "oden", "\u1f362", NULL, {NULL} } -, { "office", "\u1f3e2", NULL, {NULL} } -, { "oil_drum", "\u1f6e2\ufe0f", NULL, {NULL} } -, { "ok", "\u1f197", NULL, {NULL} } -, { "ok_hand", "\u1f44C", NULL, {NULL} } -, { "ok_woman", "\u1f646", NULL, {NULL} } -, { "old_key", "\u1f5dD\ufe0f", NULL, {NULL} } -, { "older_adult", "\u1f9d3", NULL, {NULL} } -, { "older_man", "\u1f474", NULL, {NULL} } -, { "older_woman", "\u1f475", NULL, {NULL} } -, { "om_symbol", "\u1f549\ufe0f", NULL, {NULL} } -, { "on", "\u1f51B", NULL, {NULL} } -, { "oncoming_automobile", "\u1f698", NULL, {NULL} } -, { "oncoming_bus", "\u1f68D", NULL, {NULL} } -, { "oncoming_police_car", "\u1f694", NULL, {NULL} } -, { "oncoming_taxi", "\u1f696", NULL, {NULL} } -, { "one", "1\ufe0f\u20e3", NULL, {NULL} } -, { "open_book", "\u1f4d6", NULL, {NULL} } -, { "open_file_folder", "\u1f4c2", NULL, {NULL} } -, { "open_hands", "\u1f450", NULL, {NULL} } -, { "open_mouth", "\u1f62E", NULL, {":o", ":-o", ":O", ":-O", NULL} } -, { "ophiuchus", "\u26ce", NULL, {NULL} } -, { "orange_book", "\u1f4d9", NULL, {NULL} } -, { "orange_heart", "\u1f9e1", NULL, {NULL} } -, { "orthodox_cross", "\u2626\ufe0f", NULL, {NULL} } -, { "outbox_tray", "\u1f4e4", NULL, {NULL} } -, { "owl", "\u1f989", NULL, {NULL} } -, { "ox", "\u1f402", NULL, {NULL} } -, { "package", "\u1f4e6", NULL, {NULL} } -, { "page_facing_up", "\u1f4c4", NULL, {NULL} } -, { "page_with_curl", "\u1f4c3", NULL, {NULL} } -, { "pager", "\u1f4dF", NULL, {NULL} } -, { "palm_tree", "\u1f334", NULL, {NULL} } -, { "palms_up_together", "\u1f932", NULL, {NULL} } -, { "pancakes", "\u1f95E", NULL, {NULL} } -, { "panda_face", "\u1f43C", NULL, {NULL} } -, { "paperclip", "\u1f4cE", NULL, {NULL} } -, { "parking", "\u1f17F\ufe0f", NULL, {NULL} } -, { "part_alternation_mark", "\u303d\ufe0f", NULL, {NULL} } -, { "partly_sunny", "\u26c5", NULL, {NULL} } -, { "partly_sunny_rain", "\u1f326\ufe0f", NULL, {NULL} } -, { "passenger_ship", "\u1f6f3\ufe0f", NULL, {NULL} } -, { "passport_control", "\u1f6c2", NULL, {NULL} } -, { "paw_prints", "\u1f43E", NULL, {NULL} } -, { "peace_symbol", "\u262e\ufe0f", NULL, {NULL} } -, { "peach", "\u1f351", NULL, {NULL} } -, { "peanuts", "\u1f95C", NULL, {NULL} } -, { "pear", "\u1f350", NULL, {NULL} } -, { "pencil", "\u1f4dD", NULL, {NULL} } -, { "pencil2", "\u270f\ufe0f", NULL, {NULL} } -, { "penguin", "\u1f427", NULL, {NULL} } -, { "pensive", "\u1f614", NULL, {NULL} } -, { "performing_arts", "\u1f3aD", NULL, {NULL} } -, { "persevere", "\u1f623", NULL, {NULL} } -, { "person_climbing", "\u1f9d7", NULL, {NULL} } -, { "person_doing_cartwheel", "\u1f938", NULL, {NULL} } -, { "person_frowning", "\u1f64D", NULL, {NULL} } -, { "person_in_lotus_position", "\u1f9d8", NULL, {NULL} } -, { "person_in_steamy_room", "\u1f9d6", NULL, {NULL} } -, { "person_with_ball", "\u26f9\ufe0f", NULL, {NULL} } -, { "person_with_blond_hair", "\u1f471", NULL, {NULL} } -, { "person_with_headscarf", "\u1f9d5", NULL, {NULL} } -, { "person_with_pouting_face", "\u1f64E", NULL, {NULL} } -, { "phone", "\u260e\ufe0f", NULL, {NULL} } -, { "pick", "\u26cf\ufe0f", NULL, {NULL} } -, { "pie", "\u1f967", NULL, {NULL} } -, { "pig", "\u1f437", NULL, {NULL} } -, { "pig2", "\u1f416", NULL, {NULL} } -, { "pig_nose", "\u1f43D", NULL, {NULL} } -, { "pill", "\u1f48A", NULL, {NULL} } -, { "pineapple", "\u1f34D", NULL, {NULL} } -, { "pisces", "\u2653", NULL, {NULL} } -, { "pizza", "\u1f355", NULL, {NULL} } -, { "place_of_worship", "\u1f6d0", NULL, {NULL} } -, { "point_down", "\u1f447", NULL, {NULL} } -, { "point_left", "\u1f448", NULL, {NULL} } -, { "point_right", "\u1f449", NULL, {NULL} } -, { "point_up", "\u261d\ufe0f", NULL, {NULL} } -, { "point_up_2", "\u1f446", NULL, {NULL} } -, { "police_car", "\u1f693", NULL, {NULL} } -, { "poodle", "\u1f429", NULL, {NULL} } -, { "poop", "\u1f4a9", NULL, {NULL} } -, { "popcorn", "\u1f37F", NULL, {NULL} } -, { "post_office", "\u1f3e3", NULL, {NULL} } -, { "postal_horn", "\u1f4eF", NULL, {NULL} } -, { "postbox", "\u1f4eE", NULL, {NULL} } -, { "potable_water", "\u1f6b0", NULL, {NULL} } -, { "potato", "\u1f954", NULL, {NULL} } -, { "pouch", "\u1f45D", NULL, {NULL} } -, { "poultry_leg", "\u1f357", NULL, {NULL} } -, { "pound", "\u1f4b7", NULL, {NULL} } -, { "pouting_cat", "\u1f63E", NULL, {NULL} } -, { "pray", "\u1f64F", NULL, {NULL} } -, { "prayer_beads", "\u1f4fF", NULL, {NULL} } -, { "pregnant_woman", "\u1f930", NULL, {NULL} } -, { "pretzel", "\u1f968", NULL, {NULL} } -, { "prince", "\u1f934", NULL, {NULL} } -, { "princess", "\u1f478", NULL, {NULL} } -, { "printer", "\u1f5a8\ufe0f", NULL, {NULL} } -, { "punch", "\u1f44A", NULL, {NULL} } -, { "purple_heart", "\u1f49C", "<3", {NULL} } -, { "purse", "\u1f45B", NULL, {NULL} } -, { "pushpin", "\u1f4cC", NULL, {NULL} } -, { "put_litter_in_its_place", "\u1f6aE", NULL, {NULL} } -, { "question", "\u2753", NULL, {NULL} } -, { "rabbit", "\u1f430", NULL, {NULL} } -, { "rabbit2", "\u1f407", NULL, {NULL} } -, { "racehorse", "\u1f40E", NULL, {NULL} } -, { "racing_car", "\u1f3cE\ufe0f", NULL, {NULL} } -, { "racing_motorcycle", "\u1f3cD\ufe0f", NULL, {NULL} } -, { "radio", "\u1f4fB", NULL, {NULL} } -, { "radio_button", "\u1f518", NULL, {NULL} } -, { "radioactive_sign", "\u2622\ufe0f", NULL, {NULL} } -, { "rage", "\u1f621", NULL, {NULL} } -, { "railway_car", "\u1f683", NULL, {NULL} } -, { "railway_track", "\u1f6e4\ufe0f", NULL, {NULL} } -, { "rain_cloud", "\u1f327\ufe0f", NULL, {NULL} } -, { "rainbow", "\u1f308", NULL, {NULL} } -, { "rainbow-flag", "\u1f3f3\ufe0f\u200d\u1f308", NULL, {NULL} } -, { "raised_back_of_hand", "\u1f91A", NULL, {NULL} } -, { "raised_hand", "\u270b", NULL, {NULL} } -, { "raised_hand_with_fingers_splayed", "\u1f590\ufe0f", NULL, {NULL} } -, { "raised_hands", "\u1f64C", NULL, {NULL} } -, { "raising_hand", "\u1f64B", NULL, {NULL} } -, { "ram", "\u1f40F", NULL, {NULL} } -, { "ramen", "\u1f35C", NULL, {NULL} } -, { "rat", "\u1f400", NULL, {NULL} } -, { "recycle", "\u267b\ufe0f", NULL, {NULL} } -, { "red_car", "\u1f697", NULL, {NULL} } -, { "red_circle", "\u1f534", NULL, {NULL} } -, { "registered", "\u00ae\ufe0f", NULL, {NULL} } -, { "relaxed", "\u263a\ufe0f", NULL, {NULL} } -, { "relieved", "\u1f60C", NULL, {NULL} } -, { "reminder_ribbon", "\u1f397\ufe0f", NULL, {NULL} } -, { "repeat", "\u1f501", NULL, {NULL} } -, { "repeat_one", "\u1f502", NULL, {NULL} } -, { "restroom", "\u1f6bB", NULL, {NULL} } -, { "reversed_hand_with_middle_finger_extended", "\u1f595", NULL, {NULL} } -, { "revolving_hearts", "\u1f49E", NULL, {NULL} } -, { "rewind", "\u23ea", NULL, {NULL} } -, { "rhinoceros", "\u1f98F", NULL, {NULL} } -, { "ribbon", "\u1f380", NULL, {NULL} } -, { "rice", "\u1f35A", NULL, {NULL} } -, { "rice_ball", "\u1f359", NULL, {NULL} } -, { "rice_cracker", "\u1f358", NULL, {NULL} } -, { "rice_scene", "\u1f391", NULL, {NULL} } -, { "right-facing_fist", "\u1f91C", NULL, {NULL} } -, { "right_anger_bubble", "\u1f5eF\ufe0f", NULL, {NULL} } -, { "ring", "\u1f48D", NULL, {NULL} } -, { "robot_face", "\u1f916", NULL, {NULL} } -, { "rocket", "\u1f680", NULL, {NULL} } -, { "rolled_up_newspaper", "\u1f5dE\ufe0f", NULL, {NULL} } -, { "roller_coaster", "\u1f3a2", NULL, {NULL} } -, { "rolling_on_the_floor_laughing", "\u1f923", NULL, {NULL} } -, { "rooster", "\u1f413", NULL, {NULL} } -, { "rose", "\u1f339", NULL, {NULL} } -, { "rosette", "\u1f3f5\ufe0f", NULL, {NULL} } -, { "rotating_light", "\u1f6a8", NULL, {NULL} } -, { "round_pushpin", "\u1f4cD", NULL, {NULL} } -, { "rowboat", "\u1f6a3", NULL, {NULL} } -, { "ru", "\u1f1f7\u1f1fA", NULL, {NULL} } -, { "rugby_football", "\u1f3c9", NULL, {NULL} } -, { "runner", "\u1f3c3", NULL, {NULL} } -, { "running", "\u1f3c3", NULL, {NULL} } -, { "running_shirt_with_sash", "\u1f3bD", NULL, {NULL} } -, { "sa", "\u1f202\ufe0f", NULL, {NULL} } -, { "sagittarius", "\u2650", NULL, {NULL} } -, { "sailboat", "\u26f5", NULL, {NULL} } -, { "sake", "\u1f376", NULL, {NULL} } -, { "sandal", "\u1f461", NULL, {NULL} } -, { "sandwich", "\u1f96A", NULL, {NULL} } -, { "santa", "\u1f385", NULL, {NULL} } -, { "satellite", "\u1f6f0\ufe0f", NULL, {NULL} } -, { "satellite_antenna", "\u1f4e1", NULL, {NULL} } -, { "satisfied", "\u1f606", NULL, {":>", ":->", NULL} } -, { "sauropod", "\u1f995", NULL, {NULL} } -, { "saxophone", "\u1f3b7", NULL, {NULL} } -, { "scales", "\u2696\ufe0f", NULL, {NULL} } -, { "scarf", "\u1f9e3", NULL, {NULL} } -, { "school", "\u1f3eB", NULL, {NULL} } -, { "school_satchel", "\u1f392", NULL, {NULL} } -, { "scissors", "\u2702\ufe0f", NULL, {NULL} } -, { "scooter", "\u1f6f4", NULL, {NULL} } -, { "scorpion", "\u1f982", NULL, {NULL} } -, { "scorpius", "\u264f", NULL, {NULL} } -, { "scream", "\u1f631", NULL, {NULL} } -, { "scream_cat", "\u1f640", NULL, {NULL} } -, { "scroll", "\u1f4dC", NULL, {NULL} } -, { "seat", "\u1f4bA", NULL, {NULL} } -, { "second_place_medal", "\u1f948", NULL, {NULL} } -, { "secret", "\u3299\ufe0f", NULL, {NULL} } -, { "see_no_evil", "\u1f648", NULL, {NULL} } -, { "seedling", "\u1f331", NULL, {NULL} } -, { "selfie", "\u1f933", NULL, {NULL} } -, { "serious_face_with_symbols_covering_mouth", "\u1f92C", NULL, {NULL} } -, { "seven", "7\ufe0f\u20e3", NULL, {NULL} } -, { "shallow_pan_of_food", "\u1f958", NULL, {NULL} } -, { "shamrock", "\u2618\ufe0f", NULL, {NULL} } -, { "shark", "\u1f988", NULL, {NULL} } -, { "shaved_ice", "\u1f367", NULL, {NULL} } -, { "sheep", "\u1f411", NULL, {NULL} } -, { "shell", "\u1f41A", NULL, {NULL} } -, { "shield", "\u1f6e1\ufe0f", NULL, {NULL} } -, { "shinto_shrine", "\u26e9\ufe0f", NULL, {NULL} } -, { "ship", "\u1f6a2", NULL, {NULL} } -, { "shirt", "\u1f455", NULL, {NULL} } -, { "shit", "\u1f4a9", NULL, {NULL} } -, { "shocked_face_with_exploding_head", "\u1f92F", NULL, {NULL} } -, { "shoe", "\u1f45E", NULL, {NULL} } -, { "shopping_bags", "\u1f6cD\ufe0f", NULL, {NULL} } -, { "shopping_trolley", "\u1f6d2", NULL, {NULL} } -, { "shower", "\u1f6bF", NULL, {NULL} } -, { "shrimp", "\u1f990", NULL, {NULL} } -, { "shrug", "\u1f937", NULL, {NULL} } -, { "shushing_face", "\u1f92B", NULL, {NULL} } -, { "sign_of_the_horns", "\u1f918", NULL, {NULL} } -, { "signal_strength", "\u1f4f6", NULL, {NULL} } -, { "six", "6\ufe0f\u20e3", NULL, {NULL} } -, { "six_pointed_star", "\u1f52F", NULL, {NULL} } -, { "ski", "\u1f3bF", NULL, {NULL} } -, { "skier", "\u26f7\ufe0f", NULL, {NULL} } -, { "skin-tone-2", "\u1f3fB", NULL, {NULL} } -, { "skin-tone-3", "\u1f3fC", NULL, {NULL} } -, { "skin-tone-4", "\u1f3fD", NULL, {NULL} } -, { "skin-tone-5", "\u1f3fE", NULL, {NULL} } -, { "skin-tone-6", "\u1f3fF", NULL, {NULL} } -, { "skull", "\u1f480", NULL, {NULL} } -, { "skull_and_crossbones", "\u2620\ufe0f", NULL, {NULL} } -, { "sled", "\u1f6f7", NULL, {NULL} } -, { "sleeping", "\u1f634", NULL, {NULL} } -, { "sleeping_accommodation", "\u1f6cC", NULL, {NULL} } -, { "sleepy", "\u1f62A", NULL, {NULL} } -, { "sleuth_or_spy", "\u1f575\ufe0f", NULL, {NULL} } -, { "slightly_frowning_face", "\u1f641", NULL, {NULL} } -, { "slightly_smiling_face", "\u1f642", NULL, {":)", "(:", ":-)", NULL} } -, { "slot_machine", "\u1f3b0", NULL, {NULL} } -, { "small_airplane", "\u1f6e9\ufe0f", NULL, {NULL} } -, { "small_blue_diamond", "\u1f539", NULL, {NULL} } -, { "small_orange_diamond", "\u1f538", NULL, {NULL} } -, { "small_red_triangle", "\u1f53A", NULL, {NULL} } -, { "small_red_triangle_down", "\u1f53B", NULL, {NULL} } -, { "smile", "\u1f604", ":)", {"C:", "c:", ":D", ":-D", NULL} } -, { "smile_cat", "\u1f638", NULL, {NULL} } -, { "smiley", "\u1f603", ":)", {"=)", "=-)", NULL} } -, { "smiley_cat", "\u1f63A", NULL, {NULL} } -, { "smiling_face_with_smiling_eyes_and_hand_covering_mouth", "\u1f92D", NULL, {NULL} } -, { "smiling_imp", "\u1f608", NULL, {NULL} } -, { "smirk", "\u1f60F", NULL, {NULL} } -, { "smirk_cat", "\u1f63C", NULL, {NULL} } -, { "smoking", "\u1f6aC", NULL, {NULL} } -, { "snail", "\u1f40C", NULL, {NULL} } -, { "snake", "\u1f40D", NULL, {NULL} } -, { "sneezing_face", "\u1f927", NULL, {NULL} } -, { "snow_capped_mountain", "\u1f3d4\ufe0f", NULL, {NULL} } -, { "snow_cloud", "\u1f328\ufe0f", NULL, {NULL} } -, { "snowboarder", "\u1f3c2", NULL, {NULL} } -, { "snowflake", "\u2744\ufe0f", NULL, {NULL} } -, { "snowman", "\u2603\ufe0f", NULL, {NULL} } -, { "snowman_without_snow", "\u26c4", NULL, {NULL} } -, { "sob", "\u1f62D", ":'(", {NULL} } -, { "soccer", "\u26bd", NULL, {NULL} } -, { "socks", "\u1f9e6", NULL, {NULL} } -, { "soon", "\u1f51C", NULL, {NULL} } -, { "sos", "\u1f198", NULL, {NULL} } -, { "sound", "\u1f509", NULL, {NULL} } -, { "space_invader", "\u1f47E", NULL, {NULL} } -, { "spades", "\u2660\ufe0f", NULL, {NULL} } -, { "spaghetti", "\u1f35D", NULL, {NULL} } -, { "sparkle", "\u2747\ufe0f", NULL, {NULL} } -, { "sparkler", "\u1f387", NULL, {NULL} } -, { "sparkles", "\u2728", NULL, {NULL} } -, { "sparkling_heart", "\u1f496", NULL, {NULL} } -, { "speak_no_evil", "\u1f64A", NULL, {NULL} } -, { "speaker", "\u1f508", NULL, {NULL} } -, { "speaking_head_in_silhouette", "\u1f5e3\ufe0f", NULL, {NULL} } -, { "speech_balloon", "\u1f4aC", NULL, {NULL} } -, { "speedboat", "\u1f6a4", NULL, {NULL} } -, { "spider", "\u1f577\ufe0f", NULL, {NULL} } -, { "spider_web", "\u1f578\ufe0f", NULL, {NULL} } -, { "spiral_calendar_pad", "\u1f5d3\ufe0f", NULL, {NULL} } -, { "spiral_note_pad", "\u1f5d2\ufe0f", NULL, {NULL} } -, { "spock-hand", "\u1f596", NULL, {NULL} } -, { "spoon", "\u1f944", NULL, {NULL} } -, { "sports_medal", "\u1f3c5", NULL, {NULL} } -, { "squid", "\u1f991", NULL, {NULL} } -, { "stadium", "\u1f3dF\ufe0f", NULL, {NULL} } -, { "staff_of_aesculapius", "\u2695\ufe0f", NULL, {NULL} } -, { "star", "\u2b50", NULL, {NULL} } -, { "star-struck", "\u1f929", NULL, {NULL} } -, { "star2", "\u1f31F", NULL, {NULL} } -, { "star_and_crescent", "\u262a\ufe0f", NULL, {NULL} } -, { "star_of_david", "\u2721\ufe0f", NULL, {NULL} } -, { "stars", "\u1f320", NULL, {NULL} } -, { "station", "\u1f689", NULL, {NULL} } -, { "statue_of_liberty", "\u1f5fD", NULL, {NULL} } -, { "steam_locomotive", "\u1f682", NULL, {NULL} } -, { "stew", "\u1f372", NULL, {NULL} } -, { "stopwatch", "\u23f1\ufe0f", NULL, {NULL} } -, { "straight_ruler", "\u1f4cF", NULL, {NULL} } -, { "strawberry", "\u1f353", NULL, {NULL} } -, { "stuck_out_tongue", "\u1f61B", ":p", {":p", ":-p", ":P", ":-P", ":b", ":-b", NULL} } -, { "stuck_out_tongue_closed_eyes", "\u1f61D", NULL, {NULL} } -, { "stuck_out_tongue_winking_eye", "\u1f61C", ";p", {";p", ";-p", ";b", ";-b", ";P", ";-P", NULL} } -, { "studio_microphone", "\u1f399\ufe0f", NULL, {NULL} } -, { "stuffed_flatbread", "\u1f959", NULL, {NULL} } -, { "sun_behind_cloud", "\u1f325\ufe0f", NULL, {NULL} } -, { "sun_behind_rain_cloud", "\u1f326\ufe0f", NULL, {NULL} } -, { "sun_small_cloud", "\u1f324\ufe0f", NULL, {NULL} } -, { "sun_with_face", "\u1f31E", NULL, {NULL} } -, { "sunflower", "\u1f33B", NULL, {NULL} } -, { "sunglasses", "\u1f60E", NULL, {"8)", NULL} } -, { "sunny", "\u2600\ufe0f", NULL, {NULL} } -, { "sunrise", "\u1f305", NULL, {NULL} } -, { "sunrise_over_mountains", "\u1f304", NULL, {NULL} } -, { "surfer", "\u1f3c4", NULL, {NULL} } -, { "sushi", "\u1f363", NULL, {NULL} } -, { "suspension_railway", "\u1f69F", NULL, {NULL} } -, { "sweat", "\u1f613", NULL, {NULL} } -, { "sweat_drops", "\u1f4a6", NULL, {NULL} } -, { "sweat_smile", "\u1f605", NULL, {NULL} } -, { "sweet_potato", "\u1f360", NULL, {NULL} } -, { "swimmer", "\u1f3cA", NULL, {NULL} } -, { "symbols", "\u1f523", NULL, {NULL} } -, { "synagogue", "\u1f54D", NULL, {NULL} } -, { "syringe", "\u1f489", NULL, {NULL} } -, { "t-rex", "\u1f996", NULL, {NULL} } -, { "table_tennis_paddle_and_ball", "\u1f3d3", NULL, {NULL} } -, { "taco", "\u1f32E", NULL, {NULL} } -, { "tada", "\u1f389", NULL, {NULL} } -, { "takeout_box", "\u1f961", NULL, {NULL} } -, { "tanabata_tree", "\u1f38B", NULL, {NULL} } -, { "tangerine", "\u1f34A", NULL, {NULL} } -, { "taurus", "\u2649", NULL, {NULL} } -, { "taxi", "\u1f695", NULL, {NULL} } -, { "tea", "\u1f375", NULL, {NULL} } -, { "telephone", "\u260e\ufe0f", NULL, {NULL} } -, { "telephone_receiver", "\u1f4dE", NULL, {NULL} } -, { "telescope", "\u1f52D", NULL, {NULL} } -, { "tennis", "\u1f3bE", NULL, {NULL} } -, { "tent", "\u26fa", NULL, {NULL} } -, { "the_horns", "\u1f918", NULL, {NULL} } -, { "thermometer", "\u1f321\ufe0f", NULL, {NULL} } -, { "thinking_face", "\u1f914", NULL, {NULL} } -, { "third_place_medal", "\u1f949", NULL, {NULL} } -, { "thought_balloon", "\u1f4aD", NULL, {NULL} } -, { "three", "3\ufe0f\u20e3", NULL, {NULL} } -, { "three_button_mouse", "\u1f5b1\ufe0f", NULL, {NULL} } -, { "thumbsdown", "\u1f44E", NULL, {NULL} } -, { "thumbsup", "\u1f44D", NULL, {NULL} } -, { "thunder_cloud_and_rain", "\u26c8\ufe0f", NULL, {NULL} } -, { "ticket", "\u1f3aB", NULL, {NULL} } -, { "tiger", "\u1f42F", NULL, {NULL} } -, { "tiger2", "\u1f405", NULL, {NULL} } -, { "timer_clock", "\u23f2\ufe0f", NULL, {NULL} } -, { "tired_face", "\u1f62B", NULL, {NULL} } -, { "tm", "\u2122\ufe0f", NULL, {NULL} } -, { "toilet", "\u1f6bD", NULL, {NULL} } -, { "tokyo_tower", "\u1f5fC", NULL, {NULL} } -, { "tomato", "\u1f345", NULL, {NULL} } -, { "tongue", "\u1f445", NULL, {NULL} } -, { "top", "\u1f51D", NULL, {NULL} } -, { "tophat", "\u1f3a9", NULL, {NULL} } -, { "tornado", "\u1f32A\ufe0f", NULL, {NULL} } -, { "tornado_cloud", "\u1f32A\ufe0f", NULL, {NULL} } -, { "trackball", "\u1f5b2\ufe0f", NULL, {NULL} } -, { "tractor", "\u1f69C", NULL, {NULL} } -, { "traffic_light", "\u1f6a5", NULL, {NULL} } -, { "train", "\u1f68B", NULL, {NULL} } -, { "train2", "\u1f686", NULL, {NULL} } -, { "tram", "\u1f68A", NULL, {NULL} } -, { "triangular_flag_on_post", "\u1f6a9", NULL, {NULL} } -, { "triangular_ruler", "\u1f4d0", NULL, {NULL} } -, { "trident", "\u1f531", NULL, {NULL} } -, { "triumph", "\u1f624", NULL, {NULL} } -, { "trolleybus", "\u1f68E", NULL, {NULL} } -, { "trophy", "\u1f3c6", NULL, {NULL} } -, { "tropical_drink", "\u1f379", NULL, {NULL} } -, { "tropical_fish", "\u1f420", NULL, {NULL} } -, { "truck", "\u1f69A", NULL, {NULL} } -, { "trumpet", "\u1f3bA", NULL, {NULL} } -, { "tshirt", "\u1f455", NULL, {NULL} } -, { "tulip", "\u1f337", NULL, {NULL} } -, { "tumbler_glass", "\u1f943", NULL, {NULL} } -, { "turkey", "\u1f983", NULL, {NULL} } -, { "turtle", "\u1f422", NULL, {NULL} } -, { "tv", "\u1f4fA", NULL, {NULL} } -, { "twisted_rightwards_arrows", "\u1f500", NULL, {NULL} } -, { "two", "2\ufe0f\u20e3", NULL, {NULL} } -, { "two_hearts", "\u1f495", NULL, {NULL} } -, { "two_men_holding_hands", "\u1f46C", NULL, {NULL} } -, { "two_women_holding_hands", "\u1f46D", NULL, {NULL} } -, { "u5272", "\u1f239", NULL, {NULL} } -, { "u5408", "\u1f234", NULL, {NULL} } -, { "u55b6", "\u1f23A", NULL, {NULL} } -, { "u6307", "\u1f22F", NULL, {NULL} } -, { "u6708", "\u1f237\ufe0f", NULL, {NULL} } -, { "u6709", "\u1f236", NULL, {NULL} } -, { "u6e80", "\u1f235", NULL, {NULL} } -, { "u7121", "\u1f21A", NULL, {NULL} } -, { "u7533", "\u1f238", NULL, {NULL} } -, { "u7981", "\u1f232", NULL, {NULL} } -, { "u7a7a", "\u1f233", NULL, {NULL} } -, { "uk", "\u1f1eC\u1f1e7", NULL, {NULL} } -, { "umbrella", "\u2602\ufe0f", NULL, {NULL} } -, { "umbrella_on_ground", "\u26f1\ufe0f", NULL, {NULL} } -, { "umbrella_with_rain_drops", "\u2614", NULL, {NULL} } -, { "unamused", "\u1f612", ":(", {NULL} } -, { "underage", "\u1f51E", NULL, {NULL} } -, { "unicorn_face", "\u1f984", NULL, {NULL} } -, { "unlock", "\u1f513", NULL, {NULL} } -, { "up", "\u1f199", NULL, {NULL} } -, { "upside_down_face", "\u1f643", NULL, {NULL} } -, { "us", "\u1f1fA\u1f1f8", NULL, {NULL} } -, { "v", "\u270c\ufe0f", NULL, {NULL} } -, { "vampire", "\u1f9dB", NULL, {NULL} } -, { "vertical_traffic_light", "\u1f6a6", NULL, {NULL} } -, { "vhs", "\u1f4fC", NULL, {NULL} } -, { "vibration_mode", "\u1f4f3", NULL, {NULL} } -, { "video_camera", "\u1f4f9", NULL, {NULL} } -, { "video_game", "\u1f3aE", NULL, {NULL} } -, { "violin", "\u1f3bB", NULL, {NULL} } -, { "virgo", "\u264d", NULL, {NULL} } -, { "volcano", "\u1f30B", NULL, {NULL} } -, { "volleyball", "\u1f3d0", NULL, {NULL} } -, { "vs", "\u1f19A", NULL, {NULL} } -, { "walking", "\u1f6b6", NULL, {NULL} } -, { "waning_crescent_moon", "\u1f318", NULL, {NULL} } -, { "waning_gibbous_moon", "\u1f316", NULL, {NULL} } -, { "warning", "\u26a0\ufe0f", NULL, {NULL} } -, { "wastebasket", "\u1f5d1\ufe0f", NULL, {NULL} } -, { "watch", "\u231a", NULL, {NULL} } -, { "water_buffalo", "\u1f403", NULL, {NULL} } -, { "water_polo", "\u1f93D", NULL, {NULL} } -, { "watermelon", "\u1f349", NULL, {NULL} } -, { "wave", "\u1f44B", NULL, {NULL} } -, { "waving_black_flag", "\u1f3f4", NULL, {NULL} } -, { "waving_white_flag", "\u1f3f3\ufe0f", NULL, {NULL} } -, { "wavy_dash", "\u3030\ufe0f", NULL, {NULL} } -, { "waxing_crescent_moon", "\u1f312", NULL, {NULL} } -, { "waxing_gibbous_moon", "\u1f314", NULL, {NULL} } -, { "wc", "\u1f6bE", NULL, {NULL} } -, { "weary", "\u1f629", NULL, {NULL} } -, { "wedding", "\u1f492", NULL, {NULL} } -, { "weight_lifter", "\u1f3cB\ufe0f", NULL, {NULL} } -, { "whale", "\u1f433", NULL, {NULL} } -, { "whale2", "\u1f40B", NULL, {NULL} } -, { "wheel_of_dharma", "\u2638\ufe0f", NULL, {NULL} } -, { "wheelchair", "\u267f", NULL, {NULL} } -, { "white_check_mark", "\u2705", NULL, {NULL} } -, { "white_circle", "\u26aa", NULL, {NULL} } -, { "white_flower", "\u1f4aE", NULL, {NULL} } -, { "white_frowning_face", "\u2639\ufe0f", NULL, {NULL} } -, { "white_large_square", "\u2b1c", NULL, {NULL} } -, { "white_medium_small_square", "\u25fd", NULL, {NULL} } -, { "white_medium_square", "\u25fb\ufe0f", NULL, {NULL} } -, { "white_small_square", "\u25ab\ufe0f", NULL, {NULL} } -, { "white_square_button", "\u1f533", NULL, {NULL} } -, { "wilted_flower", "\u1f940", NULL, {NULL} } -, { "wind_blowing_face", "\u1f32C\ufe0f", NULL, {NULL} } -, { "wind_chime", "\u1f390", NULL, {NULL} } -, { "wine_glass", "\u1f377", NULL, {NULL} } -, { "wink", "\u1f609", ";)", {";)", ";-)", NULL} } -, { "wolf", "\u1f43A", NULL, {NULL} } -, { "woman", "\u1f469", NULL, {NULL} } -, { "woman-biking", "\u1f6b4\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-bouncing-ball", "\u26f9\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-bowing", "\u1f647\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-boy", "\u1f469\u200d\u1f466", NULL, {NULL} } -, { "woman-boy-boy", "\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { "woman-cartwheeling", "\u1f938\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-facepalming", "\u1f926\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-frowning", "\u1f64D\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-gesturing-no", "\u1f645\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-gesturing-ok", "\u1f646\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-getting-haircut", "\u1f487\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-getting-massage", "\u1f486\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-girl", "\u1f469\u200d\u1f467", NULL, {NULL} } -, { "woman-girl-boy", "\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { "woman-girl-girl", "\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { "woman-golfing", "\u1f3cC\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-heart-man", "\u1f469\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } -, { "woman-heart-woman", "\u1f469\u200d\u2764\ufe0f\u200d\u1f469", NULL, {NULL} } -, { "woman-juggling", "\u1f939\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-kiss-man", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } -, { "woman-kiss-woman", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f469", NULL, {NULL} } -, { "woman-lifting-weights", "\u1f3cB\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-mountain-biking", "\u1f6b5\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-playing-handball", "\u1f93E\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-playing-water-polo", "\u1f93D\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-pouting", "\u1f64E\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-raising-hand", "\u1f64B\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-rowing-boat", "\u1f6a3\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-running", "\u1f3c3\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-shrugging", "\u1f937\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-surfing", "\u1f3c4\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-swimming", "\u1f3cA\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-tipping-hand", "\u1f481\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-walking", "\u1f6b6\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-wearing-turban", "\u1f473\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-with-bunny-ears-partying", "\u1f46F\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman-woman-boy", "\u1f469\u200d\u1f469\u200d\u1f466", NULL, {NULL} } -, { "woman-woman-boy-boy", "\u1f469\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { "woman-woman-girl", "\u1f469\u200d\u1f469\u200d\u1f467", NULL, {NULL} } -, { "woman-woman-girl-boy", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { "woman-woman-girl-girl", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { "woman-wrestling", "\u1f93C\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman_climbing", "\u1f9d7\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman_in_lotus_position", "\u1f9d8\u200d\u2640\ufe0f", NULL, {NULL} } -, { "woman_in_steamy_room", "\u1f9d6\u200d\u2640\ufe0f", NULL, {NULL} } -, { "womans_clothes", "\u1f45A", NULL, {NULL} } -, { "womans_hat", "\u1f452", NULL, {NULL} } -, { "womens", "\u1f6bA", NULL, {NULL} } -, { "world_map", "\u1f5fA\ufe0f", NULL, {NULL} } -, { "worried", "\u1f61F", NULL, {NULL} } -, { "wrench", "\u1f527", NULL, {NULL} } -, { "wrestlers", "\u1f93C", NULL, {NULL} } -, { "writing_hand", "\u270d\ufe0f", NULL, {NULL} } -, { "x", "\u274c", NULL, {NULL} } -, { "yellow_heart", "\u1f49B", "<3", {NULL} } -, { "yen", "\u1f4b4", NULL, {NULL} } -, { "yin_yang", "\u262f\ufe0f", NULL, {NULL} } -, { "yum", "\u1f60B", NULL, {NULL} } -, { "zany_face", "\u1f92A", NULL, {NULL} } -, { "zap", "\u26a1", NULL, {NULL} } -, { "zebra_face", "\u1f993", NULL, {NULL} } -, { "zero", "0\ufe0f\u20e3", NULL, {NULL} } -, { "zipper_mouth_face", "\u1f910", NULL, {NULL} } -, { "zombie", "\u1f9dF", NULL, {NULL} } -, { "zzz", "\u1f4a4", NULL, {NULL} } +{ { ":+1:", "\u1f44D", NULL, {NULL} } +, { ":-1:", "\u1f44E", NULL, {NULL} } +, { ":100:", "\u1f4aF", NULL, {NULL} } +, { ":1234:", "\u1f522", NULL, {NULL} } +, { ":8ball:", "\u1f3b1", NULL, {NULL} } +, { ":a:", "\u1f170\ufe0f", NULL, {NULL} } +, { ":ab:", "\u1f18E", NULL, {NULL} } +, { ":abc:", "\u1f524", NULL, {NULL} } +, { ":abcd:", "\u1f521", NULL, {NULL} } +, { ":accept:", "\u1f251", NULL, {NULL} } +, { ":admission_tickets:", "\u1f39F\ufe0f", NULL, {NULL} } +, { ":adult:", "\u1f9d1", NULL, {NULL} } +, { ":aerial_tramway:", "\u1f6a1", NULL, {NULL} } +, { ":airplane:", "\u2708\ufe0f", NULL, {NULL} } +, { ":airplane_arriving:", "\u1f6eC", NULL, {NULL} } +, { ":airplane_departure:", "\u1f6eB", NULL, {NULL} } +, { ":alarm_clock:", "\u23f0", NULL, {NULL} } +, { ":alembic:", "\u2697\ufe0f", NULL, {NULL} } +, { ":alien:", "\u1f47D", NULL, {NULL} } +, { ":ambulance:", "\u1f691", NULL, {NULL} } +, { ":amphora:", "\u1f3fA", NULL, {NULL} } +, { ":anchor:", "\u2693", NULL, {NULL} } +, { ":angel:", "\u1f47C", NULL, {NULL} } +, { ":anger:", "\u1f4a2", NULL, {NULL} } +, { ":angry:", "\u1f620", NULL, {">:(", ">:-(", NULL} } +, { ":anguished:", "\u1f627", NULL, {"D:", NULL} } +, { ":ant:", "\u1f41C", NULL, {NULL} } +, { ":apple:", "\u1f34E", NULL, {NULL} } +, { ":aquarius:", "\u2652", NULL, {NULL} } +, { ":aries:", "\u2648", NULL, {NULL} } +, { ":arrow_backward:", "\u25c0\ufe0f", NULL, {NULL} } +, { ":arrow_double_down:", "\u23ec", NULL, {NULL} } +, { ":arrow_double_up:", "\u23eb", NULL, {NULL} } +, { ":arrow_down:", "\u2b07\ufe0f", NULL, {NULL} } +, { ":arrow_down_small:", "\u1f53D", NULL, {NULL} } +, { ":arrow_forward:", "\u25b6\ufe0f", NULL, {NULL} } +, { ":arrow_heading_down:", "\u2935\ufe0f", NULL, {NULL} } +, { ":arrow_heading_up:", "\u2934\ufe0f", NULL, {NULL} } +, { ":arrow_left:", "\u2b05\ufe0f", NULL, {NULL} } +, { ":arrow_lower_left:", "\u2199\ufe0f", NULL, {NULL} } +, { ":arrow_lower_right:", "\u2198\ufe0f", NULL, {NULL} } +, { ":arrow_right:", "\u27a1\ufe0f", NULL, {NULL} } +, { ":arrow_right_hook:", "\u21aa\ufe0f", NULL, {NULL} } +, { ":arrow_up:", "\u2b06\ufe0f", NULL, {NULL} } +, { ":arrow_up_down:", "\u2195\ufe0f", NULL, {NULL} } +, { ":arrow_up_small:", "\u1f53C", NULL, {NULL} } +, { ":arrow_upper_left:", "\u2196\ufe0f", NULL, {NULL} } +, { ":arrow_upper_right:", "\u2197\ufe0f", NULL, {NULL} } +, { ":arrows_clockwise:", "\u1f503", NULL, {NULL} } +, { ":arrows_counterclockwise:", "\u1f504", NULL, {NULL} } +, { ":art:", "\u1f3a8", NULL, {NULL} } +, { ":articulated_lorry:", "\u1f69B", NULL, {NULL} } +, { ":astonished:", "\u1f632", NULL, {NULL} } +, { ":athletic_shoe:", "\u1f45F", NULL, {NULL} } +, { ":atm:", "\u1f3e7", NULL, {NULL} } +, { ":atom_symbol:", "\u269b\ufe0f", NULL, {NULL} } +, { ":avocado:", "\u1f951", NULL, {NULL} } +, { ":b:", "\u1f171\ufe0f", NULL, {NULL} } +, { ":baby:", "\u1f476", NULL, {NULL} } +, { ":baby_bottle:", "\u1f37C", NULL, {NULL} } +, { ":baby_chick:", "\u1f424", NULL, {NULL} } +, { ":baby_symbol:", "\u1f6bC", NULL, {NULL} } +, { ":back:", "\u1f519", NULL, {NULL} } +, { ":bacon:", "\u1f953", NULL, {NULL} } +, { ":badminton_racquet_and_shuttlecock:", "\u1f3f8", NULL, {NULL} } +, { ":baggage_claim:", "\u1f6c4", NULL, {NULL} } +, { ":baguette_bread:", "\u1f956", NULL, {NULL} } +, { ":balloon:", "\u1f388", NULL, {NULL} } +, { ":ballot_box_with_ballot:", "\u1f5f3\ufe0f", NULL, {NULL} } +, { ":ballot_box_with_check:", "\u2611\ufe0f", NULL, {NULL} } +, { ":bamboo:", "\u1f38D", NULL, {NULL} } +, { ":banana:", "\u1f34C", NULL, {NULL} } +, { ":bangbang:", "\u203c\ufe0f", NULL, {NULL} } +, { ":bank:", "\u1f3e6", NULL, {NULL} } +, { ":bar_chart:", "\u1f4cA", NULL, {NULL} } +, { ":barber:", "\u1f488", NULL, {NULL} } +, { ":barely_sunny:", "\u1f325\ufe0f", NULL, {NULL} } +, { ":baseball:", "\u26be", NULL, {NULL} } +, { ":basketball:", "\u1f3c0", NULL, {NULL} } +, { ":bat:", "\u1f987", NULL, {NULL} } +, { ":bath:", "\u1f6c0", NULL, {NULL} } +, { ":bathtub:", "\u1f6c1", NULL, {NULL} } +, { ":battery:", "\u1f50B", NULL, {NULL} } +, { ":beach_with_umbrella:", "\u1f3d6\ufe0f", NULL, {NULL} } +, { ":bear:", "\u1f43B", NULL, {NULL} } +, { ":bearded_person:", "\u1f9d4", NULL, {NULL} } +, { ":bed:", "\u1f6cF\ufe0f", NULL, {NULL} } +, { ":bee:", "\u1f41D", NULL, {NULL} } +, { ":beer:", "\u1f37A", NULL, {NULL} } +, { ":beers:", "\u1f37B", NULL, {NULL} } +, { ":beetle:", "\u1f41E", NULL, {NULL} } +, { ":beginner:", "\u1f530", NULL, {NULL} } +, { ":bell:", "\u1f514", NULL, {NULL} } +, { ":bellhop_bell:", "\u1f6cE\ufe0f", NULL, {NULL} } +, { ":bento:", "\u1f371", NULL, {NULL} } +, { ":bicyclist:", "\u1f6b4", NULL, {NULL} } +, { ":bike:", "\u1f6b2", NULL, {NULL} } +, { ":bikini:", "\u1f459", NULL, {NULL} } +, { ":billed_cap:", "\u1f9e2", NULL, {NULL} } +, { ":biohazard_sign:", "\u2623\ufe0f", NULL, {NULL} } +, { ":bird:", "\u1f426", NULL, {NULL} } +, { ":birthday:", "\u1f382", NULL, {NULL} } +, { ":black_circle:", "\u26ab", NULL, {NULL} } +, { ":black_circle_for_record:", "\u23fa\ufe0f", NULL, {NULL} } +, { ":black_heart:", "\u1f5a4", NULL, {NULL} } +, { ":black_joker:", "\u1f0cF", NULL, {NULL} } +, { ":black_large_square:", "\u2b1b", NULL, {NULL} } +, { ":black_left_pointing_double_triangle_with_vertical_bar:", "\u23ee\ufe0f", NULL, {NULL} } +, { ":black_medium_small_square:", "\u25fe", NULL, {NULL} } +, { ":black_medium_square:", "\u25fc\ufe0f", NULL, {NULL} } +, { ":black_nib:", "\u2712\ufe0f", NULL, {NULL} } +, { ":black_right_pointing_double_triangle_with_vertical_bar:", "\u23ed\ufe0f", NULL, {NULL} } +, { ":black_right_pointing_triangle_with_double_vertical_bar:", "\u23ef\ufe0f", NULL, {NULL} } +, { ":black_small_square:", "\u25aa\ufe0f", NULL, {NULL} } +, { ":black_square_button:", "\u1f532", NULL, {NULL} } +, { ":black_square_for_stop:", "\u23f9\ufe0f", NULL, {NULL} } +, { ":blond-haired-man:", "\u1f471\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":blond-haired-woman:", "\u1f471\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":blossom:", "\u1f33C", NULL, {NULL} } +, { ":blowfish:", "\u1f421", NULL, {NULL} } +, { ":blue_book:", "\u1f4d8", NULL, {NULL} } +, { ":blue_car:", "\u1f699", NULL, {NULL} } +, { ":blue_heart:", "\u1f499", "<3", {NULL} } +, { ":blush:", "\u1f60A", ":)", {NULL} } +, { ":boar:", "\u1f417", NULL, {NULL} } +, { ":boat:", "\u26f5", NULL, {NULL} } +, { ":bomb:", "\u1f4a3", NULL, {NULL} } +, { ":book:", "\u1f4d6", NULL, {NULL} } +, { ":bookmark:", "\u1f516", NULL, {NULL} } +, { ":bookmark_tabs:", "\u1f4d1", NULL, {NULL} } +, { ":books:", "\u1f4dA", NULL, {NULL} } +, { ":boom:", "\u1f4a5", NULL, {NULL} } +, { ":boot:", "\u1f462", NULL, {NULL} } +, { ":bouquet:", "\u1f490", NULL, {NULL} } +, { ":bow:", "\u1f647", NULL, {NULL} } +, { ":bow_and_arrow:", "\u1f3f9", NULL, {NULL} } +, { ":bowl_with_spoon:", "\u1f963", NULL, {NULL} } +, { ":bowling:", "\u1f3b3", NULL, {NULL} } +, { ":boxing_glove:", "\u1f94A", NULL, {NULL} } +, { ":boy:", "\u1f466", NULL, {NULL} } +, { ":brain:", "\u1f9e0", NULL, {NULL} } +, { ":bread:", "\u1f35E", NULL, {NULL} } +, { ":breast-feeding:", "\u1f931", NULL, {NULL} } +, { ":bride_with_veil:", "\u1f470", NULL, {NULL} } +, { ":bridge_at_night:", "\u1f309", NULL, {NULL} } +, { ":briefcase:", "\u1f4bC", NULL, {NULL} } +, { ":broccoli:", "\u1f966", NULL, {NULL} } +, { ":broken_heart:", "\u1f494", "", ":->", NULL} } +, { ":leaves:", "\u1f343", NULL, {NULL} } +, { ":ledger:", "\u1f4d2", NULL, {NULL} } +, { ":left-facing_fist:", "\u1f91B", NULL, {NULL} } +, { ":left_luggage:", "\u1f6c5", NULL, {NULL} } +, { ":left_right_arrow:", "\u2194\ufe0f", NULL, {NULL} } +, { ":left_speech_bubble:", "\u1f5e8\ufe0f", NULL, {NULL} } +, { ":leftwards_arrow_with_hook:", "\u21a9\ufe0f", NULL, {NULL} } +, { ":lemon:", "\u1f34B", NULL, {NULL} } +, { ":leo:", "\u264c", NULL, {NULL} } +, { ":leopard:", "\u1f406", NULL, {NULL} } +, { ":level_slider:", "\u1f39A\ufe0f", NULL, {NULL} } +, { ":libra:", "\u264e", NULL, {NULL} } +, { ":light_rail:", "\u1f688", NULL, {NULL} } +, { ":lightning:", "\u1f329\ufe0f", NULL, {NULL} } +, { ":lightning_cloud:", "\u1f329\ufe0f", NULL, {NULL} } +, { ":link:", "\u1f517", NULL, {NULL} } +, { ":linked_paperclips:", "\u1f587\ufe0f", NULL, {NULL} } +, { ":lion_face:", "\u1f981", NULL, {NULL} } +, { ":lips:", "\u1f444", NULL, {NULL} } +, { ":lipstick:", "\u1f484", NULL, {NULL} } +, { ":lizard:", "\u1f98E", NULL, {NULL} } +, { ":lock:", "\u1f512", NULL, {NULL} } +, { ":lock_with_ink_pen:", "\u1f50F", NULL, {NULL} } +, { ":lollipop:", "\u1f36D", NULL, {NULL} } +, { ":loop:", "\u27bf", NULL, {NULL} } +, { ":loud_sound:", "\u1f50A", NULL, {NULL} } +, { ":loudspeaker:", "\u1f4e2", NULL, {NULL} } +, { ":love_hotel:", "\u1f3e9", NULL, {NULL} } +, { ":love_letter:", "\u1f48C", NULL, {NULL} } +, { ":low_brightness:", "\u1f505", NULL, {NULL} } +, { ":lower_left_ballpoint_pen:", "\u1f58A\ufe0f", NULL, {NULL} } +, { ":lower_left_crayon:", "\u1f58D\ufe0f", NULL, {NULL} } +, { ":lower_left_fountain_pen:", "\u1f58B\ufe0f", NULL, {NULL} } +, { ":lower_left_paintbrush:", "\u1f58C\ufe0f", NULL, {NULL} } +, { ":lying_face:", "\u1f925", NULL, {NULL} } +, { ":m:", "\u24c2\ufe0f", NULL, {NULL} } +, { ":mag:", "\u1f50D", NULL, {NULL} } +, { ":mag_right:", "\u1f50E", NULL, {NULL} } +, { ":mage:", "\u1f9d9", NULL, {NULL} } +, { ":mahjong:", "\u1f004", NULL, {NULL} } +, { ":mailbox:", "\u1f4eB", NULL, {NULL} } +, { ":mailbox_closed:", "\u1f4eA", NULL, {NULL} } +, { ":mailbox_with_mail:", "\u1f4eC", NULL, {NULL} } +, { ":mailbox_with_no_mail:", "\u1f4eD", NULL, {NULL} } +, { ":male-artist:", "\u1f468\u200d\u1f3a8", NULL, {NULL} } +, { ":male-astronaut:", "\u1f468\u200d\u1f680", NULL, {NULL} } +, { ":male-construction-worker:", "\u1f477\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male-cook:", "\u1f468\u200d\u1f373", NULL, {NULL} } +, { ":male-detective:", "\u1f575\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male-doctor:", "\u1f468\u200d\u2695\ufe0f", NULL, {NULL} } +, { ":male-factory-worker:", "\u1f468\u200d\u1f3eD", NULL, {NULL} } +, { ":male-farmer:", "\u1f468\u200d\u1f33E", NULL, {NULL} } +, { ":male-firefighter:", "\u1f468\u200d\u1f692", NULL, {NULL} } +, { ":male-guard:", "\u1f482\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male-judge:", "\u1f468\u200d\u2696\ufe0f", NULL, {NULL} } +, { ":male-mechanic:", "\u1f468\u200d\u1f527", NULL, {NULL} } +, { ":male-office-worker:", "\u1f468\u200d\u1f4bC", NULL, {NULL} } +, { ":male-pilot:", "\u1f468\u200d\u2708\ufe0f", NULL, {NULL} } +, { ":male-police-officer:", "\u1f46E\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male-scientist:", "\u1f468\u200d\u1f52C", NULL, {NULL} } +, { ":male-singer:", "\u1f468\u200d\u1f3a4", NULL, {NULL} } +, { ":male-student:", "\u1f468\u200d\u1f393", NULL, {NULL} } +, { ":male-teacher:", "\u1f468\u200d\u1f3eB", NULL, {NULL} } +, { ":male-technologist:", "\u1f468\u200d\u1f4bB", NULL, {NULL} } +, { ":male_elf:", "\u1f9dD\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male_fairy:", "\u1f9dA\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male_genie:", "\u1f9dE\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male_mage:", "\u1f9d9\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male_sign:", "\u2642\ufe0f", NULL, {NULL} } +, { ":male_vampire:", "\u1f9dB\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":male_zombie:", "\u1f9dF\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man:", "\u1f468", NULL, {NULL} } +, { ":man-biking:", "\u1f6b4\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-bouncing-ball:", "\u26f9\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-bowing:", "\u1f647\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-boy:", "\u1f468\u200d\u1f466", NULL, {NULL} } +, { ":man-boy-boy:", "\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { ":man-cartwheeling:", "\u1f938\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-facepalming:", "\u1f926\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-frowning:", "\u1f64D\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-gesturing-no:", "\u1f645\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-gesturing-ok:", "\u1f646\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-getting-haircut:", "\u1f487\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-getting-massage:", "\u1f486\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-girl:", "\u1f468\u200d\u1f467", NULL, {NULL} } +, { ":man-girl-boy:", "\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { ":man-girl-girl:", "\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { ":man-golfing:", "\u1f3cC\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-heart-man:", "\u1f468\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } +, { ":man-juggling:", "\u1f939\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-kiss-man:", "\u1f468\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } +, { ":man-lifting-weights:", "\u1f3cB\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-man-boy:", "\u1f468\u200d\u1f468\u200d\u1f466", NULL, {NULL} } +, { ":man-man-boy-boy:", "\u1f468\u200d\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { ":man-man-girl:", "\u1f468\u200d\u1f468\u200d\u1f467", NULL, {NULL} } +, { ":man-man-girl-boy:", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { ":man-man-girl-girl:", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { ":man-mountain-biking:", "\u1f6b5\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-playing-handball:", "\u1f93E\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-playing-water-polo:", "\u1f93D\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-pouting:", "\u1f64E\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-raising-hand:", "\u1f64B\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-rowing-boat:", "\u1f6a3\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-running:", "\u1f3c3\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-shrugging:", "\u1f937\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-surfing:", "\u1f3c4\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-swimming:", "\u1f3cA\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-tipping-hand:", "\u1f481\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-walking:", "\u1f6b6\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-wearing-turban:", "\u1f473\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-with-bunny-ears-partying:", "\u1f46F\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man-woman-boy:", "\u1f468\u200d\u1f469\u200d\u1f466", NULL, {NULL} } +, { ":man-woman-boy:", "\u1f46A", NULL, {NULL} } +, { ":man-woman-boy-boy:", "\u1f468\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { ":man-woman-girl:", "\u1f468\u200d\u1f469\u200d\u1f467", NULL, {NULL} } +, { ":man-woman-girl-boy:", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { ":man-woman-girl-girl:", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { ":man-wrestling:", "\u1f93C\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man_and_woman_holding_hands:", "\u1f46B", NULL, {NULL} } +, { ":man_climbing:", "\u1f9d7\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man_dancing:", "\u1f57A", NULL, {NULL} } +, { ":man_in_business_suit_levitating:", "\u1f574\ufe0f", NULL, {NULL} } +, { ":man_in_lotus_position:", "\u1f9d8\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man_in_steamy_room:", "\u1f9d6\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":man_in_tuxedo:", "\u1f935", NULL, {NULL} } +, { ":man_with_gua_pi_mao:", "\u1f472", NULL, {NULL} } +, { ":man_with_turban:", "\u1f473", NULL, {NULL} } +, { ":mans_shoe:", "\u1f45E", NULL, {NULL} } +, { ":mantelpiece_clock:", "\u1f570\ufe0f", NULL, {NULL} } +, { ":maple_leaf:", "\u1f341", NULL, {NULL} } +, { ":martial_arts_uniform:", "\u1f94B", NULL, {NULL} } +, { ":mask:", "\u1f637", NULL, {NULL} } +, { ":massage:", "\u1f486", NULL, {NULL} } +, { ":meat_on_bone:", "\u1f356", NULL, {NULL} } +, { ":medal:", "\u1f396\ufe0f", NULL, {NULL} } +, { ":medical_symbol:", "\u2695\ufe0f", NULL, {NULL} } +, { ":mega:", "\u1f4e3", NULL, {NULL} } +, { ":melon:", "\u1f348", NULL, {NULL} } +, { ":memo:", "\u1f4dD", NULL, {NULL} } +, { ":menorah_with_nine_branches:", "\u1f54E", NULL, {NULL} } +, { ":mens:", "\u1f6b9", NULL, {NULL} } +, { ":mermaid:", "\u1f9dC\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":merman:", "\u1f9dC\u200d\u2642\ufe0f", NULL, {NULL} } +, { ":merperson:", "\u1f9dC", NULL, {NULL} } +, { ":metro:", "\u1f687", NULL, {NULL} } +, { ":microphone:", "\u1f3a4", NULL, {NULL} } +, { ":microscope:", "\u1f52C", NULL, {NULL} } +, { ":middle_finger:", "\u1f595", NULL, {NULL} } +, { ":milky_way:", "\u1f30C", NULL, {NULL} } +, { ":minibus:", "\u1f690", NULL, {NULL} } +, { ":minidisc:", "\u1f4bD", NULL, {NULL} } +, { ":mobile_phone_off:", "\u1f4f4", NULL, {NULL} } +, { ":money_mouth_face:", "\u1f911", NULL, {NULL} } +, { ":money_with_wings:", "\u1f4b8", NULL, {NULL} } +, { ":moneybag:", "\u1f4b0", NULL, {NULL} } +, { ":monkey:", "\u1f412", NULL, {NULL} } +, { ":monkey_face:", "\u1f435", NULL, {":o)", NULL} } +, { ":monorail:", "\u1f69D", NULL, {NULL} } +, { ":moon:", "\u1f314", NULL, {NULL} } +, { ":mortar_board:", "\u1f393", NULL, {NULL} } +, { ":mosque:", "\u1f54C", NULL, {NULL} } +, { ":mostly_sunny:", "\u1f324\ufe0f", NULL, {NULL} } +, { ":mother_christmas:", "\u1f936", NULL, {NULL} } +, { ":motor_boat:", "\u1f6e5\ufe0f", NULL, {NULL} } +, { ":motor_scooter:", "\u1f6f5", NULL, {NULL} } +, { ":motorway:", "\u1f6e3\ufe0f", NULL, {NULL} } +, { ":mount_fuji:", "\u1f5fB", NULL, {NULL} } +, { ":mountain:", "\u26f0\ufe0f", NULL, {NULL} } +, { ":mountain_bicyclist:", "\u1f6b5", NULL, {NULL} } +, { ":mountain_cableway:", "\u1f6a0", NULL, {NULL} } +, { ":mountain_railway:", "\u1f69E", NULL, {NULL} } +, { ":mouse:", "\u1f42D", NULL, {NULL} } +, { ":mouse2:", "\u1f401", NULL, {NULL} } +, { ":movie_camera:", "\u1f3a5", NULL, {NULL} } +, { ":moyai:", "\u1f5fF", NULL, {NULL} } +, { ":mrs_claus:", "\u1f936", NULL, {NULL} } +, { ":muscle:", "\u1f4aA", NULL, {NULL} } +, { ":mushroom:", "\u1f344", NULL, {NULL} } +, { ":musical_keyboard:", "\u1f3b9", NULL, {NULL} } +, { ":musical_note:", "\u1f3b5", NULL, {NULL} } +, { ":musical_score:", "\u1f3bC", NULL, {NULL} } +, { ":mute:", "\u1f507", NULL, {NULL} } +, { ":nail_care:", "\u1f485", NULL, {NULL} } +, { ":name_badge:", "\u1f4dB", NULL, {NULL} } +, { ":national_park:", "\u1f3dE\ufe0f", NULL, {NULL} } +, { ":nauseated_face:", "\u1f922", NULL, {NULL} } +, { ":necktie:", "\u1f454", NULL, {NULL} } +, { ":negative_squared_cross_mark:", "\u274e", NULL, {NULL} } +, { ":nerd_face:", "\u1f913", NULL, {NULL} } +, { ":neutral_face:", "\u1f610", NULL, {":|", ":-|", NULL} } +, { ":new:", "\u1f195", NULL, {NULL} } +, { ":new_moon:", "\u1f311", NULL, {NULL} } +, { ":new_moon_with_face:", "\u1f31A", NULL, {NULL} } +, { ":newspaper:", "\u1f4f0", NULL, {NULL} } +, { ":ng:", "\u1f196", NULL, {NULL} } +, { ":night_with_stars:", "\u1f303", NULL, {NULL} } +, { ":nine:", "9\ufe0f\u20e3", NULL, {NULL} } +, { ":no_bell:", "\u1f515", NULL, {NULL} } +, { ":no_bicycles:", "\u1f6b3", NULL, {NULL} } +, { ":no_entry:", "\u26d4", NULL, {NULL} } +, { ":no_entry_sign:", "\u1f6aB", NULL, {NULL} } +, { ":no_good:", "\u1f645", NULL, {NULL} } +, { ":no_mobile_phones:", "\u1f4f5", NULL, {NULL} } +, { ":no_mouth:", "\u1f636", NULL, {NULL} } +, { ":no_pedestrians:", "\u1f6b7", NULL, {NULL} } +, { ":no_smoking:", "\u1f6aD", NULL, {NULL} } +, { ":non-potable_water:", "\u1f6b1", NULL, {NULL} } +, { ":nose:", "\u1f443", NULL, {NULL} } +, { ":notebook:", "\u1f4d3", NULL, {NULL} } +, { ":notebook_with_decorative_cover:", "\u1f4d4", NULL, {NULL} } +, { ":notes:", "\u1f3b6", NULL, {NULL} } +, { ":nut_and_bolt:", "\u1f529", NULL, {NULL} } +, { ":o:", "\u2b55", NULL, {NULL} } +, { ":o2:", "\u1f17E\ufe0f", NULL, {NULL} } +, { ":ocean:", "\u1f30A", NULL, {NULL} } +, { ":octagonal_sign:", "\u1f6d1", NULL, {NULL} } +, { ":octopus:", "\u1f419", NULL, {NULL} } +, { ":oden:", "\u1f362", NULL, {NULL} } +, { ":office:", "\u1f3e2", NULL, {NULL} } +, { ":oil_drum:", "\u1f6e2\ufe0f", NULL, {NULL} } +, { ":ok:", "\u1f197", NULL, {NULL} } +, { ":ok_hand:", "\u1f44C", NULL, {NULL} } +, { ":ok_woman:", "\u1f646", NULL, {NULL} } +, { ":old_key:", "\u1f5dD\ufe0f", NULL, {NULL} } +, { ":older_adult:", "\u1f9d3", NULL, {NULL} } +, { ":older_man:", "\u1f474", NULL, {NULL} } +, { ":older_woman:", "\u1f475", NULL, {NULL} } +, { ":om_symbol:", "\u1f549\ufe0f", NULL, {NULL} } +, { ":on:", "\u1f51B", NULL, {NULL} } +, { ":oncoming_automobile:", "\u1f698", NULL, {NULL} } +, { ":oncoming_bus:", "\u1f68D", NULL, {NULL} } +, { ":oncoming_police_car:", "\u1f694", NULL, {NULL} } +, { ":oncoming_taxi:", "\u1f696", NULL, {NULL} } +, { ":one:", "1\ufe0f\u20e3", NULL, {NULL} } +, { ":open_book:", "\u1f4d6", NULL, {NULL} } +, { ":open_file_folder:", "\u1f4c2", NULL, {NULL} } +, { ":open_hands:", "\u1f450", NULL, {NULL} } +, { ":open_mouth:", "\u1f62E", NULL, {":o", ":-o", ":O", ":-O", NULL} } +, { ":ophiuchus:", "\u26ce", NULL, {NULL} } +, { ":orange_book:", "\u1f4d9", NULL, {NULL} } +, { ":orange_heart:", "\u1f9e1", NULL, {NULL} } +, { ":orthodox_cross:", "\u2626\ufe0f", NULL, {NULL} } +, { ":outbox_tray:", "\u1f4e4", NULL, {NULL} } +, { ":owl:", "\u1f989", NULL, {NULL} } +, { ":ox:", "\u1f402", NULL, {NULL} } +, { ":package:", "\u1f4e6", NULL, {NULL} } +, { ":page_facing_up:", "\u1f4c4", NULL, {NULL} } +, { ":page_with_curl:", "\u1f4c3", NULL, {NULL} } +, { ":pager:", "\u1f4dF", NULL, {NULL} } +, { ":palm_tree:", "\u1f334", NULL, {NULL} } +, { ":palms_up_together:", "\u1f932", NULL, {NULL} } +, { ":pancakes:", "\u1f95E", NULL, {NULL} } +, { ":panda_face:", "\u1f43C", NULL, {NULL} } +, { ":paperclip:", "\u1f4cE", NULL, {NULL} } +, { ":parking:", "\u1f17F\ufe0f", NULL, {NULL} } +, { ":part_alternation_mark:", "\u303d\ufe0f", NULL, {NULL} } +, { ":partly_sunny:", "\u26c5", NULL, {NULL} } +, { ":partly_sunny_rain:", "\u1f326\ufe0f", NULL, {NULL} } +, { ":passenger_ship:", "\u1f6f3\ufe0f", NULL, {NULL} } +, { ":passport_control:", "\u1f6c2", NULL, {NULL} } +, { ":paw_prints:", "\u1f43E", NULL, {NULL} } +, { ":peace_symbol:", "\u262e\ufe0f", NULL, {NULL} } +, { ":peach:", "\u1f351", NULL, {NULL} } +, { ":peanuts:", "\u1f95C", NULL, {NULL} } +, { ":pear:", "\u1f350", NULL, {NULL} } +, { ":pencil:", "\u1f4dD", NULL, {NULL} } +, { ":pencil2:", "\u270f\ufe0f", NULL, {NULL} } +, { ":penguin:", "\u1f427", NULL, {NULL} } +, { ":pensive:", "\u1f614", NULL, {NULL} } +, { ":performing_arts:", "\u1f3aD", NULL, {NULL} } +, { ":persevere:", "\u1f623", NULL, {NULL} } +, { ":person_climbing:", "\u1f9d7", NULL, {NULL} } +, { ":person_doing_cartwheel:", "\u1f938", NULL, {NULL} } +, { ":person_frowning:", "\u1f64D", NULL, {NULL} } +, { ":person_in_lotus_position:", "\u1f9d8", NULL, {NULL} } +, { ":person_in_steamy_room:", "\u1f9d6", NULL, {NULL} } +, { ":person_with_ball:", "\u26f9\ufe0f", NULL, {NULL} } +, { ":person_with_blond_hair:", "\u1f471", NULL, {NULL} } +, { ":person_with_headscarf:", "\u1f9d5", NULL, {NULL} } +, { ":person_with_pouting_face:", "\u1f64E", NULL, {NULL} } +, { ":phone:", "\u260e\ufe0f", NULL, {NULL} } +, { ":pick:", "\u26cf\ufe0f", NULL, {NULL} } +, { ":pie:", "\u1f967", NULL, {NULL} } +, { ":pig:", "\u1f437", NULL, {NULL} } +, { ":pig2:", "\u1f416", NULL, {NULL} } +, { ":pig_nose:", "\u1f43D", NULL, {NULL} } +, { ":pill:", "\u1f48A", NULL, {NULL} } +, { ":pineapple:", "\u1f34D", NULL, {NULL} } +, { ":pisces:", "\u2653", NULL, {NULL} } +, { ":pizza:", "\u1f355", NULL, {NULL} } +, { ":place_of_worship:", "\u1f6d0", NULL, {NULL} } +, { ":point_down:", "\u1f447", NULL, {NULL} } +, { ":point_left:", "\u1f448", NULL, {NULL} } +, { ":point_right:", "\u1f449", NULL, {NULL} } +, { ":point_up:", "\u261d\ufe0f", NULL, {NULL} } +, { ":point_up_2:", "\u1f446", NULL, {NULL} } +, { ":police_car:", "\u1f693", NULL, {NULL} } +, { ":poodle:", "\u1f429", NULL, {NULL} } +, { ":poop:", "\u1f4a9", NULL, {NULL} } +, { ":popcorn:", "\u1f37F", NULL, {NULL} } +, { ":post_office:", "\u1f3e3", NULL, {NULL} } +, { ":postal_horn:", "\u1f4eF", NULL, {NULL} } +, { ":postbox:", "\u1f4eE", NULL, {NULL} } +, { ":potable_water:", "\u1f6b0", NULL, {NULL} } +, { ":potato:", "\u1f954", NULL, {NULL} } +, { ":pouch:", "\u1f45D", NULL, {NULL} } +, { ":poultry_leg:", "\u1f357", NULL, {NULL} } +, { ":pound:", "\u1f4b7", NULL, {NULL} } +, { ":pouting_cat:", "\u1f63E", NULL, {NULL} } +, { ":pray:", "\u1f64F", NULL, {NULL} } +, { ":prayer_beads:", "\u1f4fF", NULL, {NULL} } +, { ":pregnant_woman:", "\u1f930", NULL, {NULL} } +, { ":pretzel:", "\u1f968", NULL, {NULL} } +, { ":prince:", "\u1f934", NULL, {NULL} } +, { ":princess:", "\u1f478", NULL, {NULL} } +, { ":printer:", "\u1f5a8\ufe0f", NULL, {NULL} } +, { ":punch:", "\u1f44A", NULL, {NULL} } +, { ":purple_heart:", "\u1f49C", "<3", {NULL} } +, { ":purse:", "\u1f45B", NULL, {NULL} } +, { ":pushpin:", "\u1f4cC", NULL, {NULL} } +, { ":put_litter_in_its_place:", "\u1f6aE", NULL, {NULL} } +, { ":question:", "\u2753", NULL, {NULL} } +, { ":rabbit:", "\u1f430", NULL, {NULL} } +, { ":rabbit2:", "\u1f407", NULL, {NULL} } +, { ":racehorse:", "\u1f40E", NULL, {NULL} } +, { ":racing_car:", "\u1f3cE\ufe0f", NULL, {NULL} } +, { ":racing_motorcycle:", "\u1f3cD\ufe0f", NULL, {NULL} } +, { ":radio:", "\u1f4fB", NULL, {NULL} } +, { ":radio_button:", "\u1f518", NULL, {NULL} } +, { ":radioactive_sign:", "\u2622\ufe0f", NULL, {NULL} } +, { ":rage:", "\u1f621", NULL, {NULL} } +, { ":railway_car:", "\u1f683", NULL, {NULL} } +, { ":railway_track:", "\u1f6e4\ufe0f", NULL, {NULL} } +, { ":rain_cloud:", "\u1f327\ufe0f", NULL, {NULL} } +, { ":rainbow:", "\u1f308", NULL, {NULL} } +, { ":rainbow-flag:", "\u1f3f3\ufe0f\u200d\u1f308", NULL, {NULL} } +, { ":raised_back_of_hand:", "\u1f91A", NULL, {NULL} } +, { ":raised_hand:", "\u270b", NULL, {NULL} } +, { ":raised_hand_with_fingers_splayed:", "\u1f590\ufe0f", NULL, {NULL} } +, { ":raised_hands:", "\u1f64C", NULL, {NULL} } +, { ":raising_hand:", "\u1f64B", NULL, {NULL} } +, { ":ram:", "\u1f40F", NULL, {NULL} } +, { ":ramen:", "\u1f35C", NULL, {NULL} } +, { ":rat:", "\u1f400", NULL, {NULL} } +, { ":recycle:", "\u267b\ufe0f", NULL, {NULL} } +, { ":red_car:", "\u1f697", NULL, {NULL} } +, { ":red_circle:", "\u1f534", NULL, {NULL} } +, { ":registered:", "\u00ae\ufe0f", NULL, {NULL} } +, { ":relaxed:", "\u263a\ufe0f", NULL, {NULL} } +, { ":relieved:", "\u1f60C", NULL, {NULL} } +, { ":reminder_ribbon:", "\u1f397\ufe0f", NULL, {NULL} } +, { ":repeat:", "\u1f501", NULL, {NULL} } +, { ":repeat_one:", "\u1f502", NULL, {NULL} } +, { ":restroom:", "\u1f6bB", NULL, {NULL} } +, { ":reversed_hand_with_middle_finger_extended:", "\u1f595", NULL, {NULL} } +, { ":revolving_hearts:", "\u1f49E", NULL, {NULL} } +, { ":rewind:", "\u23ea", NULL, {NULL} } +, { ":rhinoceros:", "\u1f98F", NULL, {NULL} } +, { ":ribbon:", "\u1f380", NULL, {NULL} } +, { ":rice:", "\u1f35A", NULL, {NULL} } +, { ":rice_ball:", "\u1f359", NULL, {NULL} } +, { ":rice_cracker:", "\u1f358", NULL, {NULL} } +, { ":rice_scene:", "\u1f391", NULL, {NULL} } +, { ":right-facing_fist:", "\u1f91C", NULL, {NULL} } +, { ":right_anger_bubble:", "\u1f5eF\ufe0f", NULL, {NULL} } +, { ":ring:", "\u1f48D", NULL, {NULL} } +, { ":robot_face:", "\u1f916", NULL, {NULL} } +, { ":rocket:", "\u1f680", NULL, {NULL} } +, { ":rolled_up_newspaper:", "\u1f5dE\ufe0f", NULL, {NULL} } +, { ":roller_coaster:", "\u1f3a2", NULL, {NULL} } +, { ":rolling_on_the_floor_laughing:", "\u1f923", NULL, {NULL} } +, { ":rooster:", "\u1f413", NULL, {NULL} } +, { ":rose:", "\u1f339", NULL, {NULL} } +, { ":rosette:", "\u1f3f5\ufe0f", NULL, {NULL} } +, { ":rotating_light:", "\u1f6a8", NULL, {NULL} } +, { ":round_pushpin:", "\u1f4cD", NULL, {NULL} } +, { ":rowboat:", "\u1f6a3", NULL, {NULL} } +, { ":ru:", "\u1f1f7\u1f1fA", NULL, {NULL} } +, { ":rugby_football:", "\u1f3c9", NULL, {NULL} } +, { ":runner:", "\u1f3c3", NULL, {NULL} } +, { ":running:", "\u1f3c3", NULL, {NULL} } +, { ":running_shirt_with_sash:", "\u1f3bD", NULL, {NULL} } +, { ":sa:", "\u1f202\ufe0f", NULL, {NULL} } +, { ":sagittarius:", "\u2650", NULL, {NULL} } +, { ":sailboat:", "\u26f5", NULL, {NULL} } +, { ":sake:", "\u1f376", NULL, {NULL} } +, { ":sandal:", "\u1f461", NULL, {NULL} } +, { ":sandwich:", "\u1f96A", NULL, {NULL} } +, { ":santa:", "\u1f385", NULL, {NULL} } +, { ":satellite:", "\u1f6f0\ufe0f", NULL, {NULL} } +, { ":satellite_antenna:", "\u1f4e1", NULL, {NULL} } +, { ":satisfied:", "\u1f606", NULL, {":>", ":->", NULL} } +, { ":sauropod:", "\u1f995", NULL, {NULL} } +, { ":saxophone:", "\u1f3b7", NULL, {NULL} } +, { ":scales:", "\u2696\ufe0f", NULL, {NULL} } +, { ":scarf:", "\u1f9e3", NULL, {NULL} } +, { ":school:", "\u1f3eB", NULL, {NULL} } +, { ":school_satchel:", "\u1f392", NULL, {NULL} } +, { ":scissors:", "\u2702\ufe0f", NULL, {NULL} } +, { ":scooter:", "\u1f6f4", NULL, {NULL} } +, { ":scorpion:", "\u1f982", NULL, {NULL} } +, { ":scorpius:", "\u264f", NULL, {NULL} } +, { ":scream:", "\u1f631", NULL, {NULL} } +, { ":scream_cat:", "\u1f640", NULL, {NULL} } +, { ":scroll:", "\u1f4dC", NULL, {NULL} } +, { ":seat:", "\u1f4bA", NULL, {NULL} } +, { ":second_place_medal:", "\u1f948", NULL, {NULL} } +, { ":secret:", "\u3299\ufe0f", NULL, {NULL} } +, { ":see_no_evil:", "\u1f648", NULL, {NULL} } +, { ":seedling:", "\u1f331", NULL, {NULL} } +, { ":selfie:", "\u1f933", NULL, {NULL} } +, { ":serious_face_with_symbols_covering_mouth:", "\u1f92C", NULL, {NULL} } +, { ":seven:", "7\ufe0f\u20e3", NULL, {NULL} } +, { ":shallow_pan_of_food:", "\u1f958", NULL, {NULL} } +, { ":shamrock:", "\u2618\ufe0f", NULL, {NULL} } +, { ":shark:", "\u1f988", NULL, {NULL} } +, { ":shaved_ice:", "\u1f367", NULL, {NULL} } +, { ":sheep:", "\u1f411", NULL, {NULL} } +, { ":shell:", "\u1f41A", NULL, {NULL} } +, { ":shield:", "\u1f6e1\ufe0f", NULL, {NULL} } +, { ":shinto_shrine:", "\u26e9\ufe0f", NULL, {NULL} } +, { ":ship:", "\u1f6a2", NULL, {NULL} } +, { ":shirt:", "\u1f455", NULL, {NULL} } +, { ":shit:", "\u1f4a9", NULL, {NULL} } +, { ":shocked_face_with_exploding_head:", "\u1f92F", NULL, {NULL} } +, { ":shoe:", "\u1f45E", NULL, {NULL} } +, { ":shopping_bags:", "\u1f6cD\ufe0f", NULL, {NULL} } +, { ":shopping_trolley:", "\u1f6d2", NULL, {NULL} } +, { ":shower:", "\u1f6bF", NULL, {NULL} } +, { ":shrimp:", "\u1f990", NULL, {NULL} } +, { ":shrug:", "\u1f937", NULL, {NULL} } +, { ":shushing_face:", "\u1f92B", NULL, {NULL} } +, { ":sign_of_the_horns:", "\u1f918", NULL, {NULL} } +, { ":signal_strength:", "\u1f4f6", NULL, {NULL} } +, { ":six:", "6\ufe0f\u20e3", NULL, {NULL} } +, { ":six_pointed_star:", "\u1f52F", NULL, {NULL} } +, { ":ski:", "\u1f3bF", NULL, {NULL} } +, { ":skier:", "\u26f7\ufe0f", NULL, {NULL} } +, { ":skin-tone-2:", "\u1f3fB", NULL, {NULL} } +, { ":skin-tone-3:", "\u1f3fC", NULL, {NULL} } +, { ":skin-tone-4:", "\u1f3fD", NULL, {NULL} } +, { ":skin-tone-5:", "\u1f3fE", NULL, {NULL} } +, { ":skin-tone-6:", "\u1f3fF", NULL, {NULL} } +, { ":skull:", "\u1f480", NULL, {NULL} } +, { ":skull_and_crossbones:", "\u2620\ufe0f", NULL, {NULL} } +, { ":sled:", "\u1f6f7", NULL, {NULL} } +, { ":sleeping:", "\u1f634", NULL, {NULL} } +, { ":sleeping_accommodation:", "\u1f6cC", NULL, {NULL} } +, { ":sleepy:", "\u1f62A", NULL, {NULL} } +, { ":sleuth_or_spy:", "\u1f575\ufe0f", NULL, {NULL} } +, { ":slightly_frowning_face:", "\u1f641", NULL, {NULL} } +, { ":slightly_smiling_face:", "\u1f642", NULL, {":)", "(:", ":-)", NULL} } +, { ":slot_machine:", "\u1f3b0", NULL, {NULL} } +, { ":small_airplane:", "\u1f6e9\ufe0f", NULL, {NULL} } +, { ":small_blue_diamond:", "\u1f539", NULL, {NULL} } +, { ":small_orange_diamond:", "\u1f538", NULL, {NULL} } +, { ":small_red_triangle:", "\u1f53A", NULL, {NULL} } +, { ":small_red_triangle_down:", "\u1f53B", NULL, {NULL} } +, { ":smile:", "\u1f604", ":)", {"C:", "c:", ":D", ":-D", NULL} } +, { ":smile_cat:", "\u1f638", NULL, {NULL} } +, { ":smiley:", "\u1f603", ":)", {"=)", "=-)", NULL} } +, { ":smiley_cat:", "\u1f63A", NULL, {NULL} } +, { ":smiling_face_with_smiling_eyes_and_hand_covering_mouth:", "\u1f92D", NULL, {NULL} } +, { ":smiling_imp:", "\u1f608", NULL, {NULL} } +, { ":smirk:", "\u1f60F", NULL, {NULL} } +, { ":smirk_cat:", "\u1f63C", NULL, {NULL} } +, { ":smoking:", "\u1f6aC", NULL, {NULL} } +, { ":snail:", "\u1f40C", NULL, {NULL} } +, { ":snake:", "\u1f40D", NULL, {NULL} } +, { ":sneezing_face:", "\u1f927", NULL, {NULL} } +, { ":snow_capped_mountain:", "\u1f3d4\ufe0f", NULL, {NULL} } +, { ":snow_cloud:", "\u1f328\ufe0f", NULL, {NULL} } +, { ":snowboarder:", "\u1f3c2", NULL, {NULL} } +, { ":snowflake:", "\u2744\ufe0f", NULL, {NULL} } +, { ":snowman:", "\u2603\ufe0f", NULL, {NULL} } +, { ":snowman_without_snow:", "\u26c4", NULL, {NULL} } +, { ":sob:", "\u1f62D", ":'(", {NULL} } +, { ":soccer:", "\u26bd", NULL, {NULL} } +, { ":socks:", "\u1f9e6", NULL, {NULL} } +, { ":soon:", "\u1f51C", NULL, {NULL} } +, { ":sos:", "\u1f198", NULL, {NULL} } +, { ":sound:", "\u1f509", NULL, {NULL} } +, { ":space_invader:", "\u1f47E", NULL, {NULL} } +, { ":spades:", "\u2660\ufe0f", NULL, {NULL} } +, { ":spaghetti:", "\u1f35D", NULL, {NULL} } +, { ":sparkle:", "\u2747\ufe0f", NULL, {NULL} } +, { ":sparkler:", "\u1f387", NULL, {NULL} } +, { ":sparkles:", "\u2728", NULL, {NULL} } +, { ":sparkling_heart:", "\u1f496", NULL, {NULL} } +, { ":speak_no_evil:", "\u1f64A", NULL, {NULL} } +, { ":speaker:", "\u1f508", NULL, {NULL} } +, { ":speaking_head_in_silhouette:", "\u1f5e3\ufe0f", NULL, {NULL} } +, { ":speech_balloon:", "\u1f4aC", NULL, {NULL} } +, { ":speedboat:", "\u1f6a4", NULL, {NULL} } +, { ":spider:", "\u1f577\ufe0f", NULL, {NULL} } +, { ":spider_web:", "\u1f578\ufe0f", NULL, {NULL} } +, { ":spiral_calendar_pad:", "\u1f5d3\ufe0f", NULL, {NULL} } +, { ":spiral_note_pad:", "\u1f5d2\ufe0f", NULL, {NULL} } +, { ":spock-hand:", "\u1f596", NULL, {NULL} } +, { ":spoon:", "\u1f944", NULL, {NULL} } +, { ":sports_medal:", "\u1f3c5", NULL, {NULL} } +, { ":squid:", "\u1f991", NULL, {NULL} } +, { ":stadium:", "\u1f3dF\ufe0f", NULL, {NULL} } +, { ":staff_of_aesculapius:", "\u2695\ufe0f", NULL, {NULL} } +, { ":star:", "\u2b50", NULL, {NULL} } +, { ":star-struck:", "\u1f929", NULL, {NULL} } +, { ":star2:", "\u1f31F", NULL, {NULL} } +, { ":star_and_crescent:", "\u262a\ufe0f", NULL, {NULL} } +, { ":star_of_david:", "\u2721\ufe0f", NULL, {NULL} } +, { ":stars:", "\u1f320", NULL, {NULL} } +, { ":station:", "\u1f689", NULL, {NULL} } +, { ":statue_of_liberty:", "\u1f5fD", NULL, {NULL} } +, { ":steam_locomotive:", "\u1f682", NULL, {NULL} } +, { ":stew:", "\u1f372", NULL, {NULL} } +, { ":stopwatch:", "\u23f1\ufe0f", NULL, {NULL} } +, { ":straight_ruler:", "\u1f4cF", NULL, {NULL} } +, { ":strawberry:", "\u1f353", NULL, {NULL} } +, { ":stuck_out_tongue:", "\u1f61B", ":p", {":p", ":-p", ":P", ":-P", ":b", ":-b", NULL} } +, { ":stuck_out_tongue_closed_eyes:", "\u1f61D", NULL, {NULL} } +, { ":stuck_out_tongue_winking_eye:", "\u1f61C", ";p", {";p", ";-p", ";b", ";-b", ";P", ";-P", NULL} } +, { ":studio_microphone:", "\u1f399\ufe0f", NULL, {NULL} } +, { ":stuffed_flatbread:", "\u1f959", NULL, {NULL} } +, { ":sun_behind_cloud:", "\u1f325\ufe0f", NULL, {NULL} } +, { ":sun_behind_rain_cloud:", "\u1f326\ufe0f", NULL, {NULL} } +, { ":sun_small_cloud:", "\u1f324\ufe0f", NULL, {NULL} } +, { ":sun_with_face:", "\u1f31E", NULL, {NULL} } +, { ":sunflower:", "\u1f33B", NULL, {NULL} } +, { ":sunglasses:", "\u1f60E", NULL, {"8)", NULL} } +, { ":sunny:", "\u2600\ufe0f", NULL, {NULL} } +, { ":sunrise:", "\u1f305", NULL, {NULL} } +, { ":sunrise_over_mountains:", "\u1f304", NULL, {NULL} } +, { ":surfer:", "\u1f3c4", NULL, {NULL} } +, { ":sushi:", "\u1f363", NULL, {NULL} } +, { ":suspension_railway:", "\u1f69F", NULL, {NULL} } +, { ":sweat:", "\u1f613", NULL, {NULL} } +, { ":sweat_drops:", "\u1f4a6", NULL, {NULL} } +, { ":sweat_smile:", "\u1f605", NULL, {NULL} } +, { ":sweet_potato:", "\u1f360", NULL, {NULL} } +, { ":swimmer:", "\u1f3cA", NULL, {NULL} } +, { ":symbols:", "\u1f523", NULL, {NULL} } +, { ":synagogue:", "\u1f54D", NULL, {NULL} } +, { ":syringe:", "\u1f489", NULL, {NULL} } +, { ":t-rex:", "\u1f996", NULL, {NULL} } +, { ":table_tennis_paddle_and_ball:", "\u1f3d3", NULL, {NULL} } +, { ":taco:", "\u1f32E", NULL, {NULL} } +, { ":tada:", "\u1f389", NULL, {NULL} } +, { ":takeout_box:", "\u1f961", NULL, {NULL} } +, { ":tanabata_tree:", "\u1f38B", NULL, {NULL} } +, { ":tangerine:", "\u1f34A", NULL, {NULL} } +, { ":taurus:", "\u2649", NULL, {NULL} } +, { ":taxi:", "\u1f695", NULL, {NULL} } +, { ":tea:", "\u1f375", NULL, {NULL} } +, { ":telephone:", "\u260e\ufe0f", NULL, {NULL} } +, { ":telephone_receiver:", "\u1f4dE", NULL, {NULL} } +, { ":telescope:", "\u1f52D", NULL, {NULL} } +, { ":tennis:", "\u1f3bE", NULL, {NULL} } +, { ":tent:", "\u26fa", NULL, {NULL} } +, { ":the_horns:", "\u1f918", NULL, {NULL} } +, { ":thermometer:", "\u1f321\ufe0f", NULL, {NULL} } +, { ":thinking_face:", "\u1f914", NULL, {NULL} } +, { ":third_place_medal:", "\u1f949", NULL, {NULL} } +, { ":thought_balloon:", "\u1f4aD", NULL, {NULL} } +, { ":three:", "3\ufe0f\u20e3", NULL, {NULL} } +, { ":three_button_mouse:", "\u1f5b1\ufe0f", NULL, {NULL} } +, { ":thumbsdown:", "\u1f44E", NULL, {NULL} } +, { ":thumbsup:", "\u1f44D", NULL, {NULL} } +, { ":thunder_cloud_and_rain:", "\u26c8\ufe0f", NULL, {NULL} } +, { ":ticket:", "\u1f3aB", NULL, {NULL} } +, { ":tiger:", "\u1f42F", NULL, {NULL} } +, { ":tiger2:", "\u1f405", NULL, {NULL} } +, { ":timer_clock:", "\u23f2\ufe0f", NULL, {NULL} } +, { ":tired_face:", "\u1f62B", NULL, {NULL} } +, { ":tm:", "\u2122\ufe0f", NULL, {NULL} } +, { ":toilet:", "\u1f6bD", NULL, {NULL} } +, { ":tokyo_tower:", "\u1f5fC", NULL, {NULL} } +, { ":tomato:", "\u1f345", NULL, {NULL} } +, { ":tongue:", "\u1f445", NULL, {NULL} } +, { ":top:", "\u1f51D", NULL, {NULL} } +, { ":tophat:", "\u1f3a9", NULL, {NULL} } +, { ":tornado:", "\u1f32A\ufe0f", NULL, {NULL} } +, { ":tornado_cloud:", "\u1f32A\ufe0f", NULL, {NULL} } +, { ":trackball:", "\u1f5b2\ufe0f", NULL, {NULL} } +, { ":tractor:", "\u1f69C", NULL, {NULL} } +, { ":traffic_light:", "\u1f6a5", NULL, {NULL} } +, { ":train:", "\u1f68B", NULL, {NULL} } +, { ":train2:", "\u1f686", NULL, {NULL} } +, { ":tram:", "\u1f68A", NULL, {NULL} } +, { ":triangular_flag_on_post:", "\u1f6a9", NULL, {NULL} } +, { ":triangular_ruler:", "\u1f4d0", NULL, {NULL} } +, { ":trident:", "\u1f531", NULL, {NULL} } +, { ":triumph:", "\u1f624", NULL, {NULL} } +, { ":trolleybus:", "\u1f68E", NULL, {NULL} } +, { ":trophy:", "\u1f3c6", NULL, {NULL} } +, { ":tropical_drink:", "\u1f379", NULL, {NULL} } +, { ":tropical_fish:", "\u1f420", NULL, {NULL} } +, { ":truck:", "\u1f69A", NULL, {NULL} } +, { ":trumpet:", "\u1f3bA", NULL, {NULL} } +, { ":tshirt:", "\u1f455", NULL, {NULL} } +, { ":tulip:", "\u1f337", NULL, {NULL} } +, { ":tumbler_glass:", "\u1f943", NULL, {NULL} } +, { ":turkey:", "\u1f983", NULL, {NULL} } +, { ":turtle:", "\u1f422", NULL, {NULL} } +, { ":tv:", "\u1f4fA", NULL, {NULL} } +, { ":twisted_rightwards_arrows:", "\u1f500", NULL, {NULL} } +, { ":two:", "2\ufe0f\u20e3", NULL, {NULL} } +, { ":two_hearts:", "\u1f495", NULL, {NULL} } +, { ":two_men_holding_hands:", "\u1f46C", NULL, {NULL} } +, { ":two_women_holding_hands:", "\u1f46D", NULL, {NULL} } +, { ":u5272:", "\u1f239", NULL, {NULL} } +, { ":u5408:", "\u1f234", NULL, {NULL} } +, { ":u55b6:", "\u1f23A", NULL, {NULL} } +, { ":u6307:", "\u1f22F", NULL, {NULL} } +, { ":u6708:", "\u1f237\ufe0f", NULL, {NULL} } +, { ":u6709:", "\u1f236", NULL, {NULL} } +, { ":u6e80:", "\u1f235", NULL, {NULL} } +, { ":u7121:", "\u1f21A", NULL, {NULL} } +, { ":u7533:", "\u1f238", NULL, {NULL} } +, { ":u7981:", "\u1f232", NULL, {NULL} } +, { ":u7a7a:", "\u1f233", NULL, {NULL} } +, { ":uk:", "\u1f1eC\u1f1e7", NULL, {NULL} } +, { ":umbrella:", "\u2602\ufe0f", NULL, {NULL} } +, { ":umbrella_on_ground:", "\u26f1\ufe0f", NULL, {NULL} } +, { ":umbrella_with_rain_drops:", "\u2614", NULL, {NULL} } +, { ":unamused:", "\u1f612", ":(", {NULL} } +, { ":underage:", "\u1f51E", NULL, {NULL} } +, { ":unicorn_face:", "\u1f984", NULL, {NULL} } +, { ":unlock:", "\u1f513", NULL, {NULL} } +, { ":up:", "\u1f199", NULL, {NULL} } +, { ":upside_down_face:", "\u1f643", NULL, {NULL} } +, { ":us:", "\u1f1fA\u1f1f8", NULL, {NULL} } +, { ":v:", "\u270c\ufe0f", NULL, {NULL} } +, { ":vampire:", "\u1f9dB", NULL, {NULL} } +, { ":vertical_traffic_light:", "\u1f6a6", NULL, {NULL} } +, { ":vhs:", "\u1f4fC", NULL, {NULL} } +, { ":vibration_mode:", "\u1f4f3", NULL, {NULL} } +, { ":video_camera:", "\u1f4f9", NULL, {NULL} } +, { ":video_game:", "\u1f3aE", NULL, {NULL} } +, { ":violin:", "\u1f3bB", NULL, {NULL} } +, { ":virgo:", "\u264d", NULL, {NULL} } +, { ":volcano:", "\u1f30B", NULL, {NULL} } +, { ":volleyball:", "\u1f3d0", NULL, {NULL} } +, { ":vs:", "\u1f19A", NULL, {NULL} } +, { ":walking:", "\u1f6b6", NULL, {NULL} } +, { ":waning_crescent_moon:", "\u1f318", NULL, {NULL} } +, { ":waning_gibbous_moon:", "\u1f316", NULL, {NULL} } +, { ":warning:", "\u26a0\ufe0f", NULL, {NULL} } +, { ":wastebasket:", "\u1f5d1\ufe0f", NULL, {NULL} } +, { ":watch:", "\u231a", NULL, {NULL} } +, { ":water_buffalo:", "\u1f403", NULL, {NULL} } +, { ":water_polo:", "\u1f93D", NULL, {NULL} } +, { ":watermelon:", "\u1f349", NULL, {NULL} } +, { ":wave:", "\u1f44B", NULL, {NULL} } +, { ":waving_black_flag:", "\u1f3f4", NULL, {NULL} } +, { ":waving_white_flag:", "\u1f3f3\ufe0f", NULL, {NULL} } +, { ":wavy_dash:", "\u3030\ufe0f", NULL, {NULL} } +, { ":waxing_crescent_moon:", "\u1f312", NULL, {NULL} } +, { ":waxing_gibbous_moon:", "\u1f314", NULL, {NULL} } +, { ":wc:", "\u1f6bE", NULL, {NULL} } +, { ":weary:", "\u1f629", NULL, {NULL} } +, { ":wedding:", "\u1f492", NULL, {NULL} } +, { ":weight_lifter:", "\u1f3cB\ufe0f", NULL, {NULL} } +, { ":whale:", "\u1f433", NULL, {NULL} } +, { ":whale2:", "\u1f40B", NULL, {NULL} } +, { ":wheel_of_dharma:", "\u2638\ufe0f", NULL, {NULL} } +, { ":wheelchair:", "\u267f", NULL, {NULL} } +, { ":white_check_mark:", "\u2705", NULL, {NULL} } +, { ":white_circle:", "\u26aa", NULL, {NULL} } +, { ":white_flower:", "\u1f4aE", NULL, {NULL} } +, { ":white_frowning_face:", "\u2639\ufe0f", NULL, {NULL} } +, { ":white_large_square:", "\u2b1c", NULL, {NULL} } +, { ":white_medium_small_square:", "\u25fd", NULL, {NULL} } +, { ":white_medium_square:", "\u25fb\ufe0f", NULL, {NULL} } +, { ":white_small_square:", "\u25ab\ufe0f", NULL, {NULL} } +, { ":white_square_button:", "\u1f533", NULL, {NULL} } +, { ":wilted_flower:", "\u1f940", NULL, {NULL} } +, { ":wind_blowing_face:", "\u1f32C\ufe0f", NULL, {NULL} } +, { ":wind_chime:", "\u1f390", NULL, {NULL} } +, { ":wine_glass:", "\u1f377", NULL, {NULL} } +, { ":wink:", "\u1f609", ";)", {";)", ";-)", NULL} } +, { ":wolf:", "\u1f43A", NULL, {NULL} } +, { ":woman:", "\u1f469", NULL, {NULL} } +, { ":woman-biking:", "\u1f6b4\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-bouncing-ball:", "\u26f9\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-bowing:", "\u1f647\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-boy:", "\u1f469\u200d\u1f466", NULL, {NULL} } +, { ":woman-boy-boy:", "\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { ":woman-cartwheeling:", "\u1f938\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-facepalming:", "\u1f926\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-frowning:", "\u1f64D\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-gesturing-no:", "\u1f645\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-gesturing-ok:", "\u1f646\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-getting-haircut:", "\u1f487\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-getting-massage:", "\u1f486\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-girl:", "\u1f469\u200d\u1f467", NULL, {NULL} } +, { ":woman-girl-boy:", "\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { ":woman-girl-girl:", "\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { ":woman-golfing:", "\u1f3cC\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-heart-man:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } +, { ":woman-heart-woman:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f469", NULL, {NULL} } +, { ":woman-juggling:", "\u1f939\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-kiss-man:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } +, { ":woman-kiss-woman:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f469", NULL, {NULL} } +, { ":woman-lifting-weights:", "\u1f3cB\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-mountain-biking:", "\u1f6b5\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-playing-handball:", "\u1f93E\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-playing-water-polo:", "\u1f93D\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-pouting:", "\u1f64E\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-raising-hand:", "\u1f64B\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-rowing-boat:", "\u1f6a3\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-running:", "\u1f3c3\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-shrugging:", "\u1f937\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-surfing:", "\u1f3c4\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-swimming:", "\u1f3cA\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-tipping-hand:", "\u1f481\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-walking:", "\u1f6b6\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-wearing-turban:", "\u1f473\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-with-bunny-ears-partying:", "\u1f46F\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman-woman-boy:", "\u1f469\u200d\u1f469\u200d\u1f466", NULL, {NULL} } +, { ":woman-woman-boy-boy:", "\u1f469\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } +, { ":woman-woman-girl:", "\u1f469\u200d\u1f469\u200d\u1f467", NULL, {NULL} } +, { ":woman-woman-girl-boy:", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } +, { ":woman-woman-girl-girl:", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } +, { ":woman-wrestling:", "\u1f93C\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman_climbing:", "\u1f9d7\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman_in_lotus_position:", "\u1f9d8\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":woman_in_steamy_room:", "\u1f9d6\u200d\u2640\ufe0f", NULL, {NULL} } +, { ":womans_clothes:", "\u1f45A", NULL, {NULL} } +, { ":womans_hat:", "\u1f452", NULL, {NULL} } +, { ":womens:", "\u1f6bA", NULL, {NULL} } +, { ":world_map:", "\u1f5fA\ufe0f", NULL, {NULL} } +, { ":worried:", "\u1f61F", NULL, {NULL} } +, { ":wrench:", "\u1f527", NULL, {NULL} } +, { ":wrestlers:", "\u1f93C", NULL, {NULL} } +, { ":writing_hand:", "\u270d\ufe0f", NULL, {NULL} } +, { ":x:", "\u274c", NULL, {NULL} } +, { ":yellow_heart:", "\u1f49B", "<3", {NULL} } +, { ":yen:", "\u1f4b4", NULL, {NULL} } +, { ":yin_yang:", "\u262f\ufe0f", NULL, {NULL} } +, { ":yum:", "\u1f60B", NULL, {NULL} } +, { ":zany_face:", "\u1f92A", NULL, {NULL} } +, { ":zap:", "\u26a1", NULL, {NULL} } +, { ":zebra_face:", "\u1f993", NULL, {NULL} } +, { ":zero:", "0\ufe0f\u20e3", NULL, {NULL} } +, { ":zipper_mouth_face:", "\u1f910", NULL, {NULL} } +, { ":zombie:", "\u1f9dF", NULL, {NULL} } +, { ":zzz:", "\u1f4a4", NULL, {NULL} } }; static struct t_slack_emoji_by_text slack_emoji_by_text[] = -{ { "(:", "\u1f642", "slightly_smiling_face", {"slightly_smiling_face", NULL} } -, { "):", "\u1f61E", "disappointed", {"disappointed", NULL} } -, { "8)", "\u1f60E", "sunglasses", {"sunglasses", NULL} } -, { ":'(", "\u1f622", "cry", {"cry", NULL} } -, { ":(", "\u1f61E", "disappointed", {"disappointed", NULL} } -, { ":)", "\u1f642", "slightly_smiling_face", {"slightly_smiling_face", NULL} } -, { ":*", "\u1f618", "kissing_heart", {"kissing_heart", NULL} } -, { ":-(", "\u1f61E", "disappointed", {"disappointed", NULL} } -, { ":-)", "\u1f642", "slightly_smiling_face", {"slightly_smiling_face", NULL} } -, { ":-*", "\u1f618", "kissing_heart", {"kissing_heart", NULL} } -, { ":-/", "\u1f615", "confused", {"confused", NULL} } -, { ":->", "\u1f606", "laughing", {"laughing", "satisfied", NULL} } -, { ":-D", "\u1f604", "smile", {"smile", NULL} } -, { ":-O", "\u1f62E", "open_mouth", {"open_mouth", NULL} } -, { ":-P", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } -, { ":-\\", "\u1f615", "confused", {"confused", NULL} } -, { ":-b", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } -, { ":-o", "\u1f62E", "open_mouth", {"open_mouth", NULL} } -, { ":-p", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } -, { ":-|", "\u1f610", "neutral_face", {"neutral_face", NULL} } -, { ":/", "\u1f615", "confused", {"confused", NULL} } -, { ":>", "\u1f606", "laughing", {"laughing", "satisfied", NULL} } -, { ":D", "\u1f604", "smile", {"smile", NULL} } -, { ":O", "\u1f62E", "open_mouth", {"open_mouth", NULL} } -, { ":P", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } -, { ":\\", "\u1f615", "confused", {"confused", NULL} } -, { ":b", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } -, { ":o", "\u1f62E", "open_mouth", {"open_mouth", NULL} } -, { ":o)", "\u1f435", "monkey_face", {"monkey_face", NULL} } -, { ":p", "\u1f61B", "stuck_out_tongue", {"stuck_out_tongue", NULL} } -, { ":|", "\u1f610", "neutral_face", {"neutral_face", NULL} } -, { ";)", "\u1f609", "wink", {"wink", NULL} } -, { ";-)", "\u1f609", "wink", {"wink", NULL} } -, { ";-P", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } -, { ";-b", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } -, { ";-p", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } -, { ";P", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } -, { ";b", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } -, { ";p", "\u1f61C", "stuck_out_tongue_winking_eye", {"stuck_out_tongue_winking_eye", NULL} } -, { ":(", "\u1f620", "angry", {"angry", NULL} } -, { ">:-(", "\u1f620", "angry", {"angry", NULL} } -, { "C:", "\u1f604", "smile", {"smile", NULL} } -, { "D:", "\u1f627", "anguished", {"anguished", NULL} } -, { "c:", "\u1f604", "smile", {"smile", NULL} } +{ { "(:", "\u1f642", ":slightly_smiling_face:", {":slightly_smiling_face:", NULL} } +, { "):", "\u1f61E", ":disappointed:", {":disappointed:", NULL} } +, { "8)", "\u1f60E", ":sunglasses:", {":sunglasses:", NULL} } +, { ":'(", "\u1f622", ":cry:", {":cry:", NULL} } +, { ":(", "\u1f61E", ":disappointed:", {":disappointed:", NULL} } +, { ":)", "\u1f642", ":slightly_smiling_face:", {":slightly_smiling_face:", NULL} } +, { ":*", "\u1f618", ":kissing_heart:", {":kissing_heart:", NULL} } +, { ":-(", "\u1f61E", ":disappointed:", {":disappointed:", NULL} } +, { ":-)", "\u1f642", ":slightly_smiling_face:", {":slightly_smiling_face:", NULL} } +, { ":-*", "\u1f618", ":kissing_heart:", {":kissing_heart:", NULL} } +, { ":-/", "\u1f615", ":confused:", {":confused:", NULL} } +, { ":->", "\u1f606", ":laughing:", {":laughing:", ":satisfied:", NULL} } +, { ":-D", "\u1f604", ":smile:", {":smile:", NULL} } +, { ":-O", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } +, { ":-P", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } +, { ":-\\", "\u1f615", ":confused:", {":confused:", NULL} } +, { ":-b", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } +, { ":-o", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } +, { ":-p", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } +, { ":-|", "\u1f610", ":neutral_face:", {":neutral_face:", NULL} } +, { ":/", "\u1f615", ":confused:", {":confused:", NULL} } +, { ":>", "\u1f606", ":laughing:", {":laughing:", ":satisfied:", NULL} } +, { ":D", "\u1f604", ":smile:", {":smile:", NULL} } +, { ":O", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } +, { ":P", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } +, { ":\\", "\u1f615", ":confused:", {":confused:", NULL} } +, { ":b", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } +, { ":o", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } +, { ":o)", "\u1f435", ":monkey_face:", {":monkey_face:", NULL} } +, { ":p", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } +, { ":|", "\u1f610", ":neutral_face:", {":neutral_face:", NULL} } +, { ";)", "\u1f609", ":wink:", {":wink:", NULL} } +, { ";-)", "\u1f609", ":wink:", {":wink:", NULL} } +, { ";-P", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } +, { ";-b", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } +, { ";-p", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } +, { ";P", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } +, { ";b", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } +, { ";p", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } +, { ":(", "\u1f620", ":angry:", {":angry:", NULL} } +, { ">:-(", "\u1f620", ":angry:", {":angry:", NULL} } +, { "C:", "\u1f604", ":smile:", {":smile:", NULL} } +, { "D:", "\u1f627", ":anguished:", {":anguished:", NULL} } +, { "c:", "\u1f604", ":smile:", {":smile:", NULL} } }; diff --git a/slack-emoji.pl b/slack-emoji.pl index 357f528..5803327 100644 --- a/slack-emoji.pl +++ b/slack-emoji.pl @@ -51,16 +51,21 @@ my %byname = map { my $o = $_; map {($_, $o)} @{$o->{'short_names'}} } @array; my @sortedbyname = sort { $a cmp $b } keys %byname; foreach my $name (@sortedbyname) { - my $_0 = "\"$name\""; + my $_0 = "\":$name:\""; my @_1 = split /-/, $byname{$name}->{'unified'}; my $_1 = "\""; - foreach my $codepoint (@_1) { $_1 .= "\\u$codepoint" }; + foreach my $codepoint (@_1) { + if (hex $codepoint < 0xA0) { $_1 .= chr hex $codepoint } else { $_1 .= "\\u$codepoint" } + }; $_1 .= "\""; + $_1 =~ tr/A-Za-z/a-za-z/; my $_2 = $byname{$name}->{'text'}; if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" }; + $_2 =~ s/\\/\\\\/g; my $_3 = "{"; foreach my $text (@{$byname{$name}->{'texts'}}) { if (defined $text) { $_3 .= "\"$text\", " } }; $_3 .= "NULL}"; + $_3 =~ s/\\/\\\\/g; print "$c { $_0, $_1, $_2, $_3 }"; $c = ','; } @@ -73,14 +78,18 @@ my @sortedbytext = sort { $a cmp $b } keys %bytext; foreach my $text (@sortedbytext) { my $_0 = "\"$text\""; + $_0 =~ s/\\/\\\\/g; my @_1 = split /-/, $bytext{$text}->{'unified'}; my $_1 = "\""; - foreach my $codepoint (@_1) { $_1 .= "\\u$codepoint" }; + foreach my $codepoint (@_1) { + if (hex $codepoint < 0xA0) { $_1 .= chr hex $codepoint } else { $_1 .= "\\u$codepoint" } + }; $_1 .= "\""; + $_1 =~ tr/A-Za-z/a-za-z/; my $_2 = $bytext{$text}->{'short_name'}; - if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" }; + if (defined $_2) { $_2 = "\":$_2:\"" } else { $_2 = "NULL" }; my $_3 = "{"; - foreach my $name (@{$bytext{$text}->{'short_names'}}) { if (defined $name) { $_3 .= "\"$name\", " } }; + foreach my $name (@{$bytext{$text}->{'short_names'}}) { if (defined $name) { $_3 .= "\":$name:\", " } }; $_3 .= "NULL}"; print "$c { $_0, $_1, $_2, $_3 }"; $c = ','; diff --git a/slack-emoji.py b/slack-emoji.py index 558ce9b..9b5e90e 100755 --- a/slack-emoji.py +++ b/slack-emoji.py @@ -1,5 +1,4 @@ -#!/usr/bin/python -# Compatible with python v2 and v3 +#!/usr/bin/env python3 # 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 @@ -38,7 +37,7 @@ struct t_slack_emoji_by_text { max(len(o['short_names'] if o['short_names'] else []) for o in emoji) + 1)) print("static struct t_slack_emoji_by_name slack_emoji_by_name[] =") print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format( - json.dumps(name), + json.dumps(":"+name+":"), json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s), json.dumps(o['text']), "{"+json.dumps(o['texts']+[None] if o['texts'] else [None])[1:-1]+"}") @@ -51,8 +50,9 @@ print("static struct t_slack_emoji_by_text slack_emoji_by_text[] =") print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format( json.dumps(text), json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s), - json.dumps(o['short_name']), - "{"+json.dumps(o['short_names']+[None] if o['short_names'] else [None])[1:-1]+"}") + json.dumps(":"+o['short_name']+":"), + "{"+json.dumps(list(map(lambda name: ":"+name+":", o['short_names']))+[None] + if o['short_names'] else [None])[1:-1]+"}") for o,text in sorted(((o,text) for o in emoji if o['texts'] for text in o['texts']), key=lambda x:x[1]) ).replace("null", "NULL")[1:]) diff --git a/slack.c b/slack.c index fb83898..29cc0cf 100644 --- a/slack.c +++ b/slack.c @@ -15,6 +15,7 @@ #include "slack-workspace.h" #include "slack-api.h" #include "slack-buffer.h" +#include "slack-completion.h" WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME); @@ -49,7 +50,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_plugin = plugin; - lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE /*| LLL_INFO | LLL_DEBUG + lws_set_log_level(LLL_ERR | LLL_WARN /*| LLL_NOTICE | LLL_INFO | LLL_DEBUG | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT | LLL_LATENCY | LLL_USER | LLL_COUNT*/, slack_lwsl_emit_weechat); @@ -63,6 +64,8 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) slack_api_init(); + slack_completion_init(); + slack_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, &slack_workspace_timer_cb, NULL, NULL); From 27a5acd21dfcdc721a8dc932ce51b495beb38d5c Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 12 May 2018 18:32:35 +0100 Subject: [PATCH 049/118] Clang doesn't like our gnu extensions despite -std=gnu99 So we don't like clang. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d9bede5..ea198d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: c script: make compiler: - - clang - gcc From ffcbd66a7e0bf35c9196b20a593bb5056197b2a9 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 13 May 2018 04:54:20 +0100 Subject: [PATCH 050/118] Implement Standard Slack Emoji completion using /input command_* hooks See commit 5217251e94b2e5ea54a48ac660cb303257489f91 for details --- README.org | 7 +- debian/control | 2 +- slack-completion.c | 8 ++ slack-emoji.c | 193 ++++++++++++++++++++++++++++++++++----------- slack-emoji.h | 8 ++ 5 files changed, 168 insertions(+), 50 deletions(-) diff --git a/README.org b/README.org index b7842af..4fd6d44 100644 --- a/README.org +++ b/README.org @@ -35,7 +35,7 @@ - libwebsockets (static, submodule) - json-c (static, submodule) - - weechat (>= v1.4) + - weechat (>= v1.7) * Building @@ -84,6 +84,11 @@ ** TODO [#B] Implement websocket ping and pong (milestone v0.4) - [ ] Add ping timer and pong handler (see [[http://github.com/bqv/weechat-slack/issues/9][#9]]) ** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) + - [ ] Support all channel types + - [X] +Channels+ + - [ ] Groups + - [ ] MPIMs + - [ ] IMs - [ ] Complete api endpoint set - [ ] Complete api event set ** TODO [#C] Implement full weechat functionality (milestone v0.6) diff --git a/debian/control b/debian/control index 71cf7cc..26b93b6 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,7 @@ Vcs-Browser: https://github.com/bqv/weechat-slack Package: weechat-slack Architecture: any Depends: - weechat (>= 1.4), + weechat (>= 1.7), ${shlibs:Depends}, ${misc:Depends} Description: Fast, light and extensible chat client - Slack plugin diff --git a/slack-completion.c b/slack-completion.c index 8cd19a2..b0b3c6f 100644 --- a/slack-completion.c +++ b/slack-completion.c @@ -13,6 +13,14 @@ void slack_completion_init() { + weechat_hook_command_run("/input return", + &slack_emoji_input_replace_cb, + NULL, NULL); + + weechat_hook_command_run("/input complete*", + &slack_emoji_input_complete_cb, + NULL, NULL); + weechat_hook_completion("slack_emoji", N_("slack emoji"), &slack_emoji_complete_by_name_cb, diff --git a/slack-emoji.c b/slack-emoji.c index 8de99ba..42e3eb9 100644 --- a/slack-emoji.c +++ b/slack-emoji.c @@ -4,6 +4,7 @@ #include #include +#include #include "weechat-plugin.h" #include "slack.h" @@ -12,6 +13,7 @@ #include "slack-emoji.inc" #define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) static int emoji_byname_cmp(const void *p1, const void *p2) { @@ -25,64 +27,121 @@ static int emoji_bytext_cmp(const void *p1, const void *p2) ((struct t_slack_emoji_by_text *)p2)->text); } -static size_t levenshtein_dist(const char *s, size_t len_s, const char *t, size_t len_t) -{ - size_t cost; - - /* base case: empty strings */ - if (len_s == 0) return len_t; - if (len_t == 0) return len_s; +static size_t modified_wagner_fischer(const char *src, const char *targ) +{ + size_t len = strlen(targ) + 1; + size_t above[len], below[len]; + for (size_t *k = above, c = 0; k < above + len; ++k, ++c) *k = c; - /* test if last characters of the strings match */ - if (s[len_s-1] == t[len_t-1]) - cost = 0; - else - cost = 1; + const char *src_at = src, *targ_at; + for (size_t j = 1; j < strlen(src) + 1; ++j) + { + *below = j; + targ_at = targ; + for (size_t *d = above, *a = above + 1, *l = below, *c = below + 1; + c < below + len; ++d, ++a, ++l, ++c) + { + /* |-------------replace-----------| |isrt| |delt| */ + *c = MIN( *src_at == *targ_at ? *d : *d + 1, MIN( *a + 0, *l + 1 ) ); + ++targ_at; + } + for (size_t *a = above, *b = below; a < above + len; ++a, ++b) *a = *b; + ++src_at; + } - /* delete char from s, delete char from t, and delete char from both */ - size_t delete = levenshtein_dist(s, len_s - 1, t, len_t ) + 1; - size_t insert = levenshtein_dist(s, len_s , t, len_t - 1) + 1; - size_t replace = levenshtein_dist(s, len_s - 1, t, len_t - 1) + cost; - return MIN( MIN( delete, insert ), replace ); + return above[len-1]; } -static size_t wagner_fischer(const char *src, const char *targ) +static size_t longest_common_substring(const char *X, const char *Y) { - size_t len = strlen(targ) + 1; - size_t above[len], below[len]; - for (size_t *k = above, c = 0; k < above+len; ++k, ++c) *k=c; - - const char *src_at = src, *targ_at; - for (size_t j = 1; j < strlen(src)+1; ++j) - { - *below = j; - targ_at = targ; - for (size_t *d = above, *a = above+1, *l = below, *c = below + 1; - c < below + len; ++d, ++a, ++l, ++c) - { - *c = MIN( *src_at == *targ_at ? *d : *d + 1, MIN( *a + 1, *l + 1 ) ); - ++targ_at; - } - for (size_t *a = above, *b = below; a < above + len; ++a, ++b) *a = *b; - ++src_at; - } - - return above[len-1]; + const size_t n = strlen(X); + const size_t m = strlen(Y); + size_t i, j, result = 0; + size_t **L; + + L = malloc(sizeof(size_t *) * (n + 1)); + L[0] = malloc(sizeof(size_t) * (m + 1) * (n + 1)); + + for (i = 0; i <= n; i++) + L[i] = (*L + (m + 1) * i); + + /* Following steps build L[n+1][m+1] in bottom up fashion. Note + that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */ + for (i = 0; i <= n; i++) + { + for (j = 0; j <= m; j++) + { + if (i == 0 || j == 0) + { + L[i][j] = 0; + } + else if (X[i-1] == Y[j-1]) + { + L[i][j] = L[i - 1][j - 1] + 1; + if (result < L[i][j]) + result = L[i][j]; + } + else + { + L[i][j] = 0; + } + } + } + + /* result now contains length of LCS for X[0..n-1] and Y[0..m-1] */ + free(L[0]); + free(L); + return result; } int slack_emoji_complete_by_name_cb(const void *pointer, void *data, const char *completion_item, struct t_gui_buffer *buffer, struct t_gui_completion *completion) +{ + (void) pointer; + (void) data; + (void) completion_item; + (void) buffer; + + size_t i, emoji_count = sizeof(slack_emoji_by_name) + / sizeof(struct t_slack_emoji_by_name); + + for (i = 0; i < emoji_count; i++) + weechat_hook_completion_list_add(completion, + slack_emoji_by_name[i].name, + 0, WEECHAT_LIST_POS_END); + + return WEECHAT_RC_OK; +} + +int slack_emoji_input_complete_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *command) { struct t_slack_emoji_by_name *closest_emoji; + int input_pos, input_length, start, end; + char *new_string, *word, *new_pos; + const char *input_string; (void) pointer; (void) data; + (void) command; + + input_string = weechat_buffer_get_string(buffer, "input"); + input_length = strlen(input_string); + input_pos = weechat_buffer_get_integer(buffer, "input_pos"); + for (start = input_pos; start > 0 && input_string[start] != ':'; start--) + if (input_string[start] == ' ') { break; } + for (end = input_pos; end < input_length && input_string[end] != ' '; end++) + if (input_string[end] == ':') { end++; break; } - weechat_printf(NULL, "Completing!"); + if (input_string[start] != ':') + return WEECHAT_RC_OK; + else + word = strndup(&input_string[start], end - start); - size_t i, emoji_count = sizeof(slack_emoji_by_name) + size_t emoji_count = sizeof(slack_emoji_by_name) / sizeof(struct t_slack_emoji_by_name); closest_emoji = malloc(sizeof(slack_emoji_by_name)); memcpy(closest_emoji, slack_emoji_by_name, @@ -90,20 +149,58 @@ int slack_emoji_complete_by_name_cb(const void *pointer, void *data, int edit_dist_cmp(const void *p1, const void *p2) { - return 0; + const struct t_slack_emoji_by_name *e1 = p1; + const struct t_slack_emoji_by_name *e2 = p2; + size_t d1 = modified_wagner_fischer(e1->name, word); + size_t d2 = modified_wagner_fischer(e2->name, word); + if (d1 == d2) + { + size_t l1 = longest_common_substring(e1->name, word); + size_t l2 = longest_common_substring(e2->name, word); + return (l1 < l2) - (l1 > l2); + } + return (d1 > d2) - (d1 < d2); }; qsort(closest_emoji, emoji_count, sizeof(struct t_slack_emoji_by_name), edit_dist_cmp); - for (i = 0; i < emoji_count; i++) - { - weechat_printf(NULL, closest_emoji[i].name); - weechat_hook_completion_list_add(completion, closest_emoji[i].name, - 0, WEECHAT_LIST_POS_END); - } - + size_t new_length = snprintf(NULL, 0, "%.*s%s%s", + start, input_string, + closest_emoji[0].name, + &input_string[end]) + 1; + new_string = malloc(new_length); + snprintf(new_string, new_length, "%.*s%s%s", + start, input_string, + closest_emoji[0].name, + &input_string[end]); + weechat_buffer_set(buffer, "input", new_string); + + size_t new_pos_len = snprintf(NULL, 0, "%lu", + (unsigned long)(start + + strlen(closest_emoji[0].name) - 1)); + new_pos = malloc(new_pos_len); + snprintf(new_pos, new_pos_len, "%lu", + (unsigned long)(start + + strlen(closest_emoji[0].name) - 1)); + weechat_buffer_set(buffer, "input_pos", new_pos); + + free(new_pos); + free(new_string); free(closest_emoji); + free(word); + return WEECHAT_RC_OK_EAT; +} + +int slack_emoji_input_replace_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *command) +{ + (void) pointer; + (void) data; + (void) buffer; + (void) command; + return WEECHAT_RC_OK; } diff --git a/slack-emoji.h b/slack-emoji.h index 906c684..9fc688d 100644 --- a/slack-emoji.h +++ b/slack-emoji.h @@ -10,6 +10,14 @@ int slack_emoji_complete_by_name_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion); +int slack_emoji_input_complete_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *command); + +int slack_emoji_input_replace_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *command); + const char *slack_emoji_get_unicode_by_name(const char *name); const char *slack_emoji_get_unicode_by_text(const char *text); From cb597736f15fef4be1237846647ad9ad772f9991 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 13 May 2018 11:22:00 +0100 Subject: [PATCH 051/118] Officially support tab-completion of standard slack emoji Using the weechat-idiomatic interface. TODO: Deprecate /input complete_* code --- README.org | 16 ++++++++++++---- slack-completion.c | 23 ++++++++++++++++++++++- slack-emoji.c | 11 ++++++++++- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/README.org b/README.org index 4fd6d44..333fd24 100644 --- a/README.org +++ b/README.org @@ -17,9 +17,10 @@ [[https://github.com/bqv/weechat-slack/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-slack.svg]] [[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-slack-yellow.svg]] - | Status: | Under Development | - | Location: | [[http://github.com/bqv/weechat-slack]] | - | Version: | 0.1.0 | + | Status: | Under Development | + | Location: | [[http://github.com/bqv/weechat-slack]] | + | Version: | 0.1.0 | + | Disclaimer: | Slack's API is a thing of horror | * Description @@ -77,7 +78,7 @@ - [ ] Implement sending websocket =typing= message ** TODO [#B] Implement completion engine (milestone v0.3) - [ ] Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]]) - - [ ] Support Slack Emoji + - [X] +Support Slack Emoji+ - [ ] Support Custom Emoji - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) @@ -101,6 +102,13 @@ *Your contributions are always welcome!* Please submit a pull request or create an issue to add a new or missing feature. + +* Appropriating + + As there is no C library for Slack at the time of + writing, this project implements the APIs from + scratch, and as such one could butcher this repository + to create a minimal Slack C library. * License diff --git a/slack-completion.c b/slack-completion.c index b0b3c6f..7be5449 100644 --- a/slack-completion.c +++ b/slack-completion.c @@ -2,7 +2,9 @@ // 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 "weechat-plugin.h" #include "slack.h" @@ -13,6 +15,10 @@ void slack_completion_init() { + struct t_config_option *option; + const char *default_template; + + /* weechat_hook_command_run("/input return", &slack_emoji_input_replace_cb, NULL, NULL); @@ -20,9 +26,24 @@ void slack_completion_init() weechat_hook_command_run("/input complete*", &slack_emoji_input_complete_cb, NULL, NULL); - + */ weechat_hook_completion("slack_emoji", N_("slack emoji"), &slack_emoji_complete_by_name_cb, NULL, NULL); + + option = weechat_config_get("weechat.completion.default_template"); + default_template = weechat_config_string(option); + if (!weechat_strcasestr(default_template, "%(slack_emoji)")) + { + size_t length = snprintf(NULL, 0, "%s|%s", + default_template, + "%(slack_emoji)") + 1; + char *new_template = malloc(length); + snprintf(new_template, length, "%s|%s", + default_template, + "%(slack_emoji)"); + weechat_config_option_set(option, new_template, 1); + free(new_template); + } } diff --git a/slack-emoji.c b/slack-emoji.c index 42e3eb9..7ea1392 100644 --- a/slack-emoji.c +++ b/slack-emoji.c @@ -8,6 +8,9 @@ #include "weechat-plugin.h" #include "slack.h" +#include "slack-workspace.h" +#include "slack-channel.h" +#include "slack-buffer.h" #include "slack-emoji.h" #include "slack-emoji.inc" @@ -99,10 +102,14 @@ int slack_emoji_complete_by_name_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { + struct t_slack_workspace *workspace; + struct t_slack_channel *channel; + (void) pointer; (void) data; (void) completion_item; - (void) buffer; + + slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); size_t i, emoji_count = sizeof(slack_emoji_by_name) / sizeof(struct t_slack_emoji_by_name); @@ -200,6 +207,8 @@ int slack_emoji_input_replace_cb(const void *pointer, void *data, (void) data; (void) buffer; (void) command; + + /* TBI */ return WEECHAT_RC_OK; } From d9c8e64ffe12345369613bb828f59b4e2d6ecd27 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 13 May 2018 15:31:23 +0100 Subject: [PATCH 052/118] Support tab-complete workspace-specific custom slack emoji (fix #3) --- Makefile | 15 +- README.org | 8 +- api/slack-api-hello.c | 7 + request/slack-request-emoji-list.c | 287 +++++++++++++++++++++++++++++ request/slack-request-emoji-list.h | 12 ++ request/slack-request-users-list.c | 3 - slack-emoji.c | 19 +- slack-workspace.c | 59 ++++++ slack-workspace.h | 19 ++ 9 files changed, 412 insertions(+), 17 deletions(-) create mode 100644 request/slack-request-emoji-list.c create mode 100644 request/slack-request-emoji-list.h diff --git a/Makefile b/Makefile index 4568e53..9ea5d8e 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,9 @@ ifdef DEBUG - CC=clang - CXX=g++ - DBGCFLAGS=-fsanitize=address -fsanitize=leak - DBGLDFLAGS=-static-libasan -static-liblsan + DBGCFLAGS=-fsanitize=address -fsanitize=leak -fsanitize=undefined + DBGLDFLAGS=-static-libasan -static-liblsan -static-libubsan endif RM=rm -f +FIND=find CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) LDLIBS=-lgnutls @@ -40,13 +39,14 @@ SRCS=slack.c \ request/slack-request-chat-postmessage.c \ request/slack-request-channels-list.c \ request/slack-request-conversations-members.c \ + request/slack-request-emoji-list.c \ request/slack-request-users-list.c OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack weechat-slack: $(OBJS) - $(CXX) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) + $(CC) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) ifeq ($(shell which python),) slack-emoji.inc: slack-emoji.pl @@ -70,7 +70,10 @@ depend: .depend .depend: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a $(SRCS) $(RM) ./.depend - $(CC) $(CFLAGS) -MM $^>>./.depend; + $(CC) $(CFLAGS) -MM $^>>./.depend + +tidy: + $(FIND) . -name "*.o" -delete clean: $(RM) $(OBJS) diff --git a/README.org b/README.org index 333fd24..a83f0f6 100644 --- a/README.org +++ b/README.org @@ -77,11 +77,11 @@ - [ ] Implement handling api message =message.message_replied= - [ ] Implement sending websocket =typing= message ** TODO [#B] Implement completion engine (milestone v0.3) - - [ ] Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]]) + - [X] +Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]])+ - [X] +Support Slack Emoji+ - - [ ] Support Custom Emoji + - [X] +Support Custom Emoji+ - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - - [ ] Sort nick-completion by recent (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) + - [ ] Sort nick-completion by recent speakers (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) ** TODO [#B] Implement websocket ping and pong (milestone v0.4) - [ ] Add ping timer and pong handler (see [[http://github.com/bqv/weechat-slack/issues/9][#9]]) ** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) @@ -108,7 +108,7 @@ As there is no C library for Slack at the time of writing, this project implements the APIs from scratch, and as such one could butcher this repository - to create a minimal Slack C library. + to create a minimal Slack C library. Up to you. * License diff --git a/api/slack-api-hello.c b/api/slack-api-hello.c index 87fa406..611cfc6 100644 --- a/api/slack-api-hello.c +++ b/api/slack-api-hello.c @@ -11,6 +11,7 @@ #include "slack-api-hello.h" #include "../request/slack-request-channels-list.h" #include "../request/slack-request-users-list.h" +#include "../request/slack-request-emoji-list.h" int slack_api_hello_handle(struct t_slack_workspace *workspace) { @@ -35,6 +36,12 @@ int slack_api_hello_handle(struct t_slack_workspace *workspace) if (request) slack_workspace_register_request(workspace, request); + request = slack_request_emoji_list(workspace, + weechat_config_string( + workspace->options[SLACK_WORKSPACE_OPTION_TOKEN])); + if (request) + slack_workspace_register_request(workspace, request); + return 1; } diff --git a/request/slack-request-emoji-list.c b/request/slack-request-emoji-list.c new file mode 100644 index 0000000..abc303b --- /dev/null +++ b/request/slack-request-emoji-list.c @@ -0,0 +1,287 @@ +// 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 "../weechat-plugin.h" +#include "../slack.h" +#include "../slack-workspace.h" +#include "../slack-request.h" +#include "../slack-channel.h" +#include "../request/slack-request-emoji-list.h" + +static const char *const endpoint = "/api/emoji.list?" + "token=%s"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error retrieving emoji: unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME); + //__asm__("int3"); + return 0; + } + + return 1; +} + +static const struct lws_protocols protocols[]; + +static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct t_slack_request *request = (struct t_slack_request *)user; + struct lws_client_connect_info ccinfo; + + int status; + + switch (reason) + { + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) error connecting to slack: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + in ? (char *)in : "(null)"); + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) reconnecting..."), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + status = lws_http_client_http_response(wsi); + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) retrieving emoji... (%d)"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + status); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + { + struct t_json_chunk *new_chunk, *last_chunk; + + new_chunk = malloc(sizeof(*new_chunk)); + new_chunk->data = malloc((1024 * sizeof(char)) + 1); + new_chunk->data[0] = '\0'; + new_chunk->next = NULL; + + strncat(new_chunk->data, in, (int)len); + + if (request->json_chunks) + { + for (last_chunk = request->json_chunks; last_chunk->next; + last_chunk = last_chunk->next); + last_chunk->next = new_chunk; + } + else + { + request->json_chunks = new_chunk; + } + } + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + { + int chunk_count, i; + char *json_string; + json_object *response, *ok, *error, *emoji; + struct t_json_chunk *chunk_ptr; + + chunk_count = 0; + if (request->json_chunks) + { + chunk_count++; + for (chunk_ptr = request->json_chunks; chunk_ptr->next; + chunk_ptr = chunk_ptr->next) + { + chunk_count++; + } + } + + json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); + json_string[0] = '\0'; + + chunk_ptr = request->json_chunks; + for (i = 0; i < chunk_count; i++) + { + strncat(json_string, chunk_ptr->data, 1024); + chunk_ptr = chunk_ptr->next; + + free(request->json_chunks->data); + free(request->json_chunks); + request->json_chunks = chunk_ptr; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) got response: %s"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, + json_string); + + response = json_tokener_parse(json_string); + ok = json_object_object_get(response, "ok"); + if (!json_valid(ok, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + if(json_object_get_boolean(ok)) + { + emoji = json_object_object_get(response, "emoji"); + if (!json_valid(emoji, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + json_object_object_foreach(emoji, key, val) + { + if (!json_valid(val, request->workspace)) + { + continue; + } + + slack_workspace_add_emoji( + request->workspace, + key, json_object_get_string(val)); + } + } + else + { + error = json_object_object_get(response, "error"); + if (!json_valid(error, request->workspace)) + { + json_object_put(response); + free(json_string); + return 0; + } + + weechat_printf( + request->workspace->buffer, + _("%s%s: (%d) failed to retrieve emoji: %s"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, + json_object_get_string(error)); + } + + json_object_put(response); + free(json_string); + } + /* fallthrough */ + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + request->client_wsi = NULL; + /* Does not doing this cause a leak? + lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, + { NULL, NULL, 0, 0 } +}; + +struct t_slack_request *slack_request_emoji_list( + struct t_slack_workspace *workspace, + const char *token) +{ + struct t_slack_request *request; + struct lws_context_creation_info ctxinfo; + struct lws_client_connect_info ccinfo; + + request = slack_request_alloc(workspace); + + size_t urilen = snprintf(NULL, 0, endpoint, token) + 1; + request->uri = malloc(urilen); + snprintf(request->uri, urilen, endpoint, token); + + memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ + ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + ctxinfo.protocols = protocols; + + request->context = lws_create_context(&ctxinfo); + if (!request->context) + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) error connecting to slack: lws init failed"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); + return NULL; + } + else + { + weechat_printf( + workspace->buffer, + _("%s%s: (%d) contacting slack.com:443"), + weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); + } + + memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ + ccinfo.context = request->context; + ccinfo.ssl_connection = LCCSCF_USE_SSL; + ccinfo.port = 443; + ccinfo.address = "slack.com"; + ccinfo.path = request->uri; + ccinfo.host = ccinfo.address; + ccinfo.origin = ccinfo.address; + ccinfo.method = "GET"; + ccinfo.protocol = protocols[0].name; + ccinfo.pwsi = &request->client_wsi; + ccinfo.userdata = request; + + lws_client_connect_via_info(&ccinfo); + + return request; +} diff --git a/request/slack-request-emoji-list.h b/request/slack-request-emoji-list.h new file mode 100644 index 0000000..19101d1 --- /dev/null +++ b/request/slack-request-emoji-list.h @@ -0,0 +1,12 @@ +// 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/. + +#ifndef _SLACK_REQUEST_EMOJI_LIST_H_ +#define _SLACK_REQUEST_EMOJI_LIST_H_ + +struct t_slack_request *slack_request_emoji_list( + struct t_slack_workspace *workspace, + const char *token); + +#endif /*SLACK_REQUEST_EMOJI_LIST_H*/ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index 62d5463..a8ec9af 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -220,9 +220,6 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, new_user = slack_user_new(request->workspace, json_object_get_string(id), json_object_get_string(display_name)); - - if (!new_user) - __asm__("int3"); bot_id = json_object_object_get(profile, "bot_id"); if (json_valid(bot_id, request->workspace)) diff --git a/slack-emoji.c b/slack-emoji.c index 7ea1392..3ec6802 100644 --- a/slack-emoji.c +++ b/slack-emoji.c @@ -102,6 +102,7 @@ int slack_emoji_complete_by_name_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { + struct t_slack_workspace_emoji *ptr_emoji; struct t_slack_workspace *workspace; struct t_slack_channel *channel; @@ -109,15 +110,25 @@ int slack_emoji_complete_by_name_cb(const void *pointer, void *data, (void) data; (void) completion_item; + workspace = NULL; slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); size_t i, emoji_count = sizeof(slack_emoji_by_name) / sizeof(struct t_slack_emoji_by_name); + + if (workspace) + { + for (ptr_emoji = workspace->emoji; ptr_emoji; + ptr_emoji = ptr_emoji->next_emoji) + weechat_hook_completion_list_add(completion, + ptr_emoji->name, + 0, WEECHAT_LIST_POS_END); - for (i = 0; i < emoji_count; i++) - weechat_hook_completion_list_add(completion, - slack_emoji_by_name[i].name, - 0, WEECHAT_LIST_POS_END); + for (i = 0; i < emoji_count; i++) + weechat_hook_completion_list_add(completion, + slack_emoji_by_name[i].name, + 0, WEECHAT_LIST_POS_END); + } return WEECHAT_RC_OK; } diff --git a/slack-workspace.c b/slack-workspace.c index b820d1d..23228fe 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -388,6 +388,8 @@ struct t_slack_workspace *slack_workspace_alloc(const char *domain) new_workspace->last_user = NULL; new_workspace->channels = NULL; new_workspace->last_channel = NULL; + new_workspace->emoji = NULL; + new_workspace->last_emoji = NULL; /* create options with null value */ for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) @@ -911,3 +913,60 @@ void slack_workspace_register_request(struct t_slack_workspace *workspace, workspace->requests = request; workspace->last_request = request; } + +struct t_slack_workspace_emoji *slack_workspace_emoji_search( + struct t_slack_workspace *workspace, + const char *name) +{ + struct t_slack_workspace_emoji *ptr_emoji; + + if (!workspace || !name) + return NULL; + + for (ptr_emoji = workspace->emoji; ptr_emoji; + ptr_emoji = ptr_emoji->next_emoji) + { + if (weechat_strcasecmp(ptr_emoji->name, name) == 0) + return ptr_emoji; + } + + return NULL; +} + +struct t_slack_workspace_emoji *slack_workspace_add_emoji( + struct t_slack_workspace *workspace, + const char *name, const char *url) +{ + struct t_slack_workspace_emoji *ptr_emoji, *new_emoji; + char shortname[SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN + 1]; + + (void) url; + + if (!workspace || !name || !name[0]) + return NULL; + + snprintf(shortname, SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN + 1, + ":%s:", name); + + ptr_emoji = slack_workspace_emoji_search(workspace, shortname); + if (ptr_emoji) + { + return ptr_emoji; + } + + if ((new_emoji = malloc(sizeof(*new_emoji))) == NULL) + return NULL; + + new_emoji->name = strdup(shortname); + new_emoji->url = strdup(url); + + new_emoji->prev_emoji = workspace->last_emoji; + new_emoji->next_emoji = NULL; + if (workspace->last_emoji) + (workspace->last_emoji)->next_emoji = new_emoji; + else + workspace->emoji = new_emoji; + workspace->last_emoji = new_emoji; + + return new_emoji; +} diff --git a/slack-workspace.h b/slack-workspace.h index d858b08..030b4ff 100644 --- a/slack-workspace.h +++ b/slack-workspace.h @@ -5,9 +5,20 @@ #ifndef _SLACK_WORKSPACE_H_ #define _SLACK_WORKSPACE_H_ +#define SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN 1 + 100 + 1 + extern struct t_slack_workspace *slack_workspaces; extern struct t_slack_workspace *last_slack_workspace; +struct t_slack_workspace_emoji +{ + char *name; + char *url; + + struct t_slack_workspace_emoji *prev_emoji; + struct t_slack_workspace_emoji *next_emoji; +}; + enum t_slack_workspace_option { SLACK_WORKSPACE_OPTION_TOKEN, @@ -51,6 +62,8 @@ struct t_slack_workspace struct t_slack_user *last_user; struct t_slack_channel *channels; struct t_slack_channel *last_channel; + struct t_slack_workspace_emoji *emoji; + struct t_slack_workspace_emoji *last_emoji; struct t_slack_workspace *prev_workspace; struct t_slack_workspace *next_workspace; }; @@ -72,5 +85,11 @@ int slack_workspace_connect(struct t_slack_workspace *workspace); int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls); void slack_workspace_register_request(struct t_slack_workspace *workspace, struct t_slack_request *request); +struct t_slack_workspace_emoji *slack_workspace_emoji_search( + struct t_slack_workspace *workspace, + const char *name); +struct t_slack_workspace_emoji *slack_workspace_add_emoji( + struct t_slack_workspace *workspace, + const char *name, const char *url); #endif /*SLACK_WORKSPACE_H*/ From aa2a9ab594c78dee5c74b327a8daf9810ad600ec Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 13 May 2018 15:51:39 +0100 Subject: [PATCH 053/118] Add slack_workspace completion for /slack commands --- README.org | 2 ++ slack-completion.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/README.org b/README.org index a83f0f6..f0f1eac 100644 --- a/README.org +++ b/README.org @@ -95,6 +95,8 @@ ** TODO [#C] Implement full weechat functionality (milestone v0.6) - [ ] Hook buffer closes - [ ] Relay compatibility + - [ ] Config Options + - [ ] Emoji translation options (see [[http://github.com/bqv/weechat-slack/issues/11][#11]]) ** TODO [#D] Close all issues (milestone v1.0) * Contributing diff --git a/slack-completion.c b/slack-completion.c index 7be5449..4a71eec 100644 --- a/slack-completion.c +++ b/slack-completion.c @@ -13,20 +13,39 @@ #include "slack-channel.h" #include "slack-completion.h" +int slack_completion_workspaces_cb(const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_slack_workspace *ptr_workspace; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + (void) buffer; + + for (ptr_workspace = slack_workspaces; ptr_workspace; + ptr_workspace = ptr_workspace->next_workspace) + { + weechat_hook_completion_list_add(completion, ptr_workspace->domain, + 0, WEECHAT_LIST_POS_SORT); + } + + return WEECHAT_RC_OK; +} + void slack_completion_init() { struct t_config_option *option; const char *default_template; - /* - weechat_hook_command_run("/input return", - &slack_emoji_input_replace_cb, - NULL, NULL); - - weechat_hook_command_run("/input complete*", - &slack_emoji_input_complete_cb, - NULL, NULL); - */ + weechat_hook_completion("slack_workspace", + N_("slack workspaces"), + &slack_completion_workspaces_cb, + NULL, NULL); + weechat_hook_completion("slack_emoji", N_("slack emoji"), &slack_emoji_complete_by_name_cb, From 0e8ea0701057226279f1dd8de1a62904fd9f0213 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 13 May 2018 15:56:10 +0100 Subject: [PATCH 054/118] Add usage to README.org --- README.org | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.org b/README.org index f0f1eac..e9eeebb 100644 --- a/README.org +++ b/README.org @@ -26,6 +26,15 @@ A weechat plugin in C to extend the chat client to support Slack workspaces via the RTM and Web APIs. + +* Usage + + 1. Start with `/slack register` for instructions on how + to obtain a token, or if you already have a token, use + `/slack register `. + + 2. Use `/slack connect ` with the name + returned by register * Installing From 58d46c71d5f03af8ae8789766530b12f305e0440 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 14 May 2018 05:03:03 +0100 Subject: [PATCH 055/118] Implement sorting nick completions by speaking --- README.org | 6 +-- api/slack-api-message.c | 4 ++ slack-channel.c | 95 +++++++++++++++++++++++++++++++++++++++++ slack-channel.h | 14 ++++++ slack-completion.c | 94 ++++++++++++++++++++++++++++++++++++++++ slack-config.c | 27 ++++++++++++ slack-config.h | 9 ++++ 7 files changed, 246 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index e9eeebb..0646596 100644 --- a/README.org +++ b/README.org @@ -29,11 +29,11 @@ * Usage - 1. Start with `/slack register` for instructions on how + 1. Start with =/slack register= for instructions on how to obtain a token, or if you already have a token, use - `/slack register `. + =/slack register =. - 2. Use `/slack connect ` with the name + 2. Use =/slack connect = with the name returned by register * Installing diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 0fd0a04..99f6ac0 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -107,6 +107,10 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, _("%s%s"), slack_user_as_prefix(workspace, ptr_user, NULL), message); + slack_channel_member_speaking_add(channel, ptr_user->profile.display_name, + weechat_string_has_highlight( + message, + ptr_user->profile.display_name)); free(message); ptr_typing = slack_channel_typing_search(ptr_channel, diff --git a/slack-channel.c b/slack-channel.c index d301f20..33efb9e 100644 --- a/slack-channel.c +++ b/slack-channel.c @@ -237,6 +237,8 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, new_channel->is_user_deleted = 0; new_channel->typing_hook_timer = typing_timer; + new_channel->members_speaking[0] = NULL; + new_channel->members_speaking[1] = NULL; new_channel->typings = NULL; new_channel->last_typing = NULL; new_channel->members = NULL; @@ -255,6 +257,95 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, return new_channel; } +void slack_channel_member_speaking_add_to_list(struct t_slack_channel *channel, + 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(); + + /* remove item if it was already in list */ + ptr_item = weechat_list_casesearch(channel->members_speaking[highlight], nick); + if (ptr_item) + weechat_list_remove(channel->members_speaking[highlight], ptr_item); + + /* add nick in list */ + weechat_list_add(channel->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]); + if (size > SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT) + { + to_remove = size - SLACK_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)); + } + } +} + +void slack_channel_member_speaking_add(struct t_slack_channel *channel, + const char *nick, int highlight) +{ + if (highlight < 0) + highlight = 0; + if (highlight > 1) + highlight = 1; + if (highlight) + slack_channel_member_speaking_add_to_list(channel, nick, 1); + + slack_channel_member_speaking_add_to_list(channel, nick, 0); +} + +void slack_channel_member_speaking_rename(struct t_slack_channel *channel, + 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]) + { + ptr_item = weechat_list_search(channel->members_speaking[i], old_nick); + if (ptr_item) + weechat_list_set(ptr_item, new_nick); + } + } +} + +void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + const char *nick) +{ + struct t_weelist_item *ptr_item; + int i, j, list_size; + + (void) workspace; + + for (i = 0; i < 2; i++) + { + if (channel->members_speaking[i]) + { + list_size = weechat_list_size(channel->members_speaking[i]); + for (j = 0; j < list_size; j++) + { + ptr_item = weechat_list_get (channel->members_speaking[i], j); + if (ptr_item && (strcasecmp(weechat_list_string(ptr_item), nick) == 0)) + weechat_list_set(ptr_item, nick); + } + } + } +} + void slack_channel_typing_free(struct t_slack_channel *channel, struct t_slack_channel_typing *typing) { @@ -473,6 +564,10 @@ void slack_channel_free(struct t_slack_workspace *workspace, free(channel->purpose.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); diff --git a/slack-channel.h b/slack-channel.h index 23275eb..e5f507e 100644 --- a/slack-channel.h +++ b/slack-channel.h @@ -5,6 +5,8 @@ #ifndef _SLACK_CHANNEL_H_ #define _SLACK_CHANNEL_H_ +#define SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT 128 + #define SLACK_CHANNEL_NAME_MAX_LEN 22 enum t_slack_channel_type @@ -76,6 +78,7 @@ struct t_slack_channel int is_user_deleted; struct t_hook *typing_hook_timer; + struct t_weelist *members_speaking[2]; struct t_slack_channel_typing *typings; struct t_slack_channel_typing *last_typing; struct t_slack_channel_member *members; @@ -97,6 +100,17 @@ struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, enum t_slack_channel_type type, const char *id, const char *name); +void slack_channel_member_speaking_add(struct t_slack_channel *channel, + const char *nick, int highlight); + +void slack_channel_member_speaking_rename(struct t_slack_channel *channel, + const char *old_nick, + const char *new_nick); + +void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + const char *nick); + void slack_channel_typing_free(struct t_slack_channel *channel, struct t_slack_channel_typing *typing); diff --git a/slack-completion.c b/slack-completion.c index 4a71eec..1002e0c 100644 --- a/slack-completion.c +++ b/slack-completion.c @@ -8,11 +8,99 @@ #include "weechat-plugin.h" #include "slack.h" +#include "slack-config.h" #include "slack-emoji.h" #include "slack-workspace.h" #include "slack-channel.h" +#include "slack-user.h" +#include "slack-buffer.h" #include "slack-completion.h" +void slack_completion_channel_nicks_add_speakers(struct t_gui_completion *completion, + struct t_slack_workspace *workspace, + struct t_slack_channel *channel, + int highlight) +{ + struct t_slack_user *user; + const char *member; + int list_size, i; + + if (channel->members_speaking[highlight]) + { + list_size = weechat_list_size(channel->members_speaking[highlight]); + for (i = 0; i < list_size; i++) + { + member = weechat_list_string ( + weechat_list_get(channel->members_speaking[highlight], i)); + if (member) + { + user = slack_user_search(workspace, member); + if (user) + weechat_hook_completion_list_add(completion, + user->profile.display_name, + 1, WEECHAT_LIST_POS_BEGINNING); + } + } + } +} + +int slack_completion_channel_nicks_cb(const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_slack_workspace *ptr_workspace; + struct t_slack_channel *ptr_channel; + struct t_slack_channel_member *ptr_member; + struct t_slack_user *ptr_user; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + + ptr_workspace = NULL; + ptr_channel = NULL; + slack_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel); + + if (ptr_channel) + { + switch (ptr_channel->type) + { + case SLACK_CHANNEL_TYPE_CHANNEL: + case SLACK_CHANNEL_TYPE_GROUP: + case SLACK_CHANNEL_TYPE_MPIM: + case SLACK_CHANNEL_TYPE_IM: + for (ptr_member = ptr_channel->members; ptr_member; + ptr_member = ptr_member->next_member) + { + ptr_user = slack_user_search(ptr_workspace, ptr_member->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(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS) + { + slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 0); + } + /* add members whose make highlights on me recently on this channel */ + if (weechat_config_integer(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS) + { + slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 1); + } + /* add self member at the end */ + weechat_hook_completion_list_add(completion, + ptr_workspace->nick, + 1, WEECHAT_LIST_POS_END); + break; + } + } + + return WEECHAT_RC_OK; +} + int slack_completion_workspaces_cb(const void *pointer, void *data, const char *completion_item, struct t_gui_buffer *buffer, @@ -40,6 +128,12 @@ void slack_completion_init() { struct t_config_option *option; const char *default_template; + + + weechat_hook_completion ("nick", + N_("nicks of current Slack channel"), + &slack_completion_channel_nicks_cb, + NULL, NULL); weechat_hook_completion("slack_workspace", N_("slack workspaces"), diff --git a/slack-config.c b/slack-config.c index 06a0b94..62d125e 100644 --- a/slack-config.c +++ b/slack-config.c @@ -15,6 +15,8 @@ struct t_config_file *slack_config_file; struct t_config_section *slack_config_section_workspace_default; struct t_config_section *slack_config_section_workspace; +struct t_config_option *slack_config_look_nick_completion_smart; + struct t_config_option *slack_config_workspace_default[SLACK_WORKSPACE_NUM_OPTIONS]; int slack_config_workspace_check_value_cb(const void *pointer, void *data, @@ -243,6 +245,31 @@ int slack_config_init() if(!slack_config_file) return 0; + ptr_section = weechat_config_new_section( + slack_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(slack_config_file); + slack_config_file = NULL; + return 0; + } + + slack_config_look_nick_completion_smart = weechat_config_new_option ( + slack_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( slack_config_file, "workspace_default", 0, 0, diff --git a/slack-config.h b/slack-config.h index c769419..19d10b3 100644 --- a/slack-config.h +++ b/slack-config.h @@ -7,11 +7,20 @@ #define SLACK_CONFIG_NAME "slack" +enum t_slack_config_nick_completion +{ + SLACK_CONFIG_NICK_COMPLETION_SMART_OFF = 0, + SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS, + SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, +}; + extern struct t_config_file *slack_config_file; extern struct t_config_section *slack_config_section_workspace_default; extern struct t_config_section *slack_config_section_workspace; +extern struct t_config_option *slack_config_look_nick_completion_smart; + extern struct t_config_option *slack_config_workspace_default[]; int slack_config_workspace_check_value_cb(const void *pointer, void *data, From 4e8e378ae5a1e1ddc5551459fd20eae4449d9621 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 14 May 2018 20:18:18 +0100 Subject: [PATCH 056/118] I don't wanna talk about it. (Closes #13) *muffled screams* --- api/slack-api-message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 99f6ac0..3f671ab 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -107,7 +107,7 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, _("%s%s"), slack_user_as_prefix(workspace, ptr_user, NULL), message); - slack_channel_member_speaking_add(channel, ptr_user->profile.display_name, + slack_channel_member_speaking_add(ptr_channel, ptr_user->profile.display_name, weechat_string_has_highlight( message, ptr_user->profile.display_name)); From 59a9b463a3395d1fedb8ced143cdfc74cafcc4bf Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 17 May 2018 18:10:59 +0100 Subject: [PATCH 057/118] Implement the parsing of message shares (attachments) [closes #14] --- README.org | 1 + api/slack-api-message.c | 50 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 0646596..bb06165 100644 --- a/README.org +++ b/README.org @@ -84,6 +84,7 @@ - [ ] Implement handling api message =message.message_changed= - [ ] Implement handling api message =message.message_deleted= - [ ] Implement handling api message =message.message_replied= + - [ ] Implement handling api message =message.file_share= - [ ] Implement sending websocket =typing= message ** TODO [#B] Implement completion engine (milestone v0.3) - [X] +Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]])+ diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 3f671ab..4ec05f0 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -124,6 +124,31 @@ int slack_api_message_message_handle(struct t_slack_workspace *workspace, return 1; } +int slack_api_message_attachment_handle(struct t_slack_workspace *workspace, + const char *channel, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; /* silently ignore if channel hasn't been loaded yet */ + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; /* silently ignore if user hasn't been loaded yet */ + + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message", + _("%s%s"), + "++\t", + text); + + return 1; +} + int slack_api_message_route_message(struct t_slack_workspace *workspace, const char *subtype, json_object *message) @@ -155,6 +180,8 @@ int slack_api_message(struct t_slack_workspace *workspace, json_object *message) { json_object *subtype, *channel, *user, *text, *ts; + json_object *attachments, *attachment, *fallback; + int i, rc; subtype = json_object_object_get(message, "subtype"); if (!subtype) @@ -175,11 +202,32 @@ int slack_api_message(struct t_slack_workspace *workspace, if (!json_valid(ts, workspace)) return 0; - return slack_api_message_message_handle(workspace, + rc = slack_api_message_message_handle(workspace, json_object_get_string(channel), json_object_get_string(user), json_object_get_string(text), json_object_get_string(ts)); + attachments = json_object_object_get(message, "attachments"); + if (json_valid(attachments, workspace)) + { + for (i = json_object_array_length(attachments); i > 0; i--) + { + attachment = json_object_array_get_idx(attachments, i - 1); + if (!json_valid(attachment, workspace)) + continue; + + fallback = json_object_object_get(attachment, "fallback"); + if (!json_valid(fallback, workspace)) + continue; + + slack_api_message_attachment_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user), + json_object_get_string(fallback), + json_object_get_string(ts)); + } + } + return rc; } else { /* special message */ From 64cd31c0b5d14f5a3279d9552e80243c391b99d6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 May 2018 15:14:02 +0100 Subject: [PATCH 058/118] thread_broadcast partial impl --- .../slack-api-message-thread_broadcast.c | 99 +++++++++++++++++++ .../slack-api-message-thread_broadcast.h | 12 +++ 2 files changed, 111 insertions(+) create mode 100644 api/message/slack-api-message-thread_broadcast.c create mode 100644 api/message/slack-api-message-thread_broadcast.h diff --git a/api/message/slack-api-message-thread_broadcast.c b/api/message/slack-api-message-thread_broadcast.c new file mode 100644 index 0000000..1c3c4e5 --- /dev/null +++ b/api/message/slack-api-message-thread_broadcast.c @@ -0,0 +1,99 @@ +// 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 "../../weechat-plugin.h" +#include "../../slack.h" +#include "../../slack-workspace.h" +#include "../../slack-message.h" +#include "../../slack-api.h" +#include "../../slack-channel.h" +#include "../../slack-user.h" +#include "../slack-api-message.h" +#include "slack-api-message-thread_broadcast.h" + +static const char *subtype = "thread_broadcast"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %smessage.%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), subtype, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_thread_broadcast_handle(struct t_slack_workspace *workspace, + json_object *root, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; + + /* + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; // silently ignore if channel hasn't been loaded yet + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; // silently ignore if user hasn't been loaded yet + + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message,slack_thread_broadcast", + _("%s%s"), + slack_user_as_prefix(workspace, ptr_user, NULL), + message); + free(message); + + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + */ + + return 1; +} + +int slack_api_message_thread_broadcast(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *root, *user, *text, *ts; + root = json_object_object_get(message, "root"); + if (!json_valid(root, workspace)) + return 0; + + user = json_object_object_get(message, "user"); + if (!json_valid(user, workspace)) + return 0; + + text = json_object_object_get(message, "text"); + if (!json_valid(text, workspace)) + return 0; + + ts = json_object_object_get(message, "ts"); + if (!json_valid(ts, workspace)) + return 0; + + return slack_api_message_thread_broadcast_handle(workspace, + root, json_object_get_string(user), + json_object_get_string(text), + json_object_get_string(ts)); +} + diff --git a/api/message/slack-api-message-thread_broadcast.h b/api/message/slack-api-message-thread_broadcast.h new file mode 100644 index 0000000..ea56ce7 --- /dev/null +++ b/api/message/slack-api-message-thread_broadcast.h @@ -0,0 +1,12 @@ +// 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/. + +#ifndef _SLACK_API_MESSAGE_THREAD_BROADCAST_H_ +#define _SLACK_API_MESSAGE_THREAD_BROADCAST_H_ + +int slack_api_message_thread_broadcast( + struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_MESSAGE_THREAD_BROADCAST_H*/ From bae8e0226ef20c54bcc265425e90015c5857d8a5 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 May 2018 19:07:36 +0100 Subject: [PATCH 059/118] Fix #16 --- debian/changelog | 2 +- debian/files | 1 - request/slack-request-users-list.c | 4 +++- 3 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 debian/files diff --git a/debian/changelog b/debian/changelog index cbe0a3f..38fc955 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -weechat-slack (0.1.0) sid; urgency=medium +weechat-slack (0.1.5) sid; urgency=medium [ Tony Olagbaiye ] * Initial release. diff --git a/debian/files b/debian/files deleted file mode 100644 index 55d3874..0000000 --- a/debian/files +++ /dev/null @@ -1 +0,0 @@ -weechat-slack_0.1.0_source.buildinfo net optional diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c index a8ec9af..33e2dab 100644 --- a/request/slack-request-users-list.c +++ b/request/slack-request-users-list.c @@ -219,7 +219,9 @@ static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, new_user = slack_user_new(request->workspace, json_object_get_string(id), - json_object_get_string(display_name)); + json_object_get_string(display_name)[0] ? + json_object_get_string(display_name) : + json_object_get_string(name)); bot_id = json_object_object_get(profile, "bot_id"); if (json_valid(bot_id, request->workspace)) From 06d8d19e140f79d90441d1f55891698918af95ba Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 May 2018 19:10:27 +0100 Subject: [PATCH 060/118] Bump README --- README.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index bb06165..4f46388 100644 --- a/README.org +++ b/README.org @@ -15,11 +15,11 @@ [[https://github.com/bqv/weechat-slack/issues][file:https://img.shields.io/github/issues/bqv/weechat-slack.svg]] [[https://github.com/bqv/weechat-slack/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-slack.svg]] [[https://github.com/bqv/weechat-slack/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-slack.svg]] -[[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-slack-yellow.svg]] +[[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-slack-blue.svg]] | Status: | Under Development | | Location: | [[http://github.com/bqv/weechat-slack]] | - | Version: | 0.1.0 | + | Version: | 0.1.5 | | Disclaimer: | Slack's API is a thing of horror | * Description From dc0c43c80cd9e06a3e99b94b3dce5a5c98c27c81 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 May 2018 19:44:48 +0100 Subject: [PATCH 061/118] Decode message formatting in attachment messages --- Makefile | 1 + api/slack-api-message.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9ea5d8e..1636a9a 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ slack-emoji.inc: slack-emoji.pl perl slack-emoji.pl > slack-emoji.inc else slack-emoji.inc: slack-emoji.py + pip install requests env python3 slack-emoji.py > slack-emoji.inc endif diff --git a/api/slack-api-message.c b/api/slack-api-message.c index 4ec05f0..f755c19 100644 --- a/api/slack-api-message.c +++ b/api/slack-api-message.c @@ -138,13 +138,15 @@ int slack_api_message_attachment_handle(struct t_slack_workspace *workspace, if (!ptr_user) return 1; /* silently ignore if user hasn't been loaded yet */ + char *message = slack_message_decode(workspace, text); weechat_printf_date_tags( ptr_channel->buffer, (time_t)atof(ts), "slack_message", _("%s%s"), "++\t", - text); + message); + free(message); return 1; } From f590ef76357141a56a451fb2bfa2a18977a687e5 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 May 2018 20:18:08 +0100 Subject: [PATCH 062/118] Aaaaaaaaaaaaaaaaaaaa Ihateslackihateslackihateslack --- README.org | 9 +- .../slack-api-message-message-changed.c | 104 ++++++++++++++++++ .../slack-api-message-message-changed.h | 12 ++ ...c => slack-api-message-thread-broadcast.c} | 2 +- ...h => slack-api-message-thread-broadcast.h} | 0 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 api/message/slack-api-message-message-changed.c create mode 100644 api/message/slack-api-message-message-changed.h rename api/message/{slack-api-message-thread_broadcast.c => slack-api-message-thread-broadcast.c} (98%) rename api/message/{slack-api-message-thread_broadcast.h => slack-api-message-thread-broadcast.h} (100%) diff --git a/README.org b/README.org index 4f46388..ecf69db 100644 --- a/README.org +++ b/README.org @@ -17,7 +17,7 @@ [[https://github.com/bqv/weechat-slack/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-slack.svg]] [[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-slack-blue.svg]] - | Status: | Under Development | + | Status: | Aaaaaaaaaaaaaaaaa | | Location: | [[http://github.com/bqv/weechat-slack]] | | Version: | 0.1.5 | | Disclaimer: | Slack's API is a thing of horror | @@ -79,7 +79,6 @@ ** TODO [#A] Implement essential api endpoints and events (milestone v0.2) - [X] +Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - [X] +Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - - [ ] Implement handling api message =message.thread_broadcast= - [X] +Implement handling api message =message.bot_message= (see [[http://github.com/bqv/weechat-slack/issues/2][#2]])+ - [ ] Implement handling api message =message.message_changed= - [ ] Implement handling api message =message.message_deleted= @@ -94,7 +93,9 @@ - [ ] Sort nick-completion by recent speakers (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) ** TODO [#B] Implement websocket ping and pong (milestone v0.4) - [ ] Add ping timer and pong handler (see [[http://github.com/bqv/weechat-slack/issues/9][#9]]) -** TODO [#C] Implement remaining api endpoints and events (milestone v0.5) +** TODO [#B] Implement thread handling (milestone v0.5) + - [ ] Implement handling api message =message.thread_broadcast= +** TODO [#C] Implement remaining api endpoints and events (milestone v0.6) - [ ] Support all channel types - [X] +Channels+ - [ ] Groups @@ -102,7 +103,7 @@ - [ ] IMs - [ ] Complete api endpoint set - [ ] Complete api event set -** TODO [#C] Implement full weechat functionality (milestone v0.6) +** TODO [#C] Implement full weechat functionality (milestone v0.7) - [ ] Hook buffer closes - [ ] Relay compatibility - [ ] Config Options diff --git a/api/message/slack-api-message-message-changed.c b/api/message/slack-api-message-message-changed.c new file mode 100644 index 0000000..95b2a29 --- /dev/null +++ b/api/message/slack-api-message-message-changed.c @@ -0,0 +1,104 @@ +// 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 "../../weechat-plugin.h" +#include "../../slack.h" +#include "../../slack-workspace.h" +#include "../../slack-message.h" +#include "../../slack-api.h" +#include "../../slack-channel.h" +#include "../../slack-user.h" +#include "../slack-api-message.h" +#include "slack-api-message-message-changed.h" + +static const char *subtype = "message_changed"; + +static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) +{ + if (!object) + { + weechat_printf( + workspace->buffer, + _("%s%s: error handling websocket %smessage.%s%s message: " + "unexpected response from server"), + weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_color("chat_value"), subtype, weechat_color("reset")); + return 0; + } + + return 1; +} + +int slack_api_message_message_changed_handle(struct t_slack_workspace *workspace, + json_object *root, const char *user, + const char *text, const char *ts) +{ + struct t_slack_channel *ptr_channel; + struct t_slack_user *ptr_user; + struct t_slack_channel_typing *ptr_typing; + + /* + ptr_channel = slack_channel_search(workspace, channel); + if (!ptr_channel) + return 1; // silently ignore if channel hasn't been loaded yet + ptr_user = slack_user_search(workspace, user); + if (!ptr_user) + return 1; // silently ignore if user hasn't been loaded yet + + char *message = slack_message_decode(workspace, text); + weechat_printf_date_tags( + ptr_channel->buffer, + (time_t)atof(ts), + "slack_message,slack_thread_broadcast", + _("%s%s"), + slack_user_as_prefix(workspace, ptr_user, NULL), + message); + free(message); + + ptr_typing = slack_channel_typing_search(ptr_channel, + ptr_user->profile.display_name); + if (ptr_typing) + { + slack_channel_typing_free(ptr_channel, ptr_typing); + slack_channel_typing_cb(ptr_channel, NULL, 0); + } + */ + + return 1; +} + +int slack_api_message_message_changed(struct t_slack_workspace *workspace, + json_object *message) +{ + json_object *channel, *oldmsg, *user, *text, *ts; + channel = json_object_object_get(message, "channel"); + if (!json_valid(channel, workspace)) + return 0; + + oldmsg = json_object_object_get(message, "message"); + if (!json_valid(oldmsg, workspace)) + return 0; + + user = json_object_object_get(oldmsg, "user"); + if (!json_valid(user, workspace)) + return 0; + + text = json_object_object_get(message, "text"); + if (!json_valid(text, workspace)) + return 0; + + ts = json_object_object_get(message, "ts"); + if (!json_valid(ts, workspace)) + return 0; + + return slack_api_message_message_changed_handle(workspace, + json_object_get_string(channel), + json_object_get_string(user), + json_object_get_string(text), + json_object_get_string(ts)); +} + diff --git a/api/message/slack-api-message-message-changed.h b/api/message/slack-api-message-message-changed.h new file mode 100644 index 0000000..2fd4239 --- /dev/null +++ b/api/message/slack-api-message-message-changed.h @@ -0,0 +1,12 @@ +// 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/. + +#ifndef _SLACK_API_MESSAGE_MESSAGE_CHANGED_H_ +#define _SLACK_API_MESSAGE_MESSAGE_CHANGED_H_ + +int slack_api_message_message_changed( + struct t_slack_workspace *workspace, + json_object *message); + +#endif /*SLACK_API_MESSAGE_MESSAGE_CHANGED_H*/ diff --git a/api/message/slack-api-message-thread_broadcast.c b/api/message/slack-api-message-thread-broadcast.c similarity index 98% rename from api/message/slack-api-message-thread_broadcast.c rename to api/message/slack-api-message-thread-broadcast.c index 1c3c4e5..ce59478 100644 --- a/api/message/slack-api-message-thread_broadcast.c +++ b/api/message/slack-api-message-thread-broadcast.c @@ -13,7 +13,7 @@ #include "../../slack-channel.h" #include "../../slack-user.h" #include "../slack-api-message.h" -#include "slack-api-message-thread_broadcast.h" +#include "slack-api-message-thread-broadcast.h" static const char *subtype = "thread_broadcast"; diff --git a/api/message/slack-api-message-thread_broadcast.h b/api/message/slack-api-message-thread-broadcast.h similarity index 100% rename from api/message/slack-api-message-thread_broadcast.h rename to api/message/slack-api-message-thread-broadcast.h From 8a8ad87012ebb841ae70425aafbf7ad4d7634a54 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 25 Jun 2021 22:27:32 +0100 Subject: [PATCH 063/118] add libstrophe --- .gitmodules | 3 +++ json-c | 2 +- libstrophe | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 160000 libstrophe diff --git a/.gitmodules b/.gitmodules index 633f768..f67858f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "json-c"] path = json-c url = https://github.com/json-c/json-c +[submodule "libstrophe"] + path = libstrophe + url = https://github.com/strophe/libstrophe diff --git a/json-c b/json-c index c75ebe8..75bf657 160000 --- a/json-c +++ b/json-c @@ -1 +1 @@ -Subproject commit c75ebe8973b1f03d3b3ef429c114e8d2192dc0c0 +Subproject commit 75bf657cc285c1b726492ed6af3645ea95fe17ac diff --git a/libstrophe b/libstrophe new file mode 160000 index 0000000..2d5424b --- /dev/null +++ b/libstrophe @@ -0,0 +1 @@ +Subproject commit 2d5424bcff4e9d810b73444b02708f69743ff65d From 6d8af6ed0ff3cc9cae50601c48837b2c7a34a23d Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 25 Jun 2021 23:20:49 +0100 Subject: [PATCH 064/118] skel --- .gitignore | 4 +- .gitmodules | 3 - Makefile | 53 +- debian/changelog | 31 - debian/compat | 1 - debian/control | 26 - debian/copyright | 2865 ------------------------------- debian/rules | 17 - debian/source/lintian-overrides | 6 - libwebsockets | 1 - slack-emoji.pl | 97 -- slack-emoji.py | 59 - xmpp.c | 106 ++ xmpp.h | 14 + 14 files changed, 142 insertions(+), 3141 deletions(-) delete mode 100644 debian/changelog delete mode 100644 debian/compat delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100755 debian/rules delete mode 100644 debian/source/lintian-overrides delete mode 160000 libwebsockets delete mode 100644 slack-emoji.pl delete mode 100755 slack-emoji.py create mode 100644 xmpp.c create mode 100644 xmpp.h diff --git a/.gitignore b/.gitignore index a49f82a..28a8c3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ -# Prerequisites -debian/weechat-slack/ -.debhelper/ +*~ compile_commands.json cscope* .depend diff --git a/.gitmodules b/.gitmodules index f67858f..1c84e5a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "libwebsockets"] - path = libwebsockets - url = https://github.com/warmcat/libwebsockets [submodule "json-c"] path = json-c url = https://github.com/json-c/json-c diff --git a/Makefile b/Makefile index 1636a9a..b40bb4a 100644 --- a/Makefile +++ b/Makefile @@ -4,15 +4,17 @@ ifdef DEBUG endif RM=rm -f FIND=find -CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibwebsockets/include -Ijson-c +CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibstrophe -Ijson-c LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) -LDLIBS=-lgnutls +LDLIBS= PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib INSTALL ?= /usr/bin/install -SRCS=slack.c \ +SRCS=xmpp.c \ + +OLDSRCS=slack.c \ slack-api.c \ slack-buffer.c \ slack-channel.c \ @@ -41,35 +43,26 @@ SRCS=slack.c \ request/slack-request-conversations-members.c \ request/slack-request-emoji-list.c \ request/slack-request-users-list.c -OBJS=$(subst .c,.o,$(SRCS)) libwebsockets/lib/libwebsockets.a json-c/libjson-c.a +OBJS=$(subst .c,.o,$(SRCS)) libstrophe/.libs/libstrophe.a json-c/libjson-c.a -all: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a weechat-slack +all: libstrophe/.libs/libstrophe.a json-c/libjson-c.a weechat-xmpp -weechat-slack: $(OBJS) - $(CC) $(LDFLAGS) -o slack.so $(OBJS) $(LDLIBS) +weechat-xmpp: $(OBJS) + $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(LDLIBS) -ifeq ($(shell which python),) -slack-emoji.inc: slack-emoji.pl - cpan LWP::Simple - cpan JSON - perl slack-emoji.pl > slack-emoji.inc -else -slack-emoji.inc: slack-emoji.py - pip install requests - env python3 slack-emoji.py > slack-emoji.inc -endif - -libwebsockets/lib/libwebsockets.a: - cd libwebsockets && env CFLAGS= LDFLAGS= cmake -DLWS_STATIC_PIC=ON -DLWS_WITH_SHARED=OFF -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITH_LIBEV=OFF -DLWS_WITH_LIBUV=OFF -DLWS_WITH_LIBEVENT=OFF -DCMAKE_BUILD_TYPE=DEBUG . - $(MAKE) -C libwebsockets +libstrophe/.libs/libstrophe.a: + cd libstrophe && ./bootstrap.sh && env CFLAGS= LDFLAGS= ./configure + $(MAKE) -C libstrophe +libstrophe: libstrophe/.libs/libstrophe.a json-c/libjson-c.a: cd json-c && env CFLAGS= LDFLAGS= cmake -DCMAKE_C_FLAGS=-fPIC . $(MAKE) -C json-c json-c-static +json-c: json-c/libjson-c.a depend: .depend -.depend: libwebsockets/lib/libwebsockets.a json-c/libjson-c.a $(SRCS) +.depend: libstrophe/.libs/libstrophe.a json-c/libjson-c.a $(SRCS) $(RM) ./.depend $(CC) $(CFLAGS) -MM $^>>./.depend @@ -78,8 +71,9 @@ tidy: clean: $(RM) $(OBJS) - $(MAKE) -C libwebsockets clean - $(MAKE) -C json-c clean + $(MAKE) -C libstrophe clean || true + $(MAKE) -C libwebsockets clean || true + $(MAKE) -C json-c clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true git submodule update --init --recursive || true @@ -87,18 +81,13 @@ clean: distclean: clean $(RM) *~ .depend -install: slack.so +install: xmpp.so ifeq ($(shell id -u),0) - $(INSTALL) -s -t $(DESTDIR)$(LIBDIR)/weechat/plugins -D -m 0644 slack.so + $(INSTALL) -s -t $(DESTDIR)$(LIBDIR)/weechat/plugins -D -m 0644 xmpp.so else - $(INSTALL) -s -t ~/.weechat/plugins -D -m 0755 slack.so + $(INSTALL) -s -t ~/.weechat/plugins -D -m 0755 xmpp.so endif -package-debian: - env ARCH=i386 gbp buildpackage --git-arch=i386 --git-ignore-new --git-pbuilder - env ARCH=amd64 gbp buildpackage --git-arch=amd64 --git-ignore-new --git-pbuilder -# gbp buildpackage -S --git-ignore-new - .PHONY: tags cs tags: diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 38fc955..0000000 --- a/debian/changelog +++ /dev/null @@ -1,31 +0,0 @@ -weechat-slack (0.1.5) sid; urgency=medium - - [ Tony Olagbaiye ] - * Initial release. - * Bot messages - * Slackbot responses - * CTags - * Fix channel mentions. Closes #2 - * License headers - * Administration - * Add TODO to readme - * Fix makefile to find libwebsockets.h - * Build libwebsockets first - * Revert libwebsockets header change - * Build libjson-c before too - * Typo - * Move sanitizers to debug build - * Fix make install - * Fix install finally - * Just remove `make install` from travis - * Update README.org - * Handle message.me_message (ref #5) - * Monkeypatch message.bot_message for undoc'd slackbot msgs. Fixes #6 - * Implement chat.meMessage for /me (closes #5) - * Update README.org - * Update README.org - * Describe debug process - - [ Bao ] - - -- Bao Thu, 10 May 2018 15:18:26 +0100 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index b4de394..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -11 diff --git a/debian/control b/debian/control deleted file mode 100644 index 26b93b6..0000000 --- a/debian/control +++ /dev/null @@ -1,26 +0,0 @@ -Source: weechat-slack -Section: net -Priority: optional -Maintainer: Tony Olagbaiye -Build-Depends: - cmake, pkg-config, - debhelper (>= 11), - libssl-dev, - libgnutls28-dev, - perl -Standards-Version: 4.0.0 -Homepage: https://weechat.org/ -Vcs-Git: https://github.com/bqv/weechat-slack.git -Vcs-Browser: https://github.com/bqv/weechat-slack - -Package: weechat-slack -Architecture: any -Depends: - weechat (>= 1.7), - ${shlibs:Depends}, - ${misc:Depends} -Description: Fast, light and extensible chat client - Slack plugin - WeeChat (Wee Enhanced Environment for Chat) is a fast and light chat client - for many operating systems. Everything can be done with a keyboard. - . - This package provides the Slack API plugin. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 172e0b9..0000000 --- a/debian/copyright +++ /dev/null @@ -1,2865 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: weechat-slack -Source: -# -# Please double check copyright with the licensecheck(1) command. - -Files: .depend - .gitattributes - .gitignore - .gitmodules - Makefile - api/.slack-api-message.c.swp - api/message/.slack-api-message-bot-message.c.swp - api/message/slack-api-message-unimplemented.c - api/message/slack-api-message-unimplemented.h - api/message/slack-api-message-unimplemented.o - api/slack-api-error.c - api/slack-api-error.h - api/slack-api-error.o - api/slack-api-hello.c - api/slack-api-hello.h - api/slack-api-hello.o - api/slack-api-message.c - api/slack-api-message.h - api/slack-api-message.o - api/slack-api-user-typing.c - api/slack-api-user-typing.h - api/slack-api-user-typing.o - compile_commands.json - debian/control - json-c/.deps/arraylist.Plo - json-c/.deps/debug.Plo - json-c/.deps/json_c_version.Plo - json-c/.deps/json_object.Plo - json-c/.deps/json_object_iterator.Plo - json-c/.deps/json_pointer.Plo - json-c/.deps/json_tokener.Plo - json-c/.deps/json_util.Plo - json-c/.deps/json_visit.Plo - json-c/.deps/linkhash.Plo - json-c/.deps/printbuf.Plo - json-c/.deps/random_seed.Plo - json-c/.deps/strerror_override.Plo - json-c/.editorconfig - json-c/.git - json-c/.gitignore - json-c/.travis.yml - json-c/AUTHORS - json-c/Android.configure.mk - json-c/CMakeCache.txt - json-c/CMakeFiles/3.9.0/CMakeCCompiler.cmake - json-c/CMakeFiles/3.9.0/CMakeCXXCompiler.cmake - json-c/CMakeFiles/3.9.0/CMakeDetermineCompilerABI_C.bin - json-c/CMakeFiles/3.9.0/CMakeDetermineCompilerABI_CXX.bin - json-c/CMakeFiles/3.9.0/CMakeSystem.cmake - json-c/CMakeFiles/3.9.0/CompilerIdC/CMakeCCompilerId.c - json-c/CMakeFiles/3.9.0/CompilerIdC/a.out - json-c/CMakeFiles/3.9.0/CompilerIdCXX/CMakeCXXCompilerId.cpp - json-c/CMakeFiles/3.9.0/CompilerIdCXX/a.out - json-c/CMakeFiles/CMakeDirectoryInformation.cmake - json-c/CMakeFiles/CMakeOutput.log - json-c/CMakeFiles/Makefile.cmake - json-c/CMakeFiles/Makefile2 - json-c/CMakeFiles/TargetDirectories.txt - json-c/CMakeFiles/cmake.check_cache - json-c/CMakeFiles/feature_tests.bin - json-c/CMakeFiles/feature_tests.c - json-c/CMakeFiles/feature_tests.cxx - json-c/CMakeFiles/json-c-static.dir/C.includecache - json-c/CMakeFiles/json-c-static.dir/DependInfo.cmake - json-c/CMakeFiles/json-c-static.dir/arraylist.c.o - json-c/CMakeFiles/json-c-static.dir/build.make - json-c/CMakeFiles/json-c-static.dir/cmake_clean.cmake - json-c/CMakeFiles/json-c-static.dir/cmake_clean_target.cmake - json-c/CMakeFiles/json-c-static.dir/debug.c.o - json-c/CMakeFiles/json-c-static.dir/depend.internal - json-c/CMakeFiles/json-c-static.dir/depend.make - json-c/CMakeFiles/json-c-static.dir/flags.make - json-c/CMakeFiles/json-c-static.dir/json_c_version.c.o - json-c/CMakeFiles/json-c-static.dir/json_object.c.o - json-c/CMakeFiles/json-c-static.dir/json_object_iterator.c.o - json-c/CMakeFiles/json-c-static.dir/json_pointer.c.o - json-c/CMakeFiles/json-c-static.dir/json_tokener.c.o - json-c/CMakeFiles/json-c-static.dir/json_util.c.o - json-c/CMakeFiles/json-c-static.dir/json_visit.c.o - json-c/CMakeFiles/json-c-static.dir/link.txt - json-c/CMakeFiles/json-c-static.dir/linkhash.c.o - json-c/CMakeFiles/json-c-static.dir/printbuf.c.o - json-c/CMakeFiles/json-c-static.dir/progress.make - json-c/CMakeFiles/json-c-static.dir/random_seed.c.o - json-c/CMakeFiles/json-c-static.dir/strerror_override.c.o - json-c/CMakeFiles/json-c.dir/DependInfo.cmake - json-c/CMakeFiles/json-c.dir/build.make - json-c/CMakeFiles/json-c.dir/cmake_clean.cmake - json-c/CMakeFiles/json-c.dir/depend.make - json-c/CMakeFiles/json-c.dir/flags.make - json-c/CMakeFiles/json-c.dir/link.txt - json-c/CMakeFiles/json-c.dir/progress.make - json-c/CMakeFiles/progress.marks - json-c/Doxyfile - json-c/INSTALL - json-c/Makefile - json-c/Makefile.am - json-c/NEWS - json-c/README - json-c/README.md - json-c/RELEASE_CHECKLIST.txt - json-c/STYLE.txt - json-c/appveyor.yml - json-c/autoconf-archive/README.txt - json-c/autogen.sh - json-c/autom4te.cache/requests - json-c/autom4te.cache/traces.1 - json-c/autom4te.cache/traces.2 - json-c/cmake_install.cmake - json-c/config.h - json-c/config.h.in - json-c/config.h.win32 - json-c/configure.ac - json-c/fuzz/README.md - json-c/fuzz/tokener_parse_ex_fuzzer.cc - json-c/fuzz/tokener_parse_ex_fuzzer.dict - json-c/include/config.h - json-c/include/json_config.h - json-c/issues_closed_for_0.13.md - json-c/json-c-uninstalled.pc - json-c/json-c-uninstalled.pc.in - json-c/json-c.pc - json-c/json-c.pc.in - json-c/json_config.h - json-c/json_config.h.in - json-c/json_config.h.win32 - json-c/json_inttypes.h - json-c/json_object_iterator.c - json-c/json_object_iterator.h - json-c/json_visit.h - json-c/libjson-c.a - json-c/libjson.c - json-c/math_compat.h - json-c/snprintf_compat.h - json-c/stamp-h1 - json-c/stamp-h2 - json-c/strdup_compat.h - json-c/strerror_override.c - json-c/strerror_override.h - json-c/strerror_override_private.h - json-c/tests/.deps/test1.Po - json-c/tests/.deps/test1Formatted-parse_flags.Po - json-c/tests/.deps/test1Formatted-test1.Po - json-c/tests/.deps/test2.Po - json-c/tests/.deps/test2Formatted-parse_flags.Po - json-c/tests/.deps/test2Formatted-test2.Po - json-c/tests/.deps/test4.Po - json-c/tests/.deps/testReplaceExisting.Po - json-c/tests/.deps/test_cast.Po - json-c/tests/.deps/test_charcase.Po - json-c/tests/.deps/test_compare.Po - json-c/tests/.deps/test_deep_copy.Po - json-c/tests/.deps/test_double_serializer.Po - json-c/tests/.deps/test_float.Po - json-c/tests/.deps/test_int_add.Po - json-c/tests/.deps/test_json_pointer.Po - json-c/tests/.deps/test_locale.Po - json-c/tests/.deps/test_null.Po - json-c/tests/.deps/test_parse.Po - json-c/tests/.deps/test_parse_int64.Po - json-c/tests/.deps/test_printbuf.Po - json-c/tests/.deps/test_set_serializer.Po - json-c/tests/.deps/test_set_value.Po - json-c/tests/.deps/test_util_file.Po - json-c/tests/.deps/test_visit.Po - json-c/tests/Makefile.am - json-c/tests/parse_flags.c - json-c/tests/parse_flags.h - json-c/tests/test-defs.sh - json-c/tests/test1.c - json-c/tests/test1.expected - json-c/tests/test1.test - json-c/tests/test1Formatted_plain.expected - json-c/tests/test1Formatted_pretty.expected - json-c/tests/test1Formatted_spaced.expected - json-c/tests/test2.c - json-c/tests/test2.expected - json-c/tests/test2.test - json-c/tests/test2Formatted_plain.expected - json-c/tests/test2Formatted_pretty.expected - json-c/tests/test2Formatted_spaced.expected - json-c/tests/test4.c - json-c/tests/test4.expected - json-c/tests/testReplaceExisting.c - json-c/tests/testReplaceExisting.expected - json-c/tests/test_basic.test - json-c/tests/test_cast.c - json-c/tests/test_cast.expected - json-c/tests/test_charcase.c - json-c/tests/test_charcase.expected - json-c/tests/test_compare.c - json-c/tests/test_compare.expected - json-c/tests/test_deep_copy.c - json-c/tests/test_deep_copy.expected - json-c/tests/test_double_serializer.c - json-c/tests/test_double_serializer.expected - json-c/tests/test_float.expected - json-c/tests/test_int_add.c - json-c/tests/test_int_add.expected - json-c/tests/test_json_pointer.c - json-c/tests/test_json_pointer.expected - json-c/tests/test_locale.c - json-c/tests/test_locale.expected - json-c/tests/test_null.c - json-c/tests/test_null.expected - json-c/tests/test_parse.c - json-c/tests/test_parse.expected - json-c/tests/test_parse_int64.c - json-c/tests/test_parse_int64.expected - json-c/tests/test_printbuf.c - json-c/tests/test_printbuf.expected - json-c/tests/test_set_serializer.c - json-c/tests/test_set_serializer.expected - json-c/tests/test_set_value.c - json-c/tests/test_set_value.expected - json-c/tests/test_util_file.c - json-c/tests/test_util_file.expected - json-c/tests/test_visit.c - json-c/tests/test_visit.expected - json-c/tests/valid.json - json-c/vasprintf_compat.h - libwebsockets/.git - libwebsockets/.gitignore - libwebsockets/.travis.yml - libwebsockets/CMakeCache.txt - libwebsockets/CMakeFiles/3.9.0/CMakeCCompiler.cmake - libwebsockets/CMakeFiles/3.9.0/CMakeDetermineCompilerABI_C.bin - libwebsockets/CMakeFiles/3.9.0/CMakeSystem.cmake - libwebsockets/CMakeFiles/3.9.0/CompilerIdC/CMakeCCompilerId.c - libwebsockets/CMakeFiles/3.9.0/CompilerIdC/a.out - libwebsockets/CMakeFiles/CMakeDirectoryInformation.cmake - libwebsockets/CMakeFiles/CMakeError.log - libwebsockets/CMakeFiles/CMakeOutput.log - libwebsockets/CMakeFiles/CMakeRuleHashes.txt - libwebsockets/CMakeFiles/Export/lib/cmake/libwebsockets/LibwebsocketsTargets-debug.cmake - libwebsockets/CMakeFiles/Export/lib/cmake/libwebsockets/LibwebsocketsTargets.cmake - libwebsockets/CMakeFiles/LibwebsocketsConfig.cmake - libwebsockets/CMakeFiles/Makefile.cmake - libwebsockets/CMakeFiles/Makefile2 - libwebsockets/CMakeFiles/TargetDirectories.txt - libwebsockets/CMakeFiles/cmake.check_cache - libwebsockets/CMakeFiles/dist.dir/DependInfo.cmake - libwebsockets/CMakeFiles/dist.dir/build.make - libwebsockets/CMakeFiles/dist.dir/cmake_clean.cmake - libwebsockets/CMakeFiles/dist.dir/progress.make - libwebsockets/CMakeFiles/feature_tests.bin - libwebsockets/CMakeFiles/feature_tests.c - libwebsockets/CMakeFiles/progress.marks - libwebsockets/CMakeFiles/websockets.dir/C.includecache - libwebsockets/CMakeFiles/websockets.dir/DependInfo.cmake - libwebsockets/CMakeFiles/websockets.dir/build.make - libwebsockets/CMakeFiles/websockets.dir/cmake_clean.cmake - libwebsockets/CMakeFiles/websockets.dir/cmake_clean_target.cmake - libwebsockets/CMakeFiles/websockets.dir/depend.internal - libwebsockets/CMakeFiles/websockets.dir/depend.make - libwebsockets/CMakeFiles/websockets.dir/flags.make - libwebsockets/CMakeFiles/websockets.dir/lib/alloc.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/context.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/event-libs/poll/poll.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/libwebsockets.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/misc/base64-decode.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/misc/lws-ring.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/misc/sha-1.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/output.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/plat/lws-plat-unix.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/pollfd.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/h1/ops-h1.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/client/client-handshake.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/client/client.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/header.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/server/lws-spa.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/server/parsers.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/http/server/server.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/listen/ops-listen.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/pipe/ops-pipe.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/raw/ops-raw.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/client-parser-ws.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/client-ws.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/ops-ws.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/roles/ws/server-ws.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/service.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/tls/openssl/openssl-client.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/tls/openssl/openssl-server.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/tls/openssl/ssl.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/tls/tls-client.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/tls/tls-server.c.o - libwebsockets/CMakeFiles/websockets.dir/lib/tls/tls.c.o - libwebsockets/CMakeFiles/websockets.dir/link.txt - libwebsockets/CMakeFiles/websockets.dir/progress.make - libwebsockets/CMakeLists.txt - libwebsockets/CPackConfig.cmake - libwebsockets/CPackSourceConfig.cmake - libwebsockets/Kconfig - libwebsockets/LibwebsocketsConfig.cmake - libwebsockets/LibwebsocketsConfigVersion.cmake - libwebsockets/LibwebsocketsTargets.cmake - libwebsockets/Makefile - libwebsockets/Makefile.projbuild - libwebsockets/README.md - libwebsockets/READMEs/README-plugin-sshd-base.md - libwebsockets/READMEs/README.build.md - libwebsockets/READMEs/README.esp32.md - libwebsockets/READMEs/README.generic-sessions.md - libwebsockets/READMEs/README.generic-table.md - libwebsockets/READMEs/README.lws-meta.md - libwebsockets/READMEs/README.lwsws.md - libwebsockets/READMEs/README.plugin-acme.md - libwebsockets/READMEs/README.problems.md - libwebsockets/READMEs/mainpage.md - libwebsockets/READMEs/release-checklist - libwebsockets/appveyor.yml - libwebsockets/cmake/FindLibWebSockets.cmake - libwebsockets/cmake/FindOpenSSLbins.cmake - libwebsockets/cmake/LibwebsocketsConfig.cmake.in - libwebsockets/cmake/LibwebsocketsConfigVersion.cmake.in - libwebsockets/cmake/UseRPMTools.cmake - libwebsockets/cmake/lws_config.h.in - libwebsockets/cmake/lws_config_private.h.in - libwebsockets/cmake_install.cmake - libwebsockets/component.mk - libwebsockets/contrib/Android.mk - libwebsockets/contrib/abi/README.md - libwebsockets/contrib/abi/libwebsockets.json - libwebsockets/contrib/abi/lws-abi-update.sh - libwebsockets/contrib/android-make-script.sh - libwebsockets/contrib/cross-aarch64.cmake - libwebsockets/contrib/cross-arm-linux-gnueabihf.cmake - libwebsockets/contrib/cross-esp32.cmake - libwebsockets/contrib/cross-ming.cmake - libwebsockets/contrib/cross-openwrt-makefile - libwebsockets/contrib/cross-w32.cmake - libwebsockets/contrib/cross-w64.cmake - libwebsockets/doc-assets/lws-overview.png - libwebsockets/doc-assets/lws-smp-example.png - libwebsockets/doc-assets/lws-smp-ov.png - libwebsockets/doc-assets/lwsgt-overview.png - libwebsockets/include/lws_config.h - libwebsockets/lib/alloc.c - libwebsockets/lib/event-libs/README.md - libwebsockets/lib/plat/lws-plat-optee.c - libwebsockets/lib/plat/lws-plat-win.c - libwebsockets/lib/roles/README.md - libwebsockets/lib/roles/h2/huftable.h - libwebsockets/lib/roles/http/client/client-handshake.c - libwebsockets/lib/roles/http/lextable-strings.h - libwebsockets/lib/roles/http/lextable.h - libwebsockets/lib/roles/http/server/rewrite.c - libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.h - libwebsockets/lib/roles/ws/ext/extension.c - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_stack.h - libwebsockets/libwebsockets.dox - libwebsockets/libwebsockets.pc - libwebsockets/libwebsockets_static.pc - libwebsockets/lws_config.h - libwebsockets/lws_config_private.h - libwebsockets/lwsws/etc-logrotate.d-lwsws - libwebsockets/lwsws/etc-lwsws-conf-EXAMPLE - libwebsockets/lwsws/etc-lwsws-conf.d-localhost-EXAMPLE - libwebsockets/lwsws/usr-lib-systemd-system-lwsws.service - libwebsockets/minimal-examples/README.md - libwebsockets/minimal-examples/client-server/README.md - libwebsockets/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt - libwebsockets/minimal-examples/client-server/minimal-ws-proxy/README.md - libwebsockets/minimal-examples/client-server/minimal-ws-proxy/mount-origin/favicon.ico - libwebsockets/minimal-examples/client-server/minimal-ws-proxy/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-client/README.md - libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt - libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/README.md - libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/warmcat.com.cer - libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt - libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/README.md - libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh - libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/warmcat.com.cer - libwebsockets/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt - libwebsockets/minimal-examples/http-client/minimal-http-client-multi/README.md - libwebsockets/minimal-examples/http-client/minimal-http-client-multi/selftest.sh - libwebsockets/minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer - libwebsockets/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt - libwebsockets/minimal-examples/http-client/minimal-http-client-post/README.md - libwebsockets/minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer - libwebsockets/minimal-examples/http-client/minimal-http-client-post/selftest.sh - libwebsockets/minimal-examples/http-client/minimal-http-client/CMakeLists.txt - libwebsockets/minimal-examples/http-client/minimal-http-client/README.md - libwebsockets/minimal-examples/http-client/minimal-http-client/selftest.sh - libwebsockets/minimal-examples/http-client/minimal-http-client/warmcat.com.cer - libwebsockets/minimal-examples/http-server/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/ba-passwords - libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-secret-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/localhost-100y.cert - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/localhost-100y.key - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/localhost-100y.cert - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/localhost-100y.key - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.cert - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.key - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-smp/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-sse/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/localhost-100y.cert - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/localhost-100y.key - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/http-server/minimal-http-server/CMakeLists.txt - libwebsockets/minimal-examples/http-server/minimal-http-server/README.md - libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/favicon.ico - libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/index.html - libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/raw/README.md - libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt - libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/README.md - libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt - libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/README.md - libwebsockets/minimal-examples/raw/minimal-raw-file/CMakeLists.txt - libwebsockets/minimal-examples/raw/minimal-raw-file/README.md - libwebsockets/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt - libwebsockets/minimal-examples/raw/minimal-raw-vhost/README.md - libwebsockets/minimal-examples/selftests-library.sh - libwebsockets/minimal-examples/selftests.sh - libwebsockets/minimal-examples/ws-client/README.md - libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt - libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/README.md - libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt - libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/README.md - libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt - libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/README.md - libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/libwebsockets.org.cer - libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh - libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt - libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/README.md - libwebsockets/minimal-examples/ws-server/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-broker/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-broker/mount-origin/favicon.ico - libwebsockets/minimal-examples/ws-server/minimal-ws-broker/mount-origin/index.html - libwebsockets/minimal-examples/ws-server/minimal-ws-broker/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/favicon.ico - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/index.html - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/mount-origin/favicon.ico - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/mount-origin/index.html - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/mount-origin/favicon.ico - libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/mount-origin/index.html - libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/mount-origin/favicon.ico - libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/mount-origin/libwebsockets.org-logo.png - libwebsockets/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt - libwebsockets/minimal-examples/ws-server/minimal-ws-server/README.md - libwebsockets/minimal-examples/ws-server/minimal-ws-server/mount-origin/favicon.ico - libwebsockets/minimal-examples/ws-server/minimal-ws-server/mount-origin/index.html - libwebsockets/minimal-examples/ws-server/minimal-ws-server/mount-origin/libwebsockets.org-logo.png - libwebsockets/plugin-standalone/CMakeLists.txt - libwebsockets/plugins/generic-sessions/assets/lwsgs-logo.png - libwebsockets/plugins/generic-sessions/assets/md5.min.js - libwebsockets/plugins/generic-sessions/assets/post-register-fail.html - libwebsockets/plugins/generic-sessions/assets/seats.jpg - libwebsockets/plugins/generic-sessions/assets/sent-forgot-ok.html - libwebsockets/plugins/generic-table/assets/lwsgt.js - libwebsockets/plugins/lwsws-logo.png - libwebsockets/plugins/ssh-base/crypto/chacha.c - libwebsockets/plugins/ssh-base/crypto/ed25519.c - libwebsockets/plugins/ssh-base/crypto/fe25519.c - libwebsockets/plugins/ssh-base/crypto/fe25519.h - libwebsockets/plugins/ssh-base/crypto/ge25519.c - libwebsockets/plugins/ssh-base/crypto/ge25519.h - libwebsockets/plugins/ssh-base/crypto/ge25519_base.data - libwebsockets/plugins/ssh-base/crypto/poly1305.c - libwebsockets/plugins/ssh-base/crypto/sc25519.c - libwebsockets/plugins/ssh-base/crypto/sc25519.h - libwebsockets/plugins/ssh-base/crypto/smult_curve25519_ref.c - libwebsockets/plugins/ssh-base/include/lws-plugin-sshd-static-build-includes.h - libwebsockets/scripts/attack.sh - libwebsockets/scripts/autobahn-test.sh - libwebsockets/scripts/build-gcov.sh - libwebsockets/scripts/client-ca/certindex.txt - libwebsockets/scripts/client-ca/create-ca.sh - libwebsockets/scripts/client-ca/create-client-cert.sh - libwebsockets/scripts/client-ca/create-server-cert.sh - libwebsockets/scripts/client-ca/serial - libwebsockets/scripts/client-ca/tmp.cnf - libwebsockets/scripts/esp32.mk - libwebsockets/scripts/gcov.sh - libwebsockets/scripts/h2load-smp.sh - libwebsockets/scripts/h2load.sh - libwebsockets/scripts/h2spec.sh - libwebsockets/scripts/libwebsockets.spec - libwebsockets/scripts/travis_control.sh - libwebsockets/scripts/travis_install.sh - libwebsockets/test-apps/.gitignore - libwebsockets/test-apps/android/app/build.gradle - libwebsockets/test-apps/android/app/src/main/jni/Android.mk - libwebsockets/test-apps/android/app/src/main/jni/Application.mk - libwebsockets/test-apps/android/app/src/main/libs/placeholder - libwebsockets/test-apps/android/app/src/main/res/drawable/warmcat.png - libwebsockets/test-apps/android/app/src/main/res/mipmap-hdpi/ic_launcher.png - libwebsockets/test-apps/android/app/src/main/res/mipmap-mdpi/ic_launcher.png - libwebsockets/test-apps/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png - libwebsockets/test-apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png - libwebsockets/test-apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png - libwebsockets/test-apps/android/build.gradle - libwebsockets/test-apps/android/gradle.properties - libwebsockets/test-apps/android/settings.gradle - libwebsockets/test-apps/candide.zip - libwebsockets/test-apps/favicon.ico - libwebsockets/test-apps/http2.png - libwebsockets/test-apps/libwebsockets-test-server.service - libwebsockets/test-apps/libwebsockets.org-logo.png - libwebsockets/test-apps/lws-cgi-test.sh - libwebsockets/test-apps/lws-common.js - libwebsockets/test-apps/lws-ssh-test-keys - libwebsockets/test-apps/lws-ssh-test-keys.pub - libwebsockets/test-apps/private/index.html - libwebsockets/test-apps/wss-over-h2.png - libwebsockets/win32port/libwebsockets.nsi - libwebsockets/win32port/version.rc.in - libwebsockets/win32port/win32helpers/getopt.h - libwebsockets/win32port/win32helpers/gettimeofday.c - libwebsockets/win32port/win32helpers/gettimeofday.h - libwebsockets/win32port/zlib/ZLib.vcxproj - libwebsockets/win32port/zlib/ZLib.vcxproj.filters - libwebsockets/win32port/zlib/crc32.h - libwebsockets/win32port/zlib/inffixed.h - libwebsockets/win32port/zlib/trees.h - request/#slack-request-conversations-members.c# - request/slack-request-channels-list.c - request/slack-request-channels-list.h - request/slack-request-channels-list.o - request/slack-request-chat-postmessage.c - request/slack-request-chat-postmessage.h - request/slack-request-chat-postmessage.o - request/slack-request-conversations-members.c - request/slack-request-conversations-members.h - request/slack-request-conversations-members.o - request/slack-request-users-list.c - request/slack-request-users-list.h - request/slack-request-users-list.o - slack-api.c - slack-api.h - slack-api.o - slack-buffer.c - slack-buffer.h - slack-buffer.o - slack-channel.c - slack-channel.h - slack-channel.o - slack-command.c - slack-command.h - slack-command.o - slack-config.c - slack-config.h - slack-config.o - slack-input.c - slack-input.h - slack-input.o - slack-message.c - slack-message.h - slack-message.o - slack-oauth.c - slack-oauth.h - slack-oauth.o - slack-request.c - slack-request.h - slack-request.o - slack-teaminfo.c - slack-teaminfo.h - slack-teaminfo.o - slack-user.c - slack-user.h - slack-user.o - slack-workspace.c - slack-workspace.h - slack-workspace.o - slack.c - slack.h - slack.o -Copyright: __NO_COPYRIGHT_NOR_LICENSE__ -License: __NO_COPYRIGHT_NOR_LICENSE__ - -Files: libwebsockets/include/libwebsockets.h - libwebsockets/lib/context.c - libwebsockets/lib/event-libs/libev/libev.c - libwebsockets/lib/event-libs/libev/private.h - libwebsockets/lib/event-libs/libevent/libevent.c - libwebsockets/lib/event-libs/libevent/private.h - libwebsockets/lib/event-libs/libuv/libuv.c - libwebsockets/lib/event-libs/libuv/private.h - libwebsockets/lib/event-libs/poll/poll.c - libwebsockets/lib/event-libs/poll/private.h - libwebsockets/lib/libwebsockets.c - libwebsockets/lib/libwebsockets.h - libwebsockets/lib/misc/jws/jwk.c - libwebsockets/lib/misc/jws/jws.c - libwebsockets/lib/misc/lejp.c - libwebsockets/lib/misc/lws-ring.c - libwebsockets/lib/misc/peer-limits.c - libwebsockets/lib/output.c - libwebsockets/lib/plat/lws-plat-esp32.c - libwebsockets/lib/plat/lws-plat-unix.c - libwebsockets/lib/pollfd.c - libwebsockets/lib/private-libwebsockets.h - libwebsockets/lib/roles/cgi/cgi-server.c - libwebsockets/lib/roles/cgi/ops-cgi.c - libwebsockets/lib/roles/cgi/private.h - libwebsockets/lib/roles/h1/ops-h1.c - libwebsockets/lib/roles/h1/private.h - libwebsockets/lib/roles/h2/hpack.c - libwebsockets/lib/roles/h2/http2.c - libwebsockets/lib/roles/h2/ops-h2.c - libwebsockets/lib/roles/h2/private.h - libwebsockets/lib/roles/http/client/client.c - libwebsockets/lib/roles/http/header.c - libwebsockets/lib/roles/http/server/access-log.c - libwebsockets/lib/roles/http/server/lejp-conf.c - libwebsockets/lib/roles/http/server/lws-spa.c - libwebsockets/lib/roles/http/server/parsers.c - libwebsockets/lib/roles/http/server/ranges.c - libwebsockets/lib/roles/http/server/server.c - libwebsockets/lib/roles/listen/ops-listen.c - libwebsockets/lib/roles/pipe/ops-pipe.c - libwebsockets/lib/roles/raw/ops-raw.c - libwebsockets/lib/roles/ws/client-parser-ws.c - libwebsockets/lib/roles/ws/client-ws.c - libwebsockets/lib/roles/ws/ext/extension-permessage-deflate.c - libwebsockets/lib/roles/ws/ops-ws.c - libwebsockets/lib/roles/ws/private.h - libwebsockets/lib/roles/ws/server-ws.c - libwebsockets/lib/service.c - libwebsockets/lib/tls/mbedtls/lws-genhash.c - libwebsockets/lib/tls/mbedtls/lws-genrsa.c - libwebsockets/lib/tls/mbedtls/mbedtls-client.c - libwebsockets/lib/tls/mbedtls/mbedtls-server.c - libwebsockets/lib/tls/mbedtls/ssl.c - libwebsockets/lib/tls/openssl/lws-genhash.c - libwebsockets/lib/tls/openssl/lws-genrsa.c - libwebsockets/lib/tls/openssl/openssl-client.c - libwebsockets/lib/tls/openssl/openssl-server.c - libwebsockets/lib/tls/openssl/ssl.c - libwebsockets/lib/tls/private.h - libwebsockets/lib/tls/tls-client.c - libwebsockets/lib/tls/tls-server.c - libwebsockets/lib/tls/tls.c - libwebsockets/plugins/protocol_esp32_lws_ota.c - libwebsockets/plugins/ssh-base/include/lws-plugin-ssh.h - libwebsockets/plugins/ssh-base/include/lws-ssh.h - libwebsockets/plugins/ssh-base/kex-25519.c - libwebsockets/plugins/ssh-base/sshd.c - libwebsockets/plugins/ssh-base/telnet.c - libwebsockets/test-apps/test-lejp.c -Copyright: 2010-2018 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: json-c/fuzz/build.sh - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl3.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_code.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_dbg.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_lib.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_methods.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_types.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/ssl_x509.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/tls1.h - libwebsockets/lib/tls/mbedtls/wrapper/include/internal/x509_vfy.h - libwebsockets/lib/tls/mbedtls/wrapper/include/openssl/ssl.h - libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h - libwebsockets/lib/tls/mbedtls/wrapper/include/platform/ssl_port.h - libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_cert.c - libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_lib.c - libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_methods.c - libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_pkey.c - libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_stack.c - libwebsockets/lib/tls/mbedtls/wrapper/library/ssl_x509.c - libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_pm.c - libwebsockets/lib/tls/mbedtls/wrapper/platform/ssl_port.c -Copyright: 2015-2016 Espressif Systems (Shanghai) PTE LTD - 2018 Google Inc. -License: Apache-2.0 - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - . - http://www.apache.org/licenses/LICENSE-2.0 - . - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - . - On Debian systems, the complete text of the Apache License Version 2.0 - can be found in `/usr/share/common-licenses/Apache-2.0'. - -Files: json-c/tests/test_float.c - libwebsockets/READMEs/README.test-apps.md - libwebsockets/lib/misc/daemonize.c - libwebsockets/win32port/zlib/adler32.c - libwebsockets/win32port/zlib/compress.c - libwebsockets/win32port/zlib/gzguts.h - libwebsockets/win32port/zlib/gzlib.c - libwebsockets/win32port/zlib/gzread.c - libwebsockets/win32port/zlib/gzwrite.c - libwebsockets/win32port/zlib/inffast.c - libwebsockets/win32port/zlib/inftrees.c - libwebsockets/win32port/zlib/trees.c - libwebsockets/win32port/zlib/uncompr.c - libwebsockets/win32port/zlib/zconf.h - libwebsockets/win32port/zlib/zutil.c -Copyright: 1995-2010 Jean-loup Gailly - 1995-2010 Jean-loup Gailly. For conditions of distribution and use, see copyright notice in zlib.h - 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h - 2006-2013 Andy Green - 2010-2011 Andy Green licensed under LGPL2.1 Compiled with SSL support, not using it Listening on port 7681 server sees client connect accepted v06 connection Spamming 360 random fragments - 2016 Rainer Gerhards Released under ASL 2.0 -License: __NO_LICENSE__ - -Files: libwebsockets/lwsws/main.c - libwebsockets/plugins/protocol_lws_mirror.c - libwebsockets/plugins/protocol_lws_server_status.c - libwebsockets/plugins/protocol_lws_status.c - libwebsockets/test-apps/android/README - libwebsockets/test-apps/android/app/src/main/java/org/libwebsockets/client/LwsService.java - libwebsockets/test-apps/android/app/src/main/java/org/libwebsockets/client/MainActivity.java - libwebsockets/test-apps/android/app/src/main/java/org/libwebsockets/client/ThreadService.java - libwebsockets/test-apps/android/app/src/main/jni/LwsService.cpp - libwebsockets/test-apps/test-client.c - libwebsockets/test-apps/test-server-libev.c - libwebsockets/test-apps/test-server-libevent.c - libwebsockets/test-apps/test-server.c -Copyright: 2010-2018 Andy Green - 2016 Alexander Bruines -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - The person who associated a work with this deed has dedicated - the work to the public domain by waiving all of his or her rights - to the work worldwide under copyright law, including all related - and neighboring rights, to the extent allowed by law. You can copy, - modify, distribute and perform the work, even for commercial purposes, - all without asking permission. - . - The test apps are intended to be adapted for use in your code, which - may be proprietary. So unlike the library itself, they are licensed - Public Domain. - -Files: json-c/arraylist.c - json-c/arraylist.h - json-c/debug.c - json-c/json_c_version.c - json-c/json_object.c - json-c/json_object.h - json-c/json_tokener.h - json-c/json_util.c - json-c/linkhash.c - json-c/linkhash.h - json-c/random_seed.c -Copyright: 2004-2013 Metaparadigm Pte. Ltd. Michael Clark - 2009 Hewlett-Packard Development Company, L.P. - 2012 Eric Haszlakiewicz -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - -Files: libwebsockets/lib/misc/smtp.c - libwebsockets/plugins/generic-sessions/handlers.c - libwebsockets/plugins/generic-sessions/private-lwsgs.h - libwebsockets/plugins/generic-sessions/protocol_generic_sessions.c - libwebsockets/plugins/generic-sessions/protocol_lws_messageboard.c - libwebsockets/plugins/generic-sessions/utils.c - libwebsockets/plugins/generic-table/protocol_table_dirlisting.c -Copyright: 2010-2017 Andy Green -License: LGPL-2.1 - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - . - You should have received a copy of the GNU General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: json-c/autoconf-archive/m4/libtool.m4 - json-c/autoconf-archive/m4/ltoptions.m4 - json-c/autoconf-archive/m4/ltsugar.m4 - json-c/autoconf-archive/m4/ltversion.m4 - json-c/autoconf-archive/m4/lt~obsolete.m4 -Copyright: 1996-2015 Free Software Foundation, Inc. -License: PERMISSIVE - This file is free software; the Free Software Foundation gives - unlimited permission to copy and/or distribute it, with or without - modifications, as long as this notice is preserved. - -Files: libwebsockets/plugin-standalone/protocol_example_standalone.c - libwebsockets/plugins/protocol_client_loopback_test.c - libwebsockets/plugins/protocol_dumb_increment.c - libwebsockets/plugins/protocol_lws_sshd_demo.c - libwebsockets/plugins/protocol_post_demo.c -Copyright: 2010-2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - The person who associated a work with this deed has dedicated - the work to the public domain by waiving all of his or her rights - to the work worldwide under copyright law, including all related - and neighboring rights, to the extent allowed by law. You can copy, - modify, distribute and perform the work, even for commercial purposes, - all without asking permission. - . - These test plugins are intended to be adapted for use in your code, which - may be proprietary. So unlike the library itself, they are licensed - Public Domain. - -Files: json-c/autom4te.cache/output.0 - json-c/autom4te.cache/output.1 - json-c/autom4te.cache/output.2 - json-c/configure -Copyright: 1992-2012 Free Software Foundation, Inc. -License: PERMISSIVE - This configure script is free software; the Free Software Foundation - gives unlimited permission to copy, distribute and modify it. - -Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c - libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c - libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/protocol_lws_minimal_server_echo.c - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c -Copyright: 2010-2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - The protocol shows how to send and receive bulk messages over a ws connection - that optionally may have the permessage-deflate extension negotiated on it. - -Files: libwebsockets/win32port/zlib/deflate.h - libwebsockets/win32port/zlib/inffast.h - libwebsockets/win32port/zlib/inflate.h - libwebsockets/win32port/zlib/zutil.h -Copyright: 1995-2010 Jean-loup Gailly For conditions of distribution and use, see copyright notice in zlib.h - 1995-2010 Jean-loup Gailly. For conditions of distribution and use, see copyright notice in zlib.h - 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h -License: __UNKNOWN__ - WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - -Files: json-c/autoconf-archive/m4/ax_append_compile_flags.m4 - json-c/autoconf-archive/m4/ax_append_flag.m4 - json-c/autoconf-archive/m4/ax_check_compile_flag.m4 - json-c/autoconf-archive/m4/ax_compile_check_sizeof.m4 -Copyright: 2008 Guido U. Draheim - 2008 Kaveh Ghazi - 2011 Maarten Bosmans -License: GPL-3.0+ with unknown exception *** check multiple exceptions *** - This program is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your - option) any later version. - . - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - Public License for more details. - . - You should have received a copy of the GNU General Public License along - with this program. If not, see . - . - As a special exception, the respective Autoconf Macro's copyright owner - gives unlimited permission to copy, distribute and modify the configure - scripts that are the output of Autoconf when processing the Macro. You - need not follow the terms of the GNU General Public License when using - or distributing such scripts, even though portions of the text of the - Macro appear in them. The GNU General Public License (GPL) does govern - all other use of the material that constitutes the Autoconf Macro. - . - This special exception to the GPL applies to versions of the Autoconf - Macro released by the Autoconf Archive. When you make and distribute a - modified version of the Autoconf Macro, you may extend this special - exception to the GPL to apply to your modified version as well. - . - On Debian systems, the complete text of the GNU General Public License - Version 3 can be found in `/usr/share/common-licenses/GPL-3'. - -Files: json-c/debug.h - json-c/json_object_private.h - json-c/random_seed.h -Copyright: 2004-2013 Metaparadigm Pte. Ltd. Michael Clark - 2009 Hewlett-Packard Development Company, L.P. -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - @brief Do not use, json-c internal, may be changed or removed at any time. - -Files: libwebsockets/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c - libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c - libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c -Copyright: 2010-2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - -Files: json-c/compile - json-c/missing - json-c/test-driver -Copyright: 1996-2014 Free Software Foundation, Inc. -License: GPL-2.0+ with autoconf exception - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - . - As a special exception to the GNU General Public License, if you - distribute this file as part of a program that contains a - configuration script generated by Autoconf, you may include it under - the same distribution terms that you use for the rest of that program. - . - On Debian systems, the complete text of the GNU General Public License - Version 2 can be found in `/usr/share/common-licenses/GPL-2'. - -Files: libwebsockets/lib/event-libs/private.h - libwebsockets/lib/roles/private.h -Copyright: 2010-2018 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - This is included from private-libwebsockets.h - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: libwebsockets/plugins/protocol_esp32_lws_group.c - libwebsockets/plugins/protocol_esp32_lws_scan.c -Copyright: 2017 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA* - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c - libwebsockets/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http server that can serve both normal static - content and server-side event connections. - . - To keep it simple, it serves the static stuff from the subdirectory - "./mount-origin" of the directory it was started in. - . - You can change that by changing mount.origin below. - -Files: libwebsockets/lib/roles/h2/minihuf.c - libwebsockets/lib/roles/http/minilex.c -Copyright: 2011-2014 Andy Green -License: __UNKNOWN__ - Licensed under LGPL2 - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/protocol_lws_minimal.c - libwebsockets/minimal-examples/ws-server/minimal-ws-server/protocol_lws_minimal.c -Copyright: 2010-2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This version holds a single message at a time, which may be lost if a new - message comes. See the minimal-ws-server-ring sample for the same thing - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c - libwebsockets/minimal-examples/ws-server/minimal-ws-server-pmd/minimal-ws-server-pmd.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws. - . - To keep it simple, it serves stuff in the subdirectory "./mount-origin" of - the directory it was started in. - You can change that by changing mount.origin. - -Files: json-c/json_pointer.c - json-c/json_visit.c -Copyright: 2016 Alexandru Ardelean. - 2016 Eric Haszlakiewicz -License: __UNKNOWN__ - This is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/minimal-http-server.c - libwebsockets/minimal-examples/http-server/minimal-http-server/minimal-http-server.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws. - . - To keep it simple, it serves stuff from the subdirectory - "./mount-origin" of the directory it was started in. - You can change that by changing mount.origin below. - -Files: json-c/json_tokener.c - json-c/printbuf.c -Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark - 2008-2009 Yahoo! Inc. -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - The copyrights to the contents of this file are licensed under the MIT License - (http://www.opensource.org/licenses/mit-license.php) - -Files: libwebsockets/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c - libwebsockets/minimal-examples/http-client/minimal-http-client/minimal-http-client.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the a minimal http client using lws. - . - It visits https://warmcat.com/ and receives the html page there. You - can dump the page data by changing the #if 0 below. - -Files: libwebsockets/lib/misc/romfs.c - libwebsockets/lib/misc/romfs.h -Copyright: 2017 National Institute of Advanced Industrial Science and Technology (AIST) -License: BSD-3-Clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - . - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - . - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - . - Neither the name of AIST nor the names of its contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - . - On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" - License can be found in `/usr/share/common-licenses/BSD'. - -Files: libwebsockets/win32port/win32helpers/getopt.c - libwebsockets/win32port/win32helpers/getopt_long.c -Copyright: 1987-1996 The Regents of the University of California. -License: BSD-4-Clause-UC - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by the University of - California, Berkeley and its contributors. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -Files: json-c/Makefile.in - json-c/tests/Makefile.in -Copyright: 1994-2017 Free Software Foundation, Inc. -License: __AUTO_PERMISSIVE__ - Autogenerated files with permissive licenses. - -Files: json-c/install-sh -Copyright: 1994 X Consortium -License: MIT - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to - deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- - TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - . - Except as contained in this notice, the name of the X Consortium shall not - be used in advertising or otherwise to promote the sale, use or other deal- - ings in this Software without prior written authorization from the X Consor- - tium. - . - FSF changes to this file are in the public domain. - . - Calling this script install-sh is preferred over install.sh, to prevent - 'make' implicit rules from creating a file called install from it - when there is no Makefile. - . - This script is compatible with the BSD install script, but was written - from scratch. - -Files: libwebsockets/win32port/zlib/zlib.h -Copyright: 1995-2010 Jean-loup Gailly and Mark Adler -License: Zlib - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - . - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - . - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - . - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - . - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). - -Files: libwebsockets/lib/misc/base64-decode.c -Copyright: __NO_COPYRIGHT__ in: libwebsockets/lib/misc/base64-decode.c -License: Expat - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated - documentation files (the "Software"), to deal in the - Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, - sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, - subject to the following conditions: - . - The above copyright notice and this permission notice shall - be included in all copies or substantial portions of the - Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY - KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS - OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - . - VERSION HISTORY: - Bob Trower 08/04/01 -- Create Version 0.00.00B - . - I cleaned it up quite a bit to match the (linux kernel) style of the rest - of libwebsockets; this version is under LGPL2.1 + SLE like the rest of lws - since he explicitly allows sublicensing, but I give the URL above so you can - get the original with Bob's super-liberal terms directly if you prefer. - -Files: weechat-plugin.h -Copyright: 2003-2018 Sébastien Helleu -License: GPL-3.0+ - This file is part of WeeChat, the extensible chat client. - . - WeeChat is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - . - WeeChat is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with WeeChat. If not, see . - . - On Debian systems, the complete text of the GNU General Public License - Version 3 can be found in `/usr/share/common-licenses/GPL-3'. - -Files: libwebsockets/test-apps/fuzxy.c -Copyright: 2016 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - fuzxy is designed to go on the client path - . - [ client <-> fuzxy ] <-> server - . - you can arrange that with, eg, - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: libwebsockets/lib/roles/http/private.h -Copyright: 2010-2018 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - This is included from private-libwebsockets.h if either H1 or H2 roles are - enabled - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: libwebsockets/plugins/acme-client/protocol_lws_acme_client.c -Copyright: 2017 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - Acme is in a big messy transition at the moment from a homebrewed api - to an IETF one. The old repo for the homebrew api (they currently - implement) is marked up as deprecated and "not accurate[ly] reflect[ing]" - what they implement, but the IETF standard, currently at v7 is not yet - implemented at let's encrypt (ETA Jan 2018). - . - This implementation follows draft 7 of the IETF standard, and falls back - to whatever differences exist for Boulder's tls-sni-01 challenge. The - tls-sni-02 support is there but nothing to test it against at the time of - writing (Nov 1 2017). - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: libwebsockets/plugins/protocol_esp32_lws_reboot_to_factory.c -Copyright: 2017 Andy Green -License: LGPL-2.1 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - This is intended to be mounted somewhere in your ESP32 user app... if the - client touched the mount, the plugin hangs up and reboots into the - factory mode one second later. - . - The factory mode will reassociate with the same IP with the same MAC - shortly afterwards and be accessible by the same IP / mDNS name. - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: libwebsockets/lib/roles/http/server/fops-zip.c -Copyright: 2017 Andy Green - 2017 Per Bothner -License: LGPL-2.1 - MIT License - . - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - ( copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - . - lws rewrite: - . - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation: - version 2.1 of the License. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA - . - On Debian systems, the complete text of the GNU Lesser General Public License - Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. - -Files: json-c/autoconf-archive/m4/ax_require_defined.m4 -Copyright: 2014 Mike Frysinger -License: PERMISSIVE - Copying and distribution of this file, with or without modification, are - permitted in any medium without royalty provided the copyright notice - and this notice are preserved. This file is offered as-is, without any - warranty. - -Files: json-c/tests/Makefile -Copyright: 1994-2017 Free Software Foundation, Inc. -License: PERMISSIVE - This Makefile.in is free software; the Free Software Foundation - gives unlimited permission to copy and/or distribute it, - with or without modifications, as long as this notice is preserved. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY, to the extent permitted by law; without - even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. - -Files: json-c/aclocal.m4 -Copyright: 1996-2017 Free Software Foundation, Inc. -License: PERMISSIVE - This file is free software; the Free Software Foundation - gives unlimited permission to copy and/or distribute it, - with or without modifications, as long as this notice is preserved. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY, to the extent permitted by law; without - even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. - -Files: json-c/json_util.h -Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - @brief Miscllaneous utility functions and macros. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/http2.png -Copyright: __NO_COPYRIGHT__ in: libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/http2.png -License: __UNKNOWN__ - _MANY_NON_ASCII_(10chars. over 20chars.) starting with: 8—S¯×P*<ÎY‚@!„À{O - _MANY_NON_ASCII_(3chars. over 4chars.) starting with: ¡µ@© - R - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/minimal-http-server-basicauth.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http server with a second mount that - is protected using a password file and basic auth. - . - To keep it simple, it serves the static stuff from the subdirectory - "./mount-origin" of the directory it was started in. - . - You can change that by changing mount.origin below. - -Files: libwebsockets/minimal-examples/raw/minimal-raw-file/minimal-raw-file.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates adopting a file descriptor into the lws event - loop. - -Files: json-c/CMakeLists.txt -Copyright: __NO_COPYRIGHT__ in: json-c/CMakeLists.txt -License: __UNKNOWN__ - Licensed under the MIT license. See LICENSE file in the project root for full license information. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http server that performs POST with a couple - of parameters. It dumps the parameters to the console log and redirects - to another page. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http[s] server that can work with any of the - supported event loop backends, or the default poll() one. - . - To keep it simple, it serves stuff from the subdirectory - "./mount-origin" of the directory it was started in. - You can change that by changing mount.origin below. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws that - uses a libuv event loop created outside lws. It shows how lws can - participate in someone else's event loop and clean up after itself. - . - You choose the event loop to work with at runtime, by giving the - --uv, --event or --ev switch. Lws has to have been configured to build the - selected event lib support. - . - To keep it simple, it serves stuff from the subdirectory - "./mount-origin" of the directory it was started in. - You can change that by changing mount.origin below. - -Files: libwebsockets/win32port/zlib/crc32.c -Copyright: 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h -License: __UNKNOWN__ - Thanks to Rodney Brown for his contribution of faster - CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - tables for updating the shift register in one step with three exclusive-ors - instead of four steps with four exclusive-ors. This results in about a - factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - -Files: json-c/config.log -Copyright: 2017 Free Software Foundation, Inc. -License: __UNKNOWN__ - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -Files: libwebsockets/READMEs/README.coding.md -Copyright: __NO_COPYRIGHT__ in: libwebsockets/READMEs/README.coding.md -License: __UNKNOWN__ - For these reasons and the response I got trying to raise these issues with - them, if you have a choice about event loop, I would gently encourage you - to avoid libev. Where lws uses an event loop itself, eg in lwsws, we use - libuv. - . - @section extopts Extension option control from user code - . - User code may set per-connection extension options now, using a new api - -Files: json-c/config.status -Copyright: 2012 Free Software Foundation, Inc. -License: __UNKNOWN__ - This config.status script is free software; the Free Software Foundation - gives unlimited permission to copy, distribute and modify it." - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http server that can produce dynamic http - content as well as static content. - . - To keep it simple, it serves the static stuff from the subdirectory - "./mount-origin" of the directory it was started in. - . - You can change that by changing mount.origin below. - -Files: libwebsockets/win32port/zlib/inftrees.h -Copyright: 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h -License: __UNKNOWN__ - WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - . - Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. - -Files: libwebsockets/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates integrating somebody else's connected tcp - socket into the lws event loop as a RAW wsi. It's interesting in - the kind of situation where you already have a connected socket - in your application, and you need to hand it over to lws to deal with. - . - Lws supports "adopting" these foreign sockets. - . - If you simply want a connected client raw socket using lws alone, you - -Files: libwebsockets/test-apps/test-sshd.c -Copyright: 2017 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - The person who associated a work with this deed has dedicated - the work to the public domain by waiving all of his or her rights - to the work worldwide under copyright law, including all related - and neighboring rights, to the extent allowed by law. You can copy, - modify, distribute and perform the work, even for commercial purposes, - all without asking permission. - . - The test apps are intended to be adapted for use in your code, which - may be proprietary. So unlike the library itself, they are licensed - Public Domain. - . - This test app listens on port 2200 for authorized ssh connections. Run it - using - . - $ sudo libwebsockets-test-sshd - . - Connect to it using the test private key with: - . - $ ssh -p 2200 -i /usr/local/share/libwebsockets-test-server/lws-ssh-test-keys anyuser@127.0.0.1 - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-echo/minimal-ws-server-echo.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a ws server that echoes back what it was sent, in a way - compatible with autobahn -m fuzzingclient - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-broker/minimal-ws-broker.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws, - with an added publish / broker / subscribe ws server. - . - To keep it simple, it serves stuff in the subdirectory "./mount-origin" of - the directory it was started in. - You can change that by changing mount.origin. - -Files: libwebsockets/win32port/zlib/inflate.c -Copyright: 1995-2010 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h -License: __UNKNOWN__ - Change history: - . - 1.2.beta0 24 Nov 2002 - - First version -- complete rewrite of inflate to simplify code, avoid - creation of window when not needed, minimize use of window when it is - needed, make inffast.c even faster, implement gzip decoding, and to - improve code readability and style over the previous zlib inflate code - . - 1.2.beta1 25 Nov 2002 - - Use pointers for available input and output checking in inffast.c - - Remove input and output counters in inffast.c - -Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a ws client that sends bulk data in multiple - ws fragments, in a way compatible with per-message deflate. - . - It shows how to send huge messages without needing a lot of memory. - . - Build and start the minimal-examples/ws-server/minmal-ws-server-pmd-bulk - example first. Running this sends a large message to the server and - exits. - . - If you give both sides the -n commandline option, it disables permessage- - deflate compression extension. - -Files: json-c/printbuf.h -Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark - 2008-2009 Yahoo! Inc. -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - The copyrights to the contents of this file are licensed under the MIT License - (http://www.opensource.org/licenses/mit-license.php) - . - @brief Internal string buffer handing. Unless you're writing a - -Files: libwebsockets/cmake/FindGit.cmake -Copyright: Kitware Inc. -License: __UNKNOWN__ - See COPYRIGHT.txt - or http://www.slicer.org/copyright/copyright.txt for details. - . - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - . - This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc. - and was partially funded by NIH grant 3P41RR013218-12S1 - . - AG 2013-02-18: I got it from here - https://github.com/Slicer/Slicer/blob/master/CMake/FindGit.cmake - license is BSD - . - The module defines the following variables: - -Files: json-c/json_c_version.h -Copyright: 2012-2017 Eric Haszlakiewicz -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - @brief Methods for retrieving the json-c version. - -Files: json-c/autom4te.cache/traces.0 -Copyright: 2011 Free Software Foundation, Inc. -License: __UNKNOWN__ - This config.lt script is free software; the Free Software Foundation - gives unlimited permision to copy, distribute and modify it." - -Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a ws "publisher" to go with the minimal-ws-broker - example. - . - Two threads are spawned that produce messages to be sent to the broker, - via a local ringbuffer. Locking is provided to make ringbuffer access - threadsafe. - . - When a nailed-up client connection to the broker is established, the - ringbuffer is sent to the broker, which distributes the events to all - connected clients. - -Files: libwebsockets/plugins/protocol_lws_raw_test.c -Copyright: 2010-2017 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - The person who associated a work with this deed has dedicated - the work to the public domain by waiving all of his or her rights - to the work worldwide under copyright law, including all related - and neighboring rights, to the extent allowed by law. You can copy, - modify, distribute and perform the work, even for commercial purposes, - all without asking permission. - . - These test plugins are intended to be adapted for use in your code, which - may be proprietary. So unlike the library itself, they are licensed - Public Domain. - . - This plugin test both raw file descriptors and raw socket descriptors. It - can test both or just one depending on how you configure it. libwebsockets- - test-server-v2.0 is set up to test both. - . - RAW File Descriptor Testing - -Files: libwebsockets/win32port/zlib/infback.c -Copyright: 1995-2009 Mark Adler For conditions of distribution and use, see copyright notice in zlib.h -License: __UNKNOWN__ - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - -Files: libwebsockets/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the a minimal http client using lws and POST. - . - It POSTs both form data and a file to the form at - https://libwebsockets.org/testserver/formtest and dumps - the html page received generated by the POST handler. - -Files: libwebsockets/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates integrating a raw tcp listener into the lws event loop. - . - This demo doesn't have any http or ws support. You can connect to it - using netcat. If you make multiple connections to it, things typed in one - netcat session are broadcast to all netcat connections. - . - $ nc localhost 7681 - . - You can add more vhosts with things like http or ws support, it's as it is - for clarity. - . - The main point is the apis and ways of managing raw sockets are almost - identical to http or ws mode sockets in lws. The callback names for raw - wsi are changed to be specific to RAW mode is all. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http server that performs POST with a couple - of parameters and a file upload, all in multipart (mime) form mode. - It saves the uploaded file in the current directory, dumps the parameters to - the console log and redirects to another page. - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws, - with an added websocket chat server using a ringbuffer. - . - To keep it simple, it serves stuff in the subdirectory "./mount-origin" of - the directory it was started in. - You can change that by changing mount.origin. - -Files: libwebsockets/test-apps/android/app/src/main/jni/NativeLibs.mk -Copyright: 2016 Alexander Bruines -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - The person who associated a work with this deed has dedicated - the work to the public domain by waiving all of his or her rights - to the work worldwide under copyright law, including all related - and neighboring rights, to the extent allowed by law. You can copy, - modify, distribute and perform the work, even for commercial purposes, - all without asking permission. - . - The test apps are intended to be adapted for use in your code, which - may be proprietary. So unlike the library itself, they are licensed - Public Domain. - . - This makefile is fully intergrated with this Android Studio project and - it will be called automaticaly when you build the project with Gradle. - . - The source packages for the libraries will be automaticaly downloaded. - Alternativly you can provide your own sources by placing the following - files in the 'jni' directory: - . - zlib-1.2.8.tar.gz - openssl-1.0.2g.tar.gz - libwebsockets.tar.gz - . - This makefile was tested with the latest NDK/SDK and Android Studio at the - time of this writing. As these software packages evolve changes to this - makefile may be needed or it may become obselete... - . - This makefile was made for use in Linux but you may be able to edit it - and make it work under Windows. - . - At least on Debian, building openssl requires package xutils-dev - for makedepend. Ofcourse the standard development packages must also be - installed, but xutils-dev is not that obvious in this case... - . - Makedepend will most likely print a lot of warnings during the 'make depend' - stage of building openssl. In this case these warnings can be safely ignored. - . - Include Application.mk but do not complain if it is not found - -Files: json-c/json.h -Copyright: 2004-2005 Metaparadigm Pte. Ltd. Michael Clark - 2009 Hewlett-Packard Development Company, L.P. -License: __UNKNOWN__ - This library is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - @brief A convenience header that may be included instead of other individual ones. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/minimal-http-server-form-get.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal http server that performs a form GET with a couple - of parameters. It dumps the parameters to the console log and redirects - to another page. - -Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-echo/minimal-ws-client-echo.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a ws client that echoes back what it was sent, in a - way compatible with autobahn -m fuzzingserver - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal multithreaded http server you can make with lws. - . - To keep it simple, it serves stuff in the subdirectory "./mount-origin" of - the directory it was started in. - You can change that by changing mount.origin. - . - Also for simplicity the number of threads is set in the code... note that - -Files: libwebsockets/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the a minimal ws client using lws. - . - It connects to https://libwebsockets.org/ and makes a - wss connection to the dumb-increment protocol there. While - connected, it prints the numbers it is being sent by - dumb-increment protocol. - -Files: libwebsockets/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the a minimal http client using lws, which makes - 8 downloads simultaneously from warmcat.com. - . - Currently that takes the form of 8 individual simultaneous tcp and - tls connections, which happen concurrently. Notice that the ordering - of the returned payload may be intermingled for the various connections. - . - By default the connections happen all together at the beginning and operate - concurrently, which is fast. However this is resource-intenstive, there are - 8 tcp connections, 8 tls tunnels on both the client and server. You can - instead opt to have the connections happen one after the other inside a - single tcp connection and tls tunnel, using HTTP/1.1 pipelining. To be - eligible to be pipelined on another existing connection to the same server, - -Files: libwebsockets/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the a minimal http client using lws. - -Files: libwebsockets/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates integrating a connected udp - socket into the lws event loop as a RAW wsi. It's interesting in - the kind of situation where you already have a connected socket - in your application, and you need to hand it over to lws to deal with. - . - Lws supports "adopting" these foreign sockets, and also has a helper API - to create, bind, and adopt them inside lws. - -Files: libwebsockets/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws, - with three extra lines giving it tls (ssl) capabilities, which in - turn allow operation with HTTP/2 if lws was configured for it. - . - To keep it simple, it serves stuff from the subdirectory - "./mount-origin" of the directory it was started in. - . - You can change that by changing mount.origin below. - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-broker/protocol_lws_minimal.c -Copyright: 2010-2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This implements a minimal "broker", for systems that look like this - . - [ publisher ws client ] <-> [ ws server broker ws server ] <-> [ ws client subscriber ] - . - The "publisher" role is to add data to the broker. - . - The "subscriber" role is to hear about all data added to the system. - . - The "broker" role is to manage incoming data from publishers and pass it out - to subscribers. - . - Any number of publishers and subscribers are supported. - . - This example implements a single ws server, using one ws protocol, that treats ws - connections as being in publisher or subscriber mode according to the URL the ws - connection was made to. ws connections to "/publisher" URL are understood to be - publishing data and to any other URL, subscribing. - -Files: libwebsockets/win32port/zlib/deflate.c -Copyright: 1995-2010 Jean-loup Gailly and Mark Adler For conditions of distribution and use, see copyright notice in zlib.h -License: __UNKNOWN__ - ALGORITHM - . - The "deflation" process depends on being able to identify portions - of the input text which are identical to earlier input (within a - sliding window trailing behind the input currently being processed). - . - The most straightforward technique turns out to be the fastest for - most input files: try all possible matches and select the longest. - The key feature of this algorithm is that insertions into the string - dictionary are very simple and thus fast, and deletions are avoided - completely. Insertions are performed at each input character, whereas - string matches are performed only when the previous match ends. So it - is preferable to spend more time in matches to allow very fast string - insertions and avoid deletions. The matching algorithm for small - strings is inspired from that of Rabin & Karp. A brute force approach - is used to find longer strings when a small match has been found. - A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - (by Leonid Broukhis). - A previous version of this file used a more sophisticated algorithm - (by Fiala and Greene) which is guaranteed to run in linear amortized - time, but has a larger average cost, uses more memory and is patented. - However the F&G algorithm may be faster for some highly redundant - -Files: json-c/json_pointer.h -Copyright: 2016 Alexadru Ardelean. -License: __UNKNOWN__ - This is free software; you can redistribute it and/or modify - it under the terms of the MIT license. See COPYING for details. - . - @brief JSON Pointer (RFC 6901) implementation for retrieving - objects from a json-c object tree. - -Files: libwebsockets/minimal-examples/client-server/minimal-ws-proxy/minimal-ws-proxy.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws, - with an added websocket proxy distributing what is received on a - dumb-increment wss connection to https://libwebsockets.org to all - browsers connected to this server. - . - To keep it simple, it serves stuff in the subdirectory "./mount-origin" of - the directory it was started in. - You can change that by changing mount.origin. - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates a minimal ws server that can cooperate with - other threads cleanly. Two other threads are started, which fill - a ringbuffer with strings at 10Hz. - . - The actual work and thread spawning etc are done in the protocol - -Files: libwebsockets/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c -Copyright: 2018 Andy Green -License: __UNKNOWN__ - This file is made available under the Creative Commons CC0 1.0 - Universal Public Domain Dedication. - . - This demonstrates the most minimal http server you can make with lws, - with an added websocket chat server. - . - To keep it simple, it serves stuff in the subdirectory "./mount-origin" of - the directory it was started in. - You can change that by changing mount.origin. - -Files: libwebsockets/lib/misc/getifaddrs.c -Copyright: 2000-2001 Kungliga Tekniska H�gskolan (Royal Institute of Technology, Stockholm, Sweden). -License: BSD-3-Clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - . - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - . - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - . - 3. Neither the name of the Institute nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - . - originally downloaded from - . - http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c - . - On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" - License can be found in `/usr/share/common-licenses/BSD'. - -Files: libwebsockets/lib/misc/getifaddrs.h -Copyright: 2000 Kungliga Tekniska H�gskolan (Royal Institute of Technology, Stockholm, Sweden). -License: BSD-3-Clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - . - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - . - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - . - 3. Neither the name of the Institute nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - . - $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ - . - On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" - License can be found in `/usr/share/common-licenses/BSD'. - -Files: libwebsockets/lib/misc/sha-1.c -Copyright: 1995-1997 and 1998 WIDE Project. -License: BSD-3-Clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the project nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - . - FIPS pub 180-1: Secure Hash Algorithm (SHA-1) - based on: http://csrc.nist.gov/fips/fip180-1.txt - implemented by Jun-ichiro itojun Itoh - . - On Debian systems, the complete text of the BSD 3-clause "New" or "Revised" - License can be found in `/usr/share/common-licenses/BSD'. - -Files: json-c/libtool -Copyright: 2014 Free Software Foundation, Inc. -License: GPL-2.0 with libtool exception - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - . - GNU Libtool is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of of the License, or - (at your option) any later version. - . - As a special exception to the GNU General Public License, if you - distribute this file as part of a program or library that is built - using GNU Libtool, you may include this file under the same - distribution terms that you use for the rest of that program. - . - GNU Libtool is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - . - The names of the tagged configurations supported by this script. - . - On Debian systems, the complete text of the GNU General Public License - Version 2 can be found in `/usr/share/common-licenses/GPL-2'. - -Files: json-c/ltmain.sh -Copyright: 1996-2015 Free Software Foundation, Inc. -License: GPL-2.0+ with libtool exception - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - . - GNU Libtool is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - . - As a special exception to the GNU General Public License, - if you distribute this file as part of a program or library that - is built using GNU Libtool, you may include this file under the - same distribution terms that you use for the rest of that program. - . - GNU Libtool is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - . - On Debian systems, the complete text of the GNU General Public License - Version 2 can be found in `/usr/share/common-licenses/GPL-2'. - -Files: json-c/depcomp -Copyright: 1999-2017 Free Software Foundation, Inc. -License: GPL-2.0+ with autoconf exception - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - . - As a special exception to the GNU General Public License, if you - distribute this file as part of a program that contains a - configuration script generated by Autoconf, you may include it under - the same distribution terms that you use for the rest of that program. - . - Originally written by Alexandre Oliva . - . - On Debian systems, the complete text of the GNU General Public License - Version 2 can be found in `/usr/share/common-licenses/GPL-2'. - -Files: json-c/config.guess -Copyright: 1992-2016 Free Software Foundation, Inc. -License: GPL-3.0+ with autoconf exception - This file is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program; if not, see . - . - As a special exception to the GNU General Public License, if you - distribute this file as part of a program that contains a - configuration script generated by Autoconf, you may include it under - the same distribution terms that you use for the rest of that - program. This Exception is an additional permission under section 7 - of the GNU General Public License, version 3 ("GPLv3"). - . - Originally written by Per Bothner; maintained since 2000 by Ben Elliston. - . - On Debian systems, the complete text of the GNU General Public License - Version 3 can be found in `/usr/share/common-licenses/GPL-3'. - -Files: json-c/config.sub -Copyright: 1992-2016 Free Software Foundation, Inc. -License: GPL-3.0+ with autoconf exception - This file is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program; if not, see . - . - As a special exception to the GNU General Public License, if you - distribute this file as part of a program that contains a - configuration script generated by Autoconf, you may include it under - the same distribution terms that you use for the rest of that - program. This Exception is an additional permission under section 7 - of the GNU General Public License, version 3 ("GPLv3"). - . - On Debian systems, the complete text of the GNU General Public License - Version 3 can be found in `/usr/share/common-licenses/GPL-3'. - -#---------------------------------------------------------------------------- -# xml and html files (skipped): -# json-c/README.html -# libwebsockets/minimal-examples/client-server/minimal-ws-proxy/mount-origin/index.html -# libwebsockets/minimal-examples/http-server/minimal-http-server/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-origin/index.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-basicauth/mount-secret-origin/index.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/index.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-dynamic/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost2/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost1/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-multivhost/mount-origin-localhost3/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/after-form1.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post-file/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-sse/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/after-form1.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-form-get/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/after-form1.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-tls/mount-origin/404.html -# libwebsockets/minimal-examples/http-server/minimal-http-server-sse-ring/mount-origin/404.html -# libwebsockets/minimal-examples/ws-server/minimal-ws-server-threads/mount-origin/index.html -# libwebsockets/plugins/server-status.html -# libwebsockets/plugins/generic-sessions/assets/post-register-ok.html -# libwebsockets/plugins/generic-sessions/assets/post-verify-ok.html -# libwebsockets/plugins/generic-sessions/assets/admin-login.html -# libwebsockets/plugins/generic-sessions/assets/failed-login.html -# libwebsockets/plugins/generic-sessions/assets/post-forgot-ok.html -# libwebsockets/plugins/generic-sessions/assets/post-forgot-fail.html -# libwebsockets/plugins/generic-sessions/assets/lwsgs.js -# libwebsockets/plugins/generic-sessions/assets/post-verify-fail.html -# libwebsockets/plugins/generic-sessions/assets/successful-login.html -# libwebsockets/plugins/generic-sessions/assets/sent-forgot-fail.html -# libwebsockets/plugins/generic-sessions/assets/index.html -# libwebsockets/plugins/generic-table/assets/index.html -# libwebsockets/test-apps/test.html -# libwebsockets/test-apps/android/app/app.iml -# libwebsockets/test-apps/android/app/src/main/AndroidManifest.xml -# libwebsockets/test-apps/android/app/src/main/res/layout/activity_main.xml -# libwebsockets/test-apps/android/app/src/main/res/values/colors.xml -# libwebsockets/test-apps/android/app/src/main/res/values/dimens.xml -# libwebsockets/test-apps/android/app/src/main/res/values/strings.xml -# libwebsockets/test-apps/android/app/src/main/res/values/styles.xml - -#---------------------------------------------------------------------------- -# huge files (skipped): -# cscope.out -# cscope.in.out -# cscope.po.out -# slack.so -# libwebsockets/lib/libwebsockets.a -# libwebsockets/test-apps/leaf.jpg - -#---------------------------------------------------------------------------- -# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following -# license/copyright files. - -#---------------------------------------------------------------------------- -# License file: LICENSE - Mozilla Public License Version 2.0 - ================================== - . - 1. Definitions - -------------- - . - 1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - . - 1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - . - 1.3. "Contribution" - means Covered Software of a particular Contributor. - . - 1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - . - 1.5. "Incompatible With Secondary Licenses" - means - . - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - . - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - . - 1.6. "Executable Form" - means any form of the work other than Source Code Form. - . - 1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - . - 1.8. "License" - means this document. - . - 1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - . - 1.10. "Modifications" - means any of the following: - . - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - . - (b) any new file in Source Code Form that contains any Covered - Software. - . - 1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - . - 1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - . - 1.13. "Source Code Form" - means the form of the work preferred for making modifications. - . - 1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - . - 2. License Grants and Conditions - -------------------------------- - . - 2.1. Grants - . - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - . - (a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - . - (b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - . - 2.2. Effective Date - . - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - . - 2.3. Limitations on Grant Scope - . - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - . - (a) for any code that a Contributor has removed from Covered Software; - or - . - (b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - . - (c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - . - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - . - 2.4. Subsequent Licenses - . - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - . - 2.5. Representation - . - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights - to grant the rights to its Contributions conveyed by this License. - . - 2.6. Fair Use - . - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - . - 2.7. Conditions - . - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted - in Section 2.1. - . - 3. Responsibilities - ------------------- - . - 3.1. Distribution of Source Form - . - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - . - 3.2. Distribution of Executable Form - . - If You distribute Covered Software in Executable Form then: - . - (a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - . - (b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - . - 3.3. Distribution of a Larger Work - . - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - . - 3.4. Notices - . - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, - or limitations of liability) contained within the Source Code Form of - the Covered Software, except that You may alter any license notices to - the extent required to remedy known factual inaccuracies. - . - 3.5. Application of Additional Terms - . - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - . - 4. Inability to Comply Due to Statute or Regulation - --------------------------------------------------- - . - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Software due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description must - be placed in a text file included with all distributions of the Covered - Software under this License. Except to the extent prohibited by statute - or regulation, such description must be sufficiently detailed for a - recipient of ordinary skill to be able to understand it. - . - 5. Termination - -------------- - . - 5.1. The rights granted under this License will terminate automatically - if You fail to comply with any of its terms. However, if You become - compliant, then the rights granted under this License from a particular - Contributor are reinstated (a) provisionally, unless and until such - Contributor explicitly and finally terminates Your grants, and (b) on an - ongoing basis, if such Contributor fails to notify You of the - non-compliance by some reasonable means prior to 60 days after You have - come back into compliance. Moreover, Your grants from a particular - Contributor are reinstated on an ongoing basis if such Contributor - notifies You of the non-compliance by some reasonable means, this is the - first time You have received notice of non-compliance with this License - from such Contributor, and You become compliant prior to 30 days after - Your receipt of the notice. - . - 5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - . - 5.3. In the event of termination under Sections 5.1 or 5.2 above, all - end user license agreements (excluding distributors and resellers) which - have been validly granted by You or Your distributors under this License - prior to termination shall survive termination. - . - ************************************************************************ - * * - * 6. Disclaimer of Warranty * - * ------------------------- * - * * - * Covered Software is provided under this License on an "as is" * - * basis, without warranty of any kind, either expressed, implied, or * - * statutory, including, without limitation, warranties that the * - * Covered Software is free of defects, merchantable, fit for a * - * particular purpose or non-infringing. The entire risk as to the * - * quality and performance of the Covered Software is with You. * - * Should any Covered Software prove defective in any respect, You * - * (not any Contributor) assume the cost of any necessary servicing, * - * repair, or correction. This disclaimer of warranty constitutes an * - * essential part of this License. No use of any Covered Software is * - * authorized under this License except under this disclaimer. * - * * - ************************************************************************ - . - ************************************************************************ - * * - * 7. Limitation of Liability * - * -------------------------- * - * * - * Under no circumstances and under no legal theory, whether tort * - * (including negligence), contract, or otherwise, shall any * - * Contributor, or anyone who distributes Covered Software as * - * permitted above, be liable to You for any direct, indirect, * - * special, incidental, or consequential damages of any character * - * including, without limitation, damages for lost profits, loss of * - * goodwill, work stoppage, computer failure or malfunction, or any * - * and all other commercial damages or losses, even if such party * - * shall have been informed of the possibility of such damages. This * - * limitation of liability shall not apply to liability for death or * - * personal injury resulting from such party's negligence to the * - * extent applicable law prohibits such limitation. Some * - * jurisdictions do not allow the exclusion or limitation of * - * incidental or consequential damages, so this exclusion and * - * limitation may not apply to You. * - * * - ************************************************************************ - . - 8. Litigation - ------------- - . - Any litigation relating to this License may be brought only in the - courts of a jurisdiction where the defendant maintains its principal - place of business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. - Nothing in this Section shall prevent a party's ability to bring - cross-claims or counter-claims. - . - 9. Miscellaneous - ---------------- - . - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides - that the language of a contract shall be construed against the drafter - shall not be used to construe this License against a Contributor. - . - 10. Versions of the License - --------------------------- - . - 10.1. New Versions - . - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - . - 10.2. Effect of New Versions - . - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - . - 10.3. Modified Versions - . - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - . - 10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses - . - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - . - Exhibit A - Source Code Form License Notice - ------------------------------------------- - . - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 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/. - . - If it is not possible or desirable to put the notice in a particular - file, then You may include the notice in a location (such as a LICENSE - file in a relevant directory) where a recipient would be likely to look - for such a notice. - . - You may add additional accurate notices of copyright ownership. - . - Exhibit B - "Incompatible With Secondary Licenses" Notice - --------------------------------------------------------- - . - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 3cf9a4e..0000000 --- a/debian/rules +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/make -f - -DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) - -#export DH_VERBOSE = 1 -#export DEB_BUILD_MAINT_OPTIONS = hardening=+all -#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic -export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed - -%: - dh $@ --without autoreconf - -override_dh_auto_install: - dh_auto_install -- LIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH) - -override_dh_install: - dh_install diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides deleted file mode 100644 index 75668d3..0000000 --- a/debian/source/lintian-overrides +++ /dev/null @@ -1,6 +0,0 @@ -# This is an override for the following lintian errors: -# E: weechat-slack source: source-is-missing libwebsockets/plugins/generic-sessions/assets/lwsgs.js -# E: weechat-slack source: source-is-missing libwebsockets/plugins/generic-sessions/assets/md5.min.js -# The source is not missing, all sources are included. -# This is a lintian false-positive. -weechat-slack source: source-is-missing \ No newline at end of file diff --git a/libwebsockets b/libwebsockets deleted file mode 160000 index f1c56bc..0000000 --- a/libwebsockets +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f1c56bc233a5f05c01c93a5c250a31b4d309ecac diff --git a/slack-emoji.pl b/slack-emoji.pl deleted file mode 100644 index 5803327..0000000 --- a/slack-emoji.pl +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/perl -l - -# 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/. - -use strict; -use warnings; - -use LWP::Simple; -use Data::Dumper; -use JSON qw (decode_json); -use List::Util qw (max); - -our ($json, @array); - -$json = get('https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json'); -@array = @{ decode_json($json) }; - -my $maxtexts = max (map { 1 + @{$_} } (grep defined, map { $_->{'texts'} } @array)); -my $maxnames = max (map { 1 + @{$_} } (grep defined, map { $_->{'short_names'} } @array)); - -print " -// 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 - -#define MAX_TEXTS $maxtexts -#define MAX_NAMES $maxnames - -struct t_slack_emoji_by_name { - const char *name; - const char *unicode; - const char *text_to; - const char *text_from[MAX_TEXTS]; -}; - -struct t_slack_emoji_by_text { - const char *text; - const char *unicode; - const char *name_to; - const char *name_from[MAX_NAMES]; -}; -"; - -print "static struct t_slack_emoji_by_name slack_emoji_by_name[] ="; -my $c = '{'; -my %byname = map { my $o = $_; map {($_, $o)} @{$o->{'short_names'}} } @array; -my @sortedbyname = sort { $a cmp $b } keys %byname; -foreach my $name (@sortedbyname) -{ - my $_0 = "\":$name:\""; - my @_1 = split /-/, $byname{$name}->{'unified'}; - my $_1 = "\""; - foreach my $codepoint (@_1) { - if (hex $codepoint < 0xA0) { $_1 .= chr hex $codepoint } else { $_1 .= "\\u$codepoint" } - }; - $_1 .= "\""; - $_1 =~ tr/A-Za-z/a-za-z/; - my $_2 = $byname{$name}->{'text'}; - if (defined $_2) { $_2 = "\"$_2\"" } else { $_2 = "NULL" }; - $_2 =~ s/\\/\\\\/g; - my $_3 = "{"; - foreach my $text (@{$byname{$name}->{'texts'}}) { if (defined $text) { $_3 .= "\"$text\", " } }; - $_3 .= "NULL}"; - $_3 =~ s/\\/\\\\/g; - print "$c { $_0, $_1, $_2, $_3 }"; - $c = ','; -} -print "};"; -print ""; -print "static struct t_slack_emoji_by_text slack_emoji_by_text[] ="; -$c = '{'; -my %bytext = map { my $o = $_; map {($_, $o)} @{$o->{'texts'}} } @array; -my @sortedbytext = sort { $a cmp $b } keys %bytext; -foreach my $text (@sortedbytext) -{ - my $_0 = "\"$text\""; - $_0 =~ s/\\/\\\\/g; - my @_1 = split /-/, $bytext{$text}->{'unified'}; - my $_1 = "\""; - foreach my $codepoint (@_1) { - if (hex $codepoint < 0xA0) { $_1 .= chr hex $codepoint } else { $_1 .= "\\u$codepoint" } - }; - $_1 .= "\""; - $_1 =~ tr/A-Za-z/a-za-z/; - my $_2 = $bytext{$text}->{'short_name'}; - if (defined $_2) { $_2 = "\":$_2:\"" } else { $_2 = "NULL" }; - my $_3 = "{"; - foreach my $name (@{$bytext{$text}->{'short_names'}}) { if (defined $name) { $_3 .= "\":$name:\", " } }; - $_3 .= "NULL}"; - print "$c { $_0, $_1, $_2, $_3 }"; - $c = ','; -} -print "};"; diff --git a/slack-emoji.py b/slack-emoji.py deleted file mode 100755 index 9b5e90e..0000000 --- a/slack-emoji.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python3 - -# 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/. - -import requests -import json -import ast - -emoji = requests.get("https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json").json() - -print(""" -// 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 - -#define MAX_TEXTS %d -#define MAX_NAMES %d - -struct t_slack_emoji_by_name { - const char *name; - const char *unicode; - const char *text_to; - const char *text_from[MAX_TEXTS]; -}; - -struct t_slack_emoji_by_text { - const char *text; - const char *unicode; - const char *name_to; - const char *name_from[MAX_NAMES]; -}; -"""%(max(len(o['texts'] if o['texts'] else []) for o in emoji) + 1, - max(len(o['short_names'] if o['short_names'] else []) for o in emoji) + 1)) -print("static struct t_slack_emoji_by_name slack_emoji_by_name[] =") -print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format( - json.dumps(":"+name+":"), - json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s), - json.dumps(o['text']), - "{"+json.dumps(o['texts']+[None] if o['texts'] else [None])[1:-1]+"}") - for o,name in sorted(((o,name) for o in emoji for name in o['short_names']), - key=lambda x: x[1]) -).replace("null", "NULL")[1:]) -print("};") -print("") -print("static struct t_slack_emoji_by_text slack_emoji_by_text[] =") -print("{"+"\n".join(", {{ {0}, {1}, {2}, {3} }}".format( - json.dumps(text), - json.dumps(ast.parse("\"\\u"+"\\u".join(o['unified'].split('-'))+"\"", mode='eval').body.s), - json.dumps(":"+o['short_name']+":"), - "{"+json.dumps(list(map(lambda name: ":"+name+":", o['short_names']))+[None] - if o['short_names'] else [None])[1:-1]+"}") - for o,text in sorted(((o,text) for o in emoji if o['texts'] for text in o['texts']), - key=lambda x:x[1]) -).replace("null", "NULL")[1:]) -print("};") diff --git a/xmpp.c b/xmpp.c new file mode 100644 index 0000000..fcf24e2 --- /dev/null +++ b/xmpp.c @@ -0,0 +1,106 @@ +// 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 + +#include "weechat-plugin.h" +#include "xmpp.h" +//#include "slack-config.h" +//#include "slack-command.h" +//#include "slack-workspace.h" +//#include "slack-api.h" +//#include "slack-buffer.h" +//#include "slack-completion.h" + + +WEECHAT_PLUGIN_NAME(XMPP_PLUGIN_NAME); +WEECHAT_PLUGIN_DESCRIPTION(N_("XMPP protocol")); +WEECHAT_PLUGIN_AUTHOR("bqv "); +WEECHAT_PLUGIN_VERSION(XMPP_PLUGIN_VERSION); +WEECHAT_PLUGIN_LICENSE("MPL2"); +WEECHAT_PLUGIN_PRIORITY(5500); + +struct t_weechat_plugin *weechat_xmpp_plugin = NULL; + +struct t_hook *xmpp_hook_timer = NULL; + +struct t_gui_bar_item *xmpp_typing_bar_item = NULL; + +void xmpp_lwsl_emit_weechat(int level, const char *line) +{ + char buf[50]; + //lwsl_timestamp(level, buf, sizeof(buf)); + + weechat_printf( + NULL, + _("%s%s: %s%s"), + weechat_prefix("error"), XMPP_PLUGIN_NAME, + buf, line); +} + +int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) +{ + (void) argc; + (void) argv; + + weechat_plugin = plugin; + + //lws_set_log_level(LLL_ERR | LLL_WARN /*| LLL_NOTICE | LLL_INFO | LLL_DEBUG + // | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT + // | LLL_LATENCY | LLL_USER | LLL_COUNT*/, + // xmpp_lwsl_emit_weechat); + + //if (!xmpp_config_init()) + // return WEECHAT_RC_ERROR; + + //xmpp_config_read(); + + //xmpp_command_init(); + + //xmpp_api_init(); + + //xmpp_completion_init(); + + //xmpp_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, + // &xmpp_workspace_timer_cb, + // NULL, NULL); + + if (!weechat_bar_search("typing")) + { + weechat_bar_new("typing", "off", "400", "window", "${typing}", + "bottom", "horizontal", "vertical", + "1", "1", "default", "default", "default", + "off", "xmpp_typing"); + } + + //xmpp_typing_bar_item = weechat_bar_item_new("xmpp_typing", + // &xmpp_buffer_typing_bar_cb, + // NULL, NULL); + + return WEECHAT_RC_OK; +} + +int weechat_plugin_end(struct t_weechat_plugin *plugin) +{ + /* make C compiler happy */ + (void) plugin; + + if (xmpp_typing_bar_item) + weechat_bar_item_remove(xmpp_typing_bar_item); + + if (xmpp_hook_timer) + weechat_unhook(xmpp_hook_timer); + + //xmpp_config_write(); + + //xmpp_workspace_disconnect_all(); + + //xmpp_workspace_free_all(); + + return WEECHAT_RC_OK; +} diff --git a/xmpp.h b/xmpp.h new file mode 100644 index 0000000..a70ebae --- /dev/null +++ b/xmpp.h @@ -0,0 +1,14 @@ +// 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/. + +#ifndef _XMPP_H_ +#define _XMPP_H_ + +#define weechat_plugin weechat_xmpp_plugin +#define XMPP_PLUGIN_NAME "xmpp" +#define XMPP_PLUGIN_VERSION "0.1" + +extern struct t_weechat_plugin *weechat_xmpp_plugin; + +#endif /*XMPP_H*/ From 9c5c7407b4d5f3e3d030a906e6d6f067330af94b Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 25 Jun 2021 23:39:20 +0100 Subject: [PATCH 065/118] add envrc --- .envrc | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 1 + 2 files changed, 98 insertions(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..31e7ecc --- /dev/null +++ b/.envrc @@ -0,0 +1,97 @@ +# -*- mode: sh; -*- +# Thanks +export_function() +{ + local name=$1 + local alias_dir=$PWD/.direnv/aliases + mkdir -p "$alias_dir" + PATH_add "$alias_dir" + local target="$alias_dir/$name" + if declare -f "$name" >/dev/null; then + echo "#!$SHELL" > "$target" + declare -f "$name" >> "$target" 2>/dev/null + # Notice that we add shell variables to the function trigger. + echo "$name \$*" >> "$target" + chmod +x "$target" + fi +} + +use_guix() +{ + # Set GitHub token. + export GUIX_GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + # Unset 'GUIX_PACKAGE_PATH'. + export GUIX_PACKAGE_PATH="" + + # Recreate a garbage collector root. + gcroots="$HOME/.config/guix/gcroots" + mkdir -p "$gcroots" + gcroot="$gcroots/guix" + if [ -L "$gcroot" ] + then + rm -v "$gcroot" + fi + + # Miscellaneous packages. + PACKAGES_MAINTENANCE=( + direnv + git + git:send-email + git-cal + gnupg + guile-colorized + guile-readline + less + ncurses + openssh + xdot + ) + + # Environment packages. + PACKAGES=(help2man guile-sqlite3 guile-gcrypt + autoconf autoconf-archive automake libtool + pkg-config openssl libxml2) + + # Thanks + eval "$(guix environment --search-paths --root="$gcroot" --pure guix json-c --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" + + export CC=gcc + + # Predefine configure flags. + configure() + { + ./configure --localstatedir=/var --prefix= + } + export_function configure + + # Run make and optionally build something. + build() + { + make -j 2 + if [ $# -gt 0 ] + then + ./pre-inst-env guix build "$@" + fi + } + export_function build + + # Predefine push Git command. + push() + { + git push --set-upstream origin + } + export_function push + + clear # Clean up the screen. + git-cal --author='Your Name' # Show contributions calendar. + + # Show commands help. + echo " +build build a package or just a project if no argument provided +configure run ./configure with predefined parameters +push push to upstream Git repository +" +} + +use guix diff --git a/.gitignore b/.gitignore index 28a8c3c..93fe681 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.direnv *~ compile_commands.json cscope* From 0c8a278fc5ff2af5046ac690e5e8bfc7807948c8 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 25 Jun 2021 23:44:03 +0100 Subject: [PATCH 066/118] impure envrc --- .envrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.envrc b/.envrc index 31e7ecc..4945571 100644 --- a/.envrc +++ b/.envrc @@ -54,7 +54,7 @@ use_guix() pkg-config openssl libxml2) # Thanks - eval "$(guix environment --search-paths --root="$gcroot" --pure guix json-c --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" + eval "$(guix environment --search-paths --root="$gcroot" json-c --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" export CC=gcc From ac949c6b7b02bd2385aecb193c84e545f8e34522 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 Jun 2021 00:17:15 +0100 Subject: [PATCH 067/118] fix readme --- README.org | 86 +++++++++++++++--------------------------------------- 1 file changed, 24 insertions(+), 62 deletions(-) diff --git a/README.org b/README.org index ecf69db..01cce45 100644 --- a/README.org +++ b/README.org @@ -1,57 +1,56 @@ -#+TITLE: weechat-slack +#+TITLE: weechat-xmpp #+AUTHOR: Tony Olagbaiye #+EMAIL: frony0@gmail.com #+DATE: 2018-05-09 -#+DESCRIPTION: Weechat plugin for Slack -#+KEYWORDS: weechat slack c api +#+DESCRIPTION: Weechat plugin for XMPP +#+KEYWORDS: weechat xmpp c api #+LANGUAGE: en #+OPTIONS: H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t #+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:t tags:not-in-toc #+EXPORT_EXCLUDE_TAGS: exclude #+STARTUP: showall -[[https://travis-ci.org/bqv/weechat-slack][file:https://api.travis-ci.org/bqv/weechat-slack.svg?branch=master]] -[[https://coveralls.io/github/bqv/weechat-slack?branch=master][file:https://coveralls.io/repos/github/bqv/weechat-slack/badge.svg?branch=master]] -[[https://github.com/bqv/weechat-slack/issues][file:https://img.shields.io/github/issues/bqv/weechat-slack.svg]] -[[https://github.com/bqv/weechat-slack/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-slack.svg]] -[[https://github.com/bqv/weechat-slack/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-slack.svg]] -[[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-slack-blue.svg]] +[[https://travis-ci.org/bqv/weechat-xmpp][file:https://api.travis-ci.org/bqv/weechat-xmpp.svg?branch=master]] +[[https://coveralls.io/github/bqv/weechat-xmpp?branch=master][file:https://coveralls.io/repos/github/bqv/weechat-xmpp/badge.svg?branch=master]] +[[https://github.com/bqv/weechat-xmpp/issues][file:https://img.shields.io/github/issues/bqv/weechat-xmpp.svg]] +[[https://github.com/bqv/weechat-xmpp/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-xmpp.svg]] +[[https://github.com/bqv/weechat-xmpp/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-xmpp.svg]] +[[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-xmpp-blue.svg]] - | Status: | Aaaaaaaaaaaaaaaaa | - | Location: | [[http://github.com/bqv/weechat-slack]] | - | Version: | 0.1.5 | - | Disclaimer: | Slack's API is a thing of horror | + | Status: | Aaaaaaaaaaaaaaaaa | + | Location: | [[http://github.com/bqv/weechat-xmpp]] | + | Version: | 0.1.0 | + | Disclaimer: | I'm lazy | * Description A weechat plugin in C to extend the chat client to - support Slack workspaces via the RTM and Web APIs. + support XMPP and ideally a maximal set of XEPs. * Usage - 1. Start with =/slack register= for instructions on how + 1. Start with =/xmpp register= for instructions on how to obtain a token, or if you already have a token, use - =/slack register =. + =/xmpp register =. - 2. Use =/slack connect = with the name + 2. Use =/xmpp connect = with the name returned by register * Installing - See http://github.com/bqv/weechat-extras for the suite this is part of - and a repository/package for your distribution. + Place xmpp.so in the appropriate place for weechat plugins. * Dependencies - - libwebsockets (static, submodule) + - libstrophe (static, submodule) - json-c (static, submodule) - weechat (>= v1.7) * Building #+begin_src sh - git clone git://github.com/bqv/weechat-slack.git - cd weechat-slack + git clone git://github.com/bqv/weechat-xmpp.git + cd weechat-xmpp make make install #+end_src @@ -75,39 +74,9 @@ * Tasks -** DONE [#A] Implement basic functionality (milestone v0.1) -** TODO [#A] Implement essential api endpoints and events (milestone v0.2) - - [X] +Implement handling api message =message.me_message= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - - [X] +Implement sending request =chat.meMessage= (see [[http://github.com/bqv/weechat-slack/issues/5][#5]])+ - - [X] +Implement handling api message =message.bot_message= (see [[http://github.com/bqv/weechat-slack/issues/2][#2]])+ - - [ ] Implement handling api message =message.message_changed= - - [ ] Implement handling api message =message.message_deleted= - - [ ] Implement handling api message =message.message_replied= - - [ ] Implement handling api message =message.file_share= - - [ ] Implement sending websocket =typing= message +** TODO [#A] Implement basic functionality (milestone v0.1) +** TODO [#A] Implement essential events (milestone v0.2) ** TODO [#B] Implement completion engine (milestone v0.3) - - [X] +Tab completion for slack emoji (see [[http://github.com/bqv/weechat-slack/issues/3][#3]])+ - - [X] +Support Slack Emoji+ - - [X] +Support Custom Emoji+ - - [ ] Tab completion for display/user names (see [[http://github.com/bqv/weechat-slack/issues/1][#1]]) - - [ ] Sort nick-completion by recent speakers (see [[http://github.com/bqv/weechat-slack/issues/4][#4]]) -** TODO [#B] Implement websocket ping and pong (milestone v0.4) - - [ ] Add ping timer and pong handler (see [[http://github.com/bqv/weechat-slack/issues/9][#9]]) -** TODO [#B] Implement thread handling (milestone v0.5) - - [ ] Implement handling api message =message.thread_broadcast= -** TODO [#C] Implement remaining api endpoints and events (milestone v0.6) - - [ ] Support all channel types - - [X] +Channels+ - - [ ] Groups - - [ ] MPIMs - - [ ] IMs - - [ ] Complete api endpoint set - - [ ] Complete api event set -** TODO [#C] Implement full weechat functionality (milestone v0.7) - - [ ] Hook buffer closes - - [ ] Relay compatibility - - [ ] Config Options - - [ ] Emoji translation options (see [[http://github.com/bqv/weechat-slack/issues/11][#11]]) ** TODO [#D] Close all issues (milestone v1.0) * Contributing @@ -115,15 +84,8 @@ *Your contributions are always welcome!* Please submit a pull request or create an issue to add a new or missing feature. - -* Appropriating - - As there is no C library for Slack at the time of - writing, this project implements the APIs from - scratch, and as such one could butcher this repository - to create a minimal Slack C library. Up to you. * License - weechat-slack is licensed under the Mozilla Public + weechat-xmpp is licensed under the Mozilla Public License Version 2.0 available [[https://www.mozilla.org/en-US/MPL/2.0/][here]] and in LICENSE. From 021fa87fea10a0cecea6441e11c80f275a639c26 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 Jun 2021 01:08:12 +0100 Subject: [PATCH 068/118] simpler envrc --- .envrc | 41 +++-------------------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/.envrc b/.envrc index 4945571..7889373 100644 --- a/.envrc +++ b/.envrc @@ -38,7 +38,6 @@ use_guix() direnv git git:send-email - git-cal gnupg guile-colorized guile-readline @@ -51,47 +50,13 @@ use_guix() # Environment packages. PACKAGES=(help2man guile-sqlite3 guile-gcrypt autoconf autoconf-archive automake libtool - pkg-config openssl libxml2) + make cmake gcc-toolchain pkg-config + openssl libxml2 libstrophe json-c) # Thanks - eval "$(guix environment --search-paths --root="$gcroot" json-c --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" + eval "$(guix environment --search-paths --root="$gcroot" --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" export CC=gcc - - # Predefine configure flags. - configure() - { - ./configure --localstatedir=/var --prefix= - } - export_function configure - - # Run make and optionally build something. - build() - { - make -j 2 - if [ $# -gt 0 ] - then - ./pre-inst-env guix build "$@" - fi - } - export_function build - - # Predefine push Git command. - push() - { - git push --set-upstream origin - } - export_function push - - clear # Clean up the screen. - git-cal --author='Your Name' # Show contributions calendar. - - # Show commands help. - echo " -build build a package or just a project if no argument provided -configure run ./configure with predefined parameters -push push to upstream Git repository -" } use guix From f75d1dbea3fdd29846fc1d50eb4fcb0d5545a64a Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 Jun 2021 01:30:39 +0100 Subject: [PATCH 069/118] update weechat header --- .envrc | 2 +- slack.c | 106 --- slack.h | 17 - weechat-plugin.h | 2037 ---------------------------------------------- xmpp.c | 4 +- 5 files changed, 3 insertions(+), 2163 deletions(-) delete mode 100644 slack.c delete mode 100644 slack.h delete mode 100644 weechat-plugin.h diff --git a/.envrc b/.envrc index 7889373..3381671 100644 --- a/.envrc +++ b/.envrc @@ -51,7 +51,7 @@ use_guix() PACKAGES=(help2man guile-sqlite3 guile-gcrypt autoconf autoconf-archive automake libtool make cmake gcc-toolchain pkg-config - openssl libxml2 libstrophe json-c) + libressl libxml2 libstrophe json-c weechat) # Thanks eval "$(guix environment --search-paths --root="$gcroot" --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" diff --git a/slack.c b/slack.c deleted file mode 100644 index 29cc0cf..0000000 --- a/slack.c +++ /dev/null @@ -1,106 +0,0 @@ -// 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 - -#include "weechat-plugin.h" -#include "slack.h" -#include "slack-config.h" -#include "slack-command.h" -#include "slack-workspace.h" -#include "slack-api.h" -#include "slack-buffer.h" -#include "slack-completion.h" - - -WEECHAT_PLUGIN_NAME(SLACK_PLUGIN_NAME); -WEECHAT_PLUGIN_DESCRIPTION(N_("Slack (slack.com) protocol")); -WEECHAT_PLUGIN_AUTHOR("Tony Olagbaiye "); -WEECHAT_PLUGIN_VERSION(SLACK_PLUGIN_VERSION); -WEECHAT_PLUGIN_LICENSE("MPL2"); -WEECHAT_PLUGIN_PRIORITY(5500); - -struct t_weechat_plugin *weechat_slack_plugin = NULL; - -struct t_hook *slack_hook_timer = NULL; - -struct t_gui_bar_item *slack_typing_bar_item = NULL; - -void slack_lwsl_emit_weechat(int level, const char *line) -{ - char buf[50]; - lwsl_timestamp(level, buf, sizeof(buf)); - - weechat_printf( - NULL, - _("%s%s: %s%s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - buf, line); -} - -int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) -{ - (void) argc; - (void) argv; - - weechat_plugin = plugin; - - lws_set_log_level(LLL_ERR | LLL_WARN /*| LLL_NOTICE | LLL_INFO | LLL_DEBUG - | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT - | LLL_LATENCY | LLL_USER | LLL_COUNT*/, - slack_lwsl_emit_weechat); - - if (!slack_config_init()) - return WEECHAT_RC_ERROR; - - slack_config_read(); - - slack_command_init(); - - slack_api_init(); - - slack_completion_init(); - - slack_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, - &slack_workspace_timer_cb, - NULL, NULL); - - if (!weechat_bar_search("typing")) - { - weechat_bar_new("typing", "off", "400", "window", "${typing}", - "bottom", "horizontal", "vertical", - "1", "1", "default", "default", "default", - "off", "slack_typing"); - } - - slack_typing_bar_item = weechat_bar_item_new("slack_typing", - &slack_buffer_typing_bar_cb, - NULL, NULL); - - return WEECHAT_RC_OK; -} - -int weechat_plugin_end(struct t_weechat_plugin *plugin) -{ - /* make C compiler happy */ - (void) plugin; - - if (slack_typing_bar_item) - weechat_bar_item_remove(slack_typing_bar_item); - - if (slack_hook_timer) - weechat_unhook(slack_hook_timer); - - slack_config_write(); - - slack_workspace_disconnect_all(); - - slack_workspace_free_all(); - - return WEECHAT_RC_OK; -} diff --git a/slack.h b/slack.h deleted file mode 100644 index 23f98ec..0000000 --- a/slack.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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/. - -#ifndef _SLACK_H_ -#define _SLACK_H_ - -#define weechat_plugin weechat_slack_plugin -#define SLACK_PLUGIN_NAME "slack" -#define SLACK_PLUGIN_VERSION "0.1" - -#define SLACK_CLIENT_ID "2468770254.51917335286" -#define SLACK_CLIENT_SECRET "dcb7fe380a000cba0cca3169a5fe8d70" - -extern struct t_weechat_plugin *weechat_slack_plugin; - -#endif /*SLACK_H*/ diff --git a/weechat-plugin.h b/weechat-plugin.h deleted file mode 100644 index 02dc525..0000000 --- a/weechat-plugin.h +++ /dev/null @@ -1,2037 +0,0 @@ -/* - * weechat-plugin.h - header to compile WeeChat plugins - * - * Copyright (C) 2003-2018 Sébastien Helleu - * - * This file is part of WeeChat, the extensible chat client. - * - * WeeChat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * WeeChat is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with WeeChat. If not, see . - */ - -#ifndef WEECHAT_WEECHAT_PLUGIN_H -#define WEECHAT_WEECHAT_PLUGIN_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include -#include -#include - -/* some systems like GNU/Hurd do not define PATH_MAX */ -#ifndef PATH_MAX - #define PATH_MAX 4096 -#endif /* PATH_MAX */ - -struct t_config_option; -struct t_config_section; -struct t_config_file; -struct t_gui_window; -struct t_gui_buffer; -struct t_gui_bar; -struct t_gui_bar_item; -struct t_gui_bar_window; -struct t_gui_completion; -struct t_gui_nick; -struct t_gui_nick_group; -struct t_infolist; -struct t_infolist_item; -struct t_upgrade_file; -struct t_weelist; -struct t_weelist_item; -struct t_arraylist; -struct t_hashtable; -struct t_hdata; -struct timeval; - -/* - * IMPORTANT NOTE for WeeChat developers: if you update, add or remove - * some functions in this file, then please update API version below. - */ - -/* - * API version (used to check that plugin has same API and can be loaded): - * please change the date with current one; for a second change at same - * date, increment the 01, otherwise please keep 01. - */ -#define WEECHAT_PLUGIN_API_VERSION "20171223-01" - -/* macros for defining plugin infos */ -#define WEECHAT_PLUGIN_NAME(__name) \ - char weechat_plugin_name[] = __name; \ - char weechat_plugin_api_version[] = WEECHAT_PLUGIN_API_VERSION; -#define WEECHAT_PLUGIN_AUTHOR(__author) \ - char weechat_plugin_author[] = __author; -#define WEECHAT_PLUGIN_DESCRIPTION(__desc) \ - char weechat_plugin_description[] = __desc; -#define WEECHAT_PLUGIN_VERSION(__version) \ - char weechat_plugin_version[] = __version; -#define WEECHAT_PLUGIN_LICENSE(__license) \ - char weechat_plugin_license[] = __license; -#define WEECHAT_PLUGIN_PRIORITY(__priority) \ - int weechat_plugin_priority = __priority; - -/* return codes for plugin functions */ -#define WEECHAT_RC_OK 0 -#define WEECHAT_RC_OK_EAT 1 -#define WEECHAT_RC_ERROR -1 - -/* return codes for config read functions/callbacks */ -#define WEECHAT_CONFIG_READ_OK 0 -#define WEECHAT_CONFIG_READ_MEMORY_ERROR -1 -#define WEECHAT_CONFIG_READ_FILE_NOT_FOUND -2 - -/* return codes for config write functions/callbacks */ -#define WEECHAT_CONFIG_WRITE_OK 0 -#define WEECHAT_CONFIG_WRITE_ERROR -1 -#define WEECHAT_CONFIG_WRITE_MEMORY_ERROR -2 - -/* null value for option */ -#define WEECHAT_CONFIG_OPTION_NULL "null" - -/* return codes for config option set */ -#define WEECHAT_CONFIG_OPTION_SET_OK_CHANGED 2 -#define WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE 1 -#define WEECHAT_CONFIG_OPTION_SET_ERROR 0 -#define WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND -1 - -/* return codes for config option unset */ -#define WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET 0 -#define WEECHAT_CONFIG_OPTION_UNSET_OK_RESET 1 -#define WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED 2 -#define WEECHAT_CONFIG_OPTION_UNSET_ERROR -1 - -/* list management (order of elements) */ -#define WEECHAT_LIST_POS_SORT "sort" -#define WEECHAT_LIST_POS_BEGINNING "beginning" -#define WEECHAT_LIST_POS_END "end" - -/* type for keys and values in hashtable */ -#define WEECHAT_HASHTABLE_INTEGER "integer" -#define WEECHAT_HASHTABLE_STRING "string" -#define WEECHAT_HASHTABLE_POINTER "pointer" -#define WEECHAT_HASHTABLE_BUFFER "buffer" -#define WEECHAT_HASHTABLE_TIME "time" - -/* types for hdata */ -#define WEECHAT_HDATA_OTHER 0 -#define WEECHAT_HDATA_CHAR 1 -#define WEECHAT_HDATA_INTEGER 2 -#define WEECHAT_HDATA_LONG 3 -#define WEECHAT_HDATA_STRING 4 -#define WEECHAT_HDATA_POINTER 5 -#define WEECHAT_HDATA_TIME 6 -#define WEECHAT_HDATA_HASHTABLE 7 -#define WEECHAT_HDATA_SHARED_STRING 8 - -/* flags for hdata lists */ -#define WEECHAT_HDATA_LIST_CHECK_POINTERS 1 - -/* buffer hotlist */ -#define WEECHAT_HOTLIST_LOW "0" -#define WEECHAT_HOTLIST_MESSAGE "1" -#define WEECHAT_HOTLIST_PRIVATE "2" -#define WEECHAT_HOTLIST_HIGHLIGHT "3" - -/* - * process return code (for callback): - * if >= 0, the process ended and it's return code of command - * if -1, the process is still running - * if -2, the process ended with an error - * if -3, the callback is called in the child process (exec of function) - * (note: the return code -3 is NEVER sent to script plugins, - * it can be used only in C API) - */ -#define WEECHAT_HOOK_PROCESS_RUNNING -1 -#define WEECHAT_HOOK_PROCESS_ERROR -2 -#define WEECHAT_HOOK_PROCESS_CHILD -3 - -/* connect status for connection hooked */ -#define WEECHAT_HOOK_CONNECT_OK 0 -#define WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND 1 -#define WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND 2 -#define WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED 3 -#define WEECHAT_HOOK_CONNECT_PROXY_ERROR 4 -#define WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR 5 -#define WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR 6 -#define WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR 7 -#define WEECHAT_HOOK_CONNECT_MEMORY_ERROR 8 -#define WEECHAT_HOOK_CONNECT_TIMEOUT 9 -#define WEECHAT_HOOK_CONNECT_SOCKET_ERROR 10 - -/* action for gnutls callback: verify or set certificate */ -#define WEECHAT_HOOK_CONNECT_GNUTLS_CB_VERIFY_CERT 0 -#define WEECHAT_HOOK_CONNECT_GNUTLS_CB_SET_CERT 1 - -/* type of data for signal hooked */ -#define WEECHAT_HOOK_SIGNAL_STRING "string" -#define WEECHAT_HOOK_SIGNAL_INT "int" -#define WEECHAT_HOOK_SIGNAL_POINTER "pointer" - -/* macro to format string with variable args, using dynamic buffer size */ -#define weechat_va_format(__format) \ - va_list argptr; \ - int vaa_size, vaa_num; \ - char *vbuffer, *vaa_buffer2; \ - vaa_size = 1024; \ - vbuffer = malloc (vaa_size); \ - if (vbuffer) \ - { \ - while (1) \ - { \ - va_start (argptr, __format); \ - vaa_num = vsnprintf (vbuffer, vaa_size, __format, argptr); \ - va_end (argptr); \ - if ((vaa_num >= 0) && (vaa_num < vaa_size)) \ - break; \ - vaa_size = (vaa_num >= 0) ? vaa_num + 1 : vaa_size * 2; \ - vaa_buffer2 = realloc (vbuffer, vaa_size); \ - if (!vaa_buffer2) \ - { \ - free (vbuffer); \ - vbuffer = NULL; \ - break; \ - } \ - vbuffer = vaa_buffer2; \ - } \ - } - -/* - * macro to return error in case of missing arguments in callback of - * hook_command - */ -#define WEECHAT_COMMAND_MIN_ARGS(__min_args, __option) \ - if (argc < __min_args) \ - { \ - weechat_printf_date_tags ( \ - NULL, 0, "no_filter", \ - _("%sToo few arguments for command \"%s%s%s\" " \ - "(help on command: /help %s)"), \ - weechat_prefix ("error"), \ - argv[0], \ - (__option && __option[0]) ? " " : "", \ - (__option && __option[0]) ? __option : "", \ - argv[0] + 1); \ - return WEECHAT_RC_ERROR; \ - } - -/* macro to return error in callback of hook_command */ -#define WEECHAT_COMMAND_ERROR \ - { \ - weechat_printf_date_tags ( \ - NULL, 0, "no_filter", \ - _("%sError with command \"%s\" " \ - "(help on command: /help %s)"), \ - weechat_prefix ("error"), \ - argv_eol[0], \ - argv[0] + 1); \ - return WEECHAT_RC_ERROR; \ - } - -struct t_weechat_plugin -{ - /* plugin variables */ - char *filename; /* name of plugin on disk */ - void *handle; /* handle of plugin (given by dlopen)*/ - char *name; /* short name */ - char *description; /* description */ - char *author; /* author */ - char *version; /* plugin version */ - char *license; /* license */ - char *charset; /* charset used by plugin */ - int priority; /* plugin priority (default is 1000) */ - int initialized; /* plugin initialized? (init called) */ - int debug; /* debug level for plugin (0=off) */ - struct t_hashtable *variables; /* plugin custom variables */ - struct t_weechat_plugin *prev_plugin; /* link to previous plugin */ - struct t_weechat_plugin *next_plugin; /* link to next plugin */ - - /* - * plugin functions (API) - * WeeChat developers: if you add functions in API, update value of - * constant WEECHAT_PLUGIN_API_VERSION - */ - - /* plugins */ - const char *(*plugin_get_name) (struct t_weechat_plugin *plugin); - - /* strings */ - void (*charset_set) (struct t_weechat_plugin *plugin, const char *charset); - char *(*iconv_to_internal) (const char *charset, const char *string); - char *(*iconv_from_internal) (const char *charset, const char *string); - const char *(*gettext) (const char *string); - const char *(*ngettext) (const char *single, const char *plural, int count); - char *(*strndup) (const char *string, int length); - void (*string_tolower) (char *string); - void (*string_toupper) (char *string); - int (*strcasecmp) (const char *string1, const char *string2); - int (*strcasecmp_range) (const char *string1, const char *string2, - int range); - int (*strncasecmp) (const char *string1, const char *string2, int max); - int (*strncasecmp_range) (const char *string1, const char *string2, - int max, int range); - int (*strcmp_ignore_chars) (const char *string1, const char *string2, - const char *chars_ignored, int case_sensitive); - const char *(*strcasestr) (const char *string, const char *search); - int (*strlen_screen) (const char *string); - int (*string_match) (const char *string, const char *mask, - int case_sensitive); - char *(*string_replace) (const char *string, const char *search, - const char *replace); - char *(*string_expand_home) (const char *path); - char *(*string_eval_path_home) (const char *path, - struct t_hashtable *pointers, - struct t_hashtable *extra_vars, - struct t_hashtable *options); - char *(*string_remove_quotes) (const char *string, const char *quotes); - char *(*string_strip) (const char *string, int left, int right, - const char *chars); - char *(*string_convert_escaped_chars) (const char *string); - char *(*string_mask_to_regex) (const char *mask); - const char *(*string_regex_flags) (const char *regex, int default_flags, - int *flags); - int (*string_regcomp) (void *preg, const char *regex, int default_flags); - int (*string_has_highlight) (const char *string, - const char *highlight_words); - int (*string_has_highlight_regex) (const char *string, const char *regex); - char *(*string_replace_regex) (const char *string, void *regex, - const char *replace, - const char reference_char, - char *(*callback)(void *data, - const char *text), - void *callback_data); - char **(*string_split) (const char *string, const char *separators, - int keep_eol, int num_items_max, int *num_items); - char **(*string_split_shell) (const char *string, int *num_items); - void (*string_free_split) (char **split_string); - char *(*string_build_with_split_string) (const char **split_string, - const char *separator); - char **(*string_split_command) (const char *command, char separator); - void (*string_free_split_command) (char **split_command); - char *(*string_format_size) (unsigned long long size); - char *(*string_remove_color) (const char *string, const char *replacement); - void (*string_encode_base64) (const char *from, int length, char *to); - int (*string_decode_base64) (const char *from, char *to); - char *(*string_hex_dump) (const char *data, int data_size, - int bytes_per_line, const char *prefix, - const char *suffix); - int (*string_is_command_char) (const char *string); - const char *(*string_input_for_buffer) (const char *string); - char *(*string_eval_expression )(const char *expr, - struct t_hashtable *pointers, - struct t_hashtable *extra_vars, - struct t_hashtable *options); - char **(*string_dyn_alloc) (int size_alloc); - int (*string_dyn_copy) (char **string, const char *new_string); - int (*string_dyn_concat) (char **string, const char *add); - char *(*string_dyn_free) (char **string, int free_string); - - /* UTF-8 strings */ - int (*utf8_has_8bits) (const char *string); - int (*utf8_is_valid) (const char *string, int length, char **error); - void (*utf8_normalize) (char *string, char replacement); - const char *(*utf8_prev_char) (const char *string_start, - const char *string); - const char *(*utf8_next_char) (const char *string); - int (*utf8_char_int) (const char *string); - int (*utf8_char_size) (const char *string); - int (*utf8_strlen) (const char *string); - int (*utf8_strnlen) (const char *string, int bytes); - int (*utf8_strlen_screen) (const char *string); - int (*utf8_charcmp) (const char *string1, const char *string2); - int (*utf8_charcasecmp) (const char *string1, const char *string2); - int (*utf8_char_size_screen) (const char *string); - const char *(*utf8_add_offset) (const char *string, int offset); - int (*utf8_real_pos) (const char *string, int pos); - int (*utf8_pos) (const char *string, int real_pos); - char *(*utf8_strndup) (const char *string, int length); - - /* directories/files */ - int (*mkdir_home) (const char *directory, int mode); - int (*mkdir) (const char *directory, int mode); - int (*mkdir_parents) (const char *directory, int mode); - void (*exec_on_files) (const char *directory, int recurse_subdirs, - int hidden_files, - void (*callback)(void *data, const char *filename), - void *callback_data); - char *(*file_get_content) (const char *filename); - - /* util */ - int (*util_timeval_cmp) (struct timeval *tv1, struct timeval *tv2); - long long (*util_timeval_diff) (struct timeval *tv1, struct timeval *tv2); - void (*util_timeval_add) (struct timeval *tv, long long interval); - const char *(*util_get_time_string) (const time_t *date); - int (*util_version_number) (const char *version); - - /* sorted lists */ - struct t_weelist *(*list_new) (); - struct t_weelist_item *(*list_add) (struct t_weelist *weelist, - const char *data, - const char *where, - void *user_data); - struct t_weelist_item *(*list_search) (struct t_weelist *weelist, - const char *data); - int (*list_search_pos) (struct t_weelist *weelist, - const char *data); - struct t_weelist_item *(*list_casesearch) (struct t_weelist *weelist, - const char *data); - int (*list_casesearch_pos) (struct t_weelist *weelist, - const char *data); - struct t_weelist_item *(*list_get) (struct t_weelist *weelist, - int position); - void (*list_set) (struct t_weelist_item *item, const char *value); - struct t_weelist_item *(*list_next) (struct t_weelist_item *item); - struct t_weelist_item *(*list_prev) (struct t_weelist_item *item); - const char *(*list_string) (struct t_weelist_item *item); - int (*list_size) (struct t_weelist *weelist); - void (*list_remove) (struct t_weelist *weelist, - struct t_weelist_item *item); - void (*list_remove_all) (struct t_weelist *weelist); - void (*list_free) (struct t_weelist *weelist); - - /* array lists */ - struct t_arraylist *(*arraylist_new) (int initial_size, - int sorted, - int allow_duplicates, - int (*callback_cmp)(void *data, - struct t_arraylist *arraylist, - void *pointer1, - void *pointer2), - void *callback_cmp_data, - void (*callback_free)(void *data, - struct t_arraylist *arraylist, - void *pointer), - void *callback_free_data); - int (*arraylist_size) (struct t_arraylist *arraylist); - void *(*arraylist_get) (struct t_arraylist *arraylist, int index); - void *(*arraylist_search) (struct t_arraylist *arraylist, void *pointer, - int *index, int *index_insert); - int (*arraylist_insert) (struct t_arraylist *arraylist, int index, - void *pointer); - int (*arraylist_add) (struct t_arraylist *arraylist, void *pointer); - int (*arraylist_remove) (struct t_arraylist *arraylist, int index); - int (*arraylist_clear) (struct t_arraylist *arraylist); - void (*arraylist_free) (struct t_arraylist *arraylist); - - /* hash tables */ - struct t_hashtable *(*hashtable_new) (int size, - const char *type_keys, - const char *type_values, - unsigned long long (*callback_hash_key)(struct t_hashtable *hashtable, - const void *key), - int (*callback_keycmp)(struct t_hashtable *hashtable, - const void *key1, - const void *key2)); - struct t_hashtable_item *(*hashtable_set_with_size) (struct t_hashtable *hashtable, - const void *key, - int key_size, - const void *value, - int value_size); - struct t_hashtable_item *(*hashtable_set) (struct t_hashtable *hashtable, - const void *key, - const void *value); - void *(*hashtable_get) (struct t_hashtable *hashtable, const void *key); - int (*hashtable_has_key) (struct t_hashtable *hashtable, const void *key); - void (*hashtable_map) (struct t_hashtable *hashtable, - void (*callback_map) (void *data, - struct t_hashtable *hashtable, - const void *key, - const void *value), - void *callback_map_data); - void (*hashtable_map_string) (struct t_hashtable *hashtable, - void (*callback_map) (void *data, - struct t_hashtable *hashtable, - const char *key, - const char *value), - void *callback_map_data); - struct t_hashtable *(*hashtable_dup) (struct t_hashtable *hashtable); - int (*hashtable_get_integer) (struct t_hashtable *hashtable, - const char *property); - const char *(*hashtable_get_string) (struct t_hashtable *hashtable, - const char *property); - void (*hashtable_set_pointer) (struct t_hashtable *hashtable, - const char *property, - void *pointer); - int (*hashtable_add_to_infolist) (struct t_hashtable *hashtable, - struct t_infolist_item *infolist_item, - const char *prefix); - void (*hashtable_remove) (struct t_hashtable *hashtable, const void *key); - void (*hashtable_remove_all) (struct t_hashtable *hashtable); - void (*hashtable_free) (struct t_hashtable *hashtable); - - /* config files */ - struct t_config_file *(*config_new) (struct t_weechat_plugin *plugin, - const char *name, - int (*callback_reload)(const void *pointer, - void *data, - struct t_config_file *config_file), - const void *callback_reload_pointer, - void *callback_reload_data); - struct t_config_section *(*config_new_section) (struct t_config_file *config_file, - const char *name, - int user_can_add_options, - int user_can_delete_options, - int (*callback_read)(const void *pointer, - void *data, - struct t_config_file *config_file, - struct t_config_section *section, - const char *option_name, - const char *value), - const void *callback_read_pointer, - void *callback_read_data, - int (*callback_write)(const void *pointer, - void *data, - struct t_config_file *config_file, - const char *section_name), - const void *callback_write_pointer, - void *callback_write_data, - int (*callback_write_default)(const void *pointer, - void *data, - struct t_config_file *config_file, - const char *section_name), - const void *callback_write_default_pointer, - void *callback_write_default_data, - int (*callback_create_option)(const void *pointer, - void *data, - struct t_config_file *config_file, - struct t_config_section *section, - const char *option_name, - const char *value), - const void *callback_create_option_pointer, - void *callback_create_option_data, - int (*callback_delete_option)(const void *pointer, - void *data, - struct t_config_file *config_file, - struct t_config_section *section, - struct t_config_option *option), - const void *callback_delete_option_pointer, - void *callback_delete_option_data); - struct t_config_section *(*config_search_section) (struct t_config_file *config_file, - const char *section_name); - struct t_config_option *(*config_new_option) (struct t_config_file *config_file, - struct t_config_section *section, - const char *name, - const char *type, - const char *description, - const char *string_values, - int min, - int max, - 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, - void (*callback_delete)(const void *pointer, - void *data, - struct t_config_option *option), - const void *callback_delete_pointer, - void *callback_delete_data); - struct t_config_option *(*config_search_option) (struct t_config_file *config_file, - struct t_config_section *section, - const char *option_name); - void (*config_search_section_option) (struct t_config_file *config_file, - struct t_config_section *section, - const char *option_name, - struct t_config_section **section_found, - struct t_config_option **option_found); - void (*config_search_with_string) (const char *option_name, - struct t_config_file **config_file, - struct t_config_section **section, - struct t_config_option **option, - char **pos_option_name); - int (*config_string_to_boolean) (const char *text); - int (*config_option_reset) (struct t_config_option *option, - int run_callback); - int (*config_option_set) (struct t_config_option *option, - const char *value, int run_callback); - int (*config_option_set_null) (struct t_config_option *option, - int run_callback); - int (*config_option_unset) (struct t_config_option *option); - void (*config_option_rename) (struct t_config_option *option, - const char *new_name); - const char *(*config_option_get_string) (struct t_config_option *option, - const char *property); - void *(*config_option_get_pointer) (struct t_config_option *option, - const char *property); - int (*config_option_is_null) (struct t_config_option *option); - int (*config_option_default_is_null) (struct t_config_option *option); - int (*config_boolean) (struct t_config_option *option); - int (*config_boolean_default) (struct t_config_option *option); - int (*config_integer) (struct t_config_option *option); - int (*config_integer_default) (struct t_config_option *option); - const char *(*config_string) (struct t_config_option *option); - const char *(*config_string_default) (struct t_config_option *option); - const char *(*config_color) (struct t_config_option *option); - const char *(*config_color_default) (struct t_config_option *option); - int (*config_write_option) (struct t_config_file *config_file, - struct t_config_option *option); - int (*config_write_line) (struct t_config_file *config_file, - const char *option_name, - const char *value, ...); - int (*config_write) (struct t_config_file *config_file); - int (*config_read) (struct t_config_file *config_file); - int (*config_reload) (struct t_config_file *config_file); - void (*config_option_free) (struct t_config_option *option); - void (*config_section_free_options) (struct t_config_section *section); - void (*config_section_free) (struct t_config_section *section); - void (*config_free) (struct t_config_file *config_file); - struct t_config_option *(*config_get) (const char *option_name); - const char *(*config_get_plugin) (struct t_weechat_plugin *plugin, - const char *option_name); - int (*config_is_set_plugin) (struct t_weechat_plugin *plugin, - const char *option_name); - int (*config_set_plugin) (struct t_weechat_plugin *plugin, - const char *option_name, const char *value); - void (*config_set_desc_plugin) (struct t_weechat_plugin *plugin, - const char *option_name, - const char *description); - int (*config_unset_plugin) (struct t_weechat_plugin *plugin, - const char *option_name); - - /* key bindings */ - int (*key_bind) (const char *context, struct t_hashtable *keys); - int (*key_unbind) (const char *context, const char *key); - - /* display */ - const char *(*prefix) (const char *prefix); - const char *(*color) (const char *color_name); - void (*printf_date_tags) (struct t_gui_buffer *buffer, time_t date, - const char *tags, const char *message, ...); - void (*printf_y) (struct t_gui_buffer *buffer, int y, - const char *message, ...); - void (*log_printf) (const char *message, ...); - - /* hooks */ - struct t_hook *(*hook_command) (struct t_weechat_plugin *plugin, - const char *command, - const char *description, - const char *args, - const char *args_description, - const char *completion, - int (*callback)(const void *pointer, - void *data, - struct t_gui_buffer *buffer, - int argc, char **argv, - char **argv_eol), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_command_run) (struct t_weechat_plugin *plugin, - const char *command, - int (*callback)(const void *pointer, - void *data, - struct t_gui_buffer *buffer, - const char *command), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_timer) (struct t_weechat_plugin *plugin, - long interval, - int align_second, - int max_calls, - int (*callback)(const void *pointer, - void *data, - int remaining_calls), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_fd) (struct t_weechat_plugin *plugin, - int fd, - int flag_read, - int flag_write, - int flag_exception, - int (*callback)(const void *pointer, - void *data, - int fd), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_process) (struct t_weechat_plugin *plugin, - const char *command, - int timeout, - int (*callback)(const void *pointer, - void *data, - const char *command, - int return_code, - const char *out, - const char *err), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_process_hashtable) (struct t_weechat_plugin *plugin, - const char *command, - struct t_hashtable *options, - int timeout, - int (*callback)(const void *pointer, - void *data, - const char *command, - int return_code, - const char *out, - const char *err), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_connect) (struct t_weechat_plugin *plugin, - const char *proxy, - const char *address, - int port, - int ipv6, - int retry, - void *gnutls_sess, void *gnutls_cb, - int gnutls_dhkey_size, - const char *gnutls_priorities, - const char *local_hostname, - int (*callback)(const void *pointer, - void *data, - int status, - int gnutls_rc, - int sock, - const char *error, - const char *ip_address), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_print) (struct t_weechat_plugin *plugin, - struct t_gui_buffer *buffer, - const char *tags, - const char *message, - int strip_colors, - int (*callback)(const void *pointer, - void *data, - struct t_gui_buffer *buffer, - time_t date, - int tags_count, - const char **tags, - int displayed, - int highlight, - const char *prefix, - const char *message), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_signal) (struct t_weechat_plugin *plugin, - const char *signal, - int (*callback)(const void *pointer, - void *data, - const char *signal, - const char *type_data, - void *signal_data), - const void *callback_pointer, - void *callback_data); - int (*hook_signal_send) (const char *signal, const char *type_data, - void *signal_data); - struct t_hook *(*hook_hsignal) (struct t_weechat_plugin *plugin, - const char *signal, - int (*callback)(const void *pointer, - void *data, - const char *signal, - struct t_hashtable *hashtable), - const void *callback_pointer, - void *callback_data); - int (*hook_hsignal_send) (const char *signal, - struct t_hashtable *hashtable); - struct t_hook *(*hook_config) (struct t_weechat_plugin *plugin, - const char *option, - int (*callback)(const void *pointer, - void *data, - const char *option, - const char *value), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_completion) (struct t_weechat_plugin *plugin, - const char *completion_item, - const char *description, - int (*callback)(const void *pointer, - void *data, - const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion), - const void *callback_pointer, - void *callback_data); - const char *(*hook_completion_get_string) (struct t_gui_completion *completion, - const char *property); - void (*hook_completion_list_add) (struct t_gui_completion *completion, - const char *word, - int nick_completion, - const char *where); - struct t_hook *(*hook_modifier) (struct t_weechat_plugin *plugin, - const char *modifier, - char *(*callback)(const void *pointer, - void *data, - const char *modifier, - const char *modifier_data, - const char *string), - const void *callback_pointer, - void *callback_data); - char *(*hook_modifier_exec) (struct t_weechat_plugin *plugin, - const char *modifier, - const char *modifier_data, - const char *string); - struct t_hook *(*hook_info) (struct t_weechat_plugin *plugin, - const char *info_name, - const char *description, - const char *args_description, - const char *(*callback)(const void *pointer, - void *data, - const char *info_name, - const char *arguments), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_info_hashtable) (struct t_weechat_plugin *plugin, - const char *info_name, - const char *description, - const char *args_description, - const char *output_description, - struct t_hashtable *(*callback)(const void *pointer, - void *data, - const char *info_name, - struct t_hashtable *hashtable), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_infolist) (struct t_weechat_plugin *plugin, - const char *infolist_name, - const char *description, - const char *pointer_description, - const char *args_description, - struct t_infolist *(*callback)(const void *cb_pointer, - void *data, - const char *infolist_name, - void *obj_pointer, - const char *arguments), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_hdata) (struct t_weechat_plugin *plugin, - const char *hdata_name, - const char *description, - struct t_hdata *(*callback)(const void *pointer, - void *data, - const char *hdata_name), - const void *callback_pointer, - void *callback_data); - struct t_hook *(*hook_focus) (struct t_weechat_plugin *plugin, - const char *area, - struct t_hashtable *(*callback)(const void *pointer, - void *data, - struct t_hashtable *info), - const void *callback_pointer, - void *callback_data); - void (*hook_set) (struct t_hook *hook, const char *property, - const char *value); - void (*unhook) (struct t_hook *hook); - void (*unhook_all) (struct t_weechat_plugin *plugin, - const char *subplugin); - - /* buffers */ - struct t_gui_buffer *(*buffer_new) (struct t_weechat_plugin *plugin, - const char *name, - int (*input_callback)(const void *pointer, - void *data, - struct t_gui_buffer *buffer, - const char *input_data), - const void *input_callback_pointer, - void *input_callback_data, - int (*close_callback)(const void *pointer, - void *data, - struct t_gui_buffer *buffer), - const void *close_callback_pointer, - void *close_callback_data); - struct t_gui_buffer *(*buffer_search) (const char *plugin, const char *name); - struct t_gui_buffer *(*buffer_search_main) (); - void (*buffer_clear) (struct t_gui_buffer *buffer); - void (*buffer_close) (struct t_gui_buffer *buffer); - void (*buffer_merge) (struct t_gui_buffer *buffer, - struct t_gui_buffer *target_buffer); - void (*buffer_unmerge) (struct t_gui_buffer *buffer, int number); - int (*buffer_get_integer) (struct t_gui_buffer *buffer, - const char *property); - const char *(*buffer_get_string) (struct t_gui_buffer *buffer, - const char *property); - void *(*buffer_get_pointer) (struct t_gui_buffer *buffer, - const char *property); - void (*buffer_set) (struct t_gui_buffer *buffer, const char *property, - const char *value); - void (*buffer_set_pointer) (struct t_gui_buffer *buffer, - const char *property, void *pointer); - char *(*buffer_string_replace_local_var) (struct t_gui_buffer *buffer, - const char *string); - int (*buffer_match_list) (struct t_gui_buffer *buffer, const char *string); - - /* windows */ - struct t_gui_window *(*window_search_with_buffer) (struct t_gui_buffer *buffer); - int (*window_get_integer) (struct t_gui_window *window, - const char *property); - const char *(*window_get_string) (struct t_gui_window *window, - const char *property); - void *(*window_get_pointer) (struct t_gui_window *window, - const char *property); - void (*window_set_title) (const char *title); - - /* nicklist */ - struct t_gui_nick_group *(*nicklist_add_group) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *parent_group, - const char *name, - const char *color, - int visible); - struct t_gui_nick_group *(*nicklist_search_group) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *from_group, - const char *name); - struct t_gui_nick *(*nicklist_add_nick) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group, - const char *name, - const char *color, - const char *prefix, - const char *prefix_color, - int visible); - struct t_gui_nick *(*nicklist_search_nick) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *from_group, - const char *name); - void (*nicklist_remove_group) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group); - void (*nicklist_remove_nick) (struct t_gui_buffer *buffer, - struct t_gui_nick *nick); - void (*nicklist_remove_all) (struct t_gui_buffer *buffer); - void (*nicklist_get_next_item) (struct t_gui_buffer *buffer, - struct t_gui_nick_group **group, - struct t_gui_nick **nick); - int (*nicklist_group_get_integer) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group, - const char *property); - const char *(*nicklist_group_get_string) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group, - const char *property); - void *(*nicklist_group_get_pointer) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group, - const char *property); - void (*nicklist_group_set) (struct t_gui_buffer *buffer, - struct t_gui_nick_group *group, - const char *property, const char *value); - int (*nicklist_nick_get_integer) (struct t_gui_buffer *buffer, - struct t_gui_nick *nick, - const char *property); - const char *(*nicklist_nick_get_string) (struct t_gui_buffer *buffer, - struct t_gui_nick *nick, - const char *property); - void *(*nicklist_nick_get_pointer) (struct t_gui_buffer *buffer, - struct t_gui_nick *nick, - const char *property); - void (*nicklist_nick_set) (struct t_gui_buffer *buffer, - struct t_gui_nick *nick, - const char *property, const char *value); - - /* bars */ - struct t_gui_bar_item *(*bar_item_search) (const char *name); - struct t_gui_bar_item *(*bar_item_new) (struct t_weechat_plugin *plugin, - const char *name, - char *(*build_callback)(const void *pointer, - void *data, - struct t_gui_bar_item *item, - struct t_gui_window *window, - struct t_gui_buffer *buffer, - struct t_hashtable *extra_info), - const void *build_callback_pointer, - void *build_callback_data); - void (*bar_item_update) (const char *name); - void (*bar_item_remove) (struct t_gui_bar_item *item); - struct t_gui_bar *(*bar_search) (const char *name); - struct t_gui_bar *(*bar_new) (const char *name, - const char *hidden, - const char *priority, - const char *type, - const char *condition, - const char *position, - const char *filling_top_bottom, - const char *filling_left_right, - const char *size, - const char *size_max, - const char *color_fg, - const char *color_delim, - const char *color_bg, - const char *separator, - const char *items); - int (*bar_set) (struct t_gui_bar *bar, const char *property, - const char *value); - void (*bar_update) (const char *name); - void (*bar_remove) (struct t_gui_bar *bar); - - /* command */ - int (*command) (struct t_weechat_plugin *plugin, - struct t_gui_buffer *buffer, const char *command); - - /* network */ - int (*network_pass_proxy) (const char *proxy, int sock, - const char *address, int port); - int (*network_connect_to) (const char *proxy, - struct sockaddr *address, - socklen_t address_length); - - /* infos */ - const char *(*info_get) (struct t_weechat_plugin *plugin, - const char *info_name, - const char *arguments); - struct t_hashtable *(*info_get_hashtable) (struct t_weechat_plugin *plugin, - const char *info_name, - struct t_hashtable *hashtable); - - /* infolists */ - struct t_infolist *(*infolist_new) (struct t_weechat_plugin *plugin); - struct t_infolist_item *(*infolist_new_item) (struct t_infolist *infolist); - struct t_infolist_var *(*infolist_new_var_integer) (struct t_infolist_item *item, - const char *name, - int value); - struct t_infolist_var *(*infolist_new_var_string) (struct t_infolist_item *item, - const char *name, - const char *value); - struct t_infolist_var *(*infolist_new_var_pointer) (struct t_infolist_item *item, - const char *name, - void *pointer); - struct t_infolist_var *(*infolist_new_var_buffer) (struct t_infolist_item *item, - const char *name, - void *pointer, - int size); - struct t_infolist_var *(*infolist_new_var_time) (struct t_infolist_item *item, - const char *name, - time_t time); - struct t_infolist_var *(*infolist_search_var) (struct t_infolist *infolist, - const char *name); - struct t_infolist *(*infolist_get) (struct t_weechat_plugin *plugin, - const char *infolist_name, - void *pointer, - const char *arguments); - int (*infolist_next) (struct t_infolist *infolist); - int (*infolist_prev) (struct t_infolist *infolist); - void (*infolist_reset_item_cursor) (struct t_infolist *infolist); - const char *(*infolist_fields) (struct t_infolist *infolist); - int (*infolist_integer) (struct t_infolist *infolist, const char *var); - const char *(*infolist_string) (struct t_infolist *infolist, const char *var); - void *(*infolist_pointer) (struct t_infolist *infolist, const char *var); - void *(*infolist_buffer) (struct t_infolist *infolist, const char *var, - int *size); - time_t (*infolist_time) (struct t_infolist *infolist, const char *var); - void (*infolist_free) (struct t_infolist *infolist); - - /* hdata */ - struct t_hdata *(*hdata_new) (struct t_weechat_plugin *plugin, - const char *hdata_name, const char *var_prev, - const char *var_next, - int create_allowed, int delete_allowed, - int (*callback_update)(void *data, - struct t_hdata *hdata, - void *pointer, - struct t_hashtable *hashtable), - void *callback_update_data); - void (*hdata_new_var) (struct t_hdata *hdata, const char *name, int offset, - int type, int update_allowed, const char *array_size, - const char *hdata_name); - void (*hdata_new_list) (struct t_hdata *hdata, const char *name, - void *pointer, int flags); - struct t_hdata *(*hdata_get) (struct t_weechat_plugin *plugin, - const char *hdata_name); - int (*hdata_get_var_offset) (struct t_hdata *hdata, const char *name); - int (*hdata_get_var_type) (struct t_hdata *hdata, const char *name); - const char *(*hdata_get_var_type_string) (struct t_hdata *hdata, - const char *name); - int (*hdata_get_var_array_size) (struct t_hdata *hdata, void *pointer, - const char *name); - const char *(*hdata_get_var_array_size_string) (struct t_hdata *hdata, - void *pointer, - const char *name); - const char *(*hdata_get_var_hdata) (struct t_hdata *hdata, - const char *name); - void *(*hdata_get_var) (struct t_hdata *hdata, void *pointer, - const char *name); - void *(*hdata_get_var_at_offset) (struct t_hdata *hdata, void *pointer, - int offset); - void *(*hdata_get_list) (struct t_hdata *hdata, const char *name); - int (*hdata_check_pointer) (struct t_hdata *hdata, void *list, - void *pointer); - void *(*hdata_move) (struct t_hdata *hdata, void *pointer, int count); - void *(*hdata_search) (struct t_hdata *hdata, void *pointer, - const char *search, int move); - char (*hdata_char) (struct t_hdata *hdata, void *pointer, - const char *name); - int (*hdata_integer) (struct t_hdata *hdata, void *pointer, - const char *name); - long (*hdata_long) (struct t_hdata *hdata, void *pointer, - const char *name); - const char *(*hdata_string) (struct t_hdata *hdata, void *pointer, - const char *name); - void *(*hdata_pointer) (struct t_hdata *hdata, void *pointer, - const char *name); - time_t (*hdata_time) (struct t_hdata *hdata, void *pointer, - const char *name); - struct t_hashtable *(*hdata_hashtable) (struct t_hdata *hdata, - void *pointer, const char *name); - int (*hdata_compare) (struct t_hdata *hdata, - void *pointer1, void *pointer2, const char *name, - int case_sensitive); - int (*hdata_set) (struct t_hdata *hdata, void *pointer, const char *name, - const char *value); - int (*hdata_update) (struct t_hdata *hdata, void *pointer, - struct t_hashtable *hashtable); - const char *(*hdata_get_string) (struct t_hdata *hdata, - const char *property); - - /* upgrade */ - struct t_upgrade_file *(*upgrade_new) (const char *filename, - int (*callback_read)(const void *pointer, - void *data, - struct t_upgrade_file *upgrade_file, - int object_id, - struct t_infolist *infolist), - const void *callback_read_pointer, - void *callback_read_data); - int (*upgrade_write_object) (struct t_upgrade_file *upgrade_file, - int object_id, - struct t_infolist *infolist); - int (*upgrade_read) (struct t_upgrade_file *upgrade_file); - void (*upgrade_close) (struct t_upgrade_file *upgrade_file); -}; - -extern int weechat_plugin_init (struct t_weechat_plugin *plugin, - int argc, char *argv[]); -extern int weechat_plugin_end (struct t_weechat_plugin *plugin); - -/* macros for easy call to plugin API */ - -/* plugins */ -#define weechat_plugin_get_name(__plugin) \ - (weechat_plugin->plugin_get_name)(__plugin) - -/* strings */ -#define weechat_charset_set(__charset) \ - (weechat_plugin->charset_set)(weechat_plugin, __charset) -#define weechat_iconv_to_internal(__charset, __string) \ - (weechat_plugin->iconv_to_internal)(__charset, __string) -#define weechat_iconv_from_internal(__charset, __string) \ - (weechat_plugin->iconv_from_internal)(__charset, __string) -#ifndef WEECHAT_H -#ifndef _ -#define _(string) (weechat_plugin->gettext)(string) -#endif /* _ */ -#ifndef N_ -#define N_(string) (string) -#endif /* N_ */ -#ifndef NG_ -#define NG_(single,plural,number) \ - (weechat_plugin->ngettext)(single, plural, number) -#endif /* NG_ */ -#endif /* WEECHAT_H */ -#define weechat_gettext(string) (weechat_plugin->gettext)(string) -#define weechat_ngettext(single,plural,number) \ - (weechat_plugin->ngettext)(single, plural, number) -#define weechat_strndup(__string, __length) \ - (weechat_plugin->strndup)(__string, __length) -#define weechat_string_tolower(__string) \ - (weechat_plugin->string_tolower)(__string) -#define weechat_string_toupper(__string) \ - (weechat_plugin->string_toupper)(__string) -#define weechat_strcasecmp(__string1, __string2) \ - (weechat_plugin->strcasecmp)(__string1, __string2) -#define weechat_strcasecmp_range(__string1, __string2, __range) \ - (weechat_plugin->strcasecmp_range)(__string1, __string2, __range) -#define weechat_strncasecmp(__string1, __string2, __max) \ - (weechat_plugin->strncasecmp)(__string1, __string2, __max) -#define weechat_strncasecmp_range(__string1, __string2, __max, __range) \ - (weechat_plugin->strncasecmp_range)(__string1, __string2, __max, \ - __range) -#define weechat_strcmp_ignore_chars(__string1, __string2, \ - __chars_ignored, __case_sensitive) \ - (weechat_plugin->strcmp_ignore_chars)(__string1, __string2, \ - __chars_ignored, \ - __case_sensitive) -#define weechat_strcasestr(__string, __search) \ - (weechat_plugin->strcasestr)(__string, __search) -#define weechat_strlen_screen(__string) \ - (weechat_plugin->strlen_screen)(__string) -#define weechat_string_match(__string, __mask, __case_sensitive) \ - (weechat_plugin->string_match)(__string, __mask, __case_sensitive) -#define weechat_string_replace(__string, __search, __replace) \ - (weechat_plugin->string_replace)(__string, __search, __replace) -#define weechat_string_expand_home(__path) \ - (weechat_plugin->string_expand_home)(__path) -#define weechat_string_eval_path_home(__path, __pointers, \ - __extra_vars, __options) \ - (weechat_plugin->string_eval_path_home)(__path, __pointers, \ - __extra_vars, __options) -#define weechat_string_remove_quotes(__string, __quotes) \ - (weechat_plugin->string_remove_quotes)(__string, __quotes) -#define weechat_string_strip(__string, __left, __right, __chars) \ - (weechat_plugin->string_strip)(__string, __left, __right, __chars) -#define weechat_string_convert_escaped_chars(__string) \ - (weechat_plugin->string_convert_escaped_chars)(__string) -#define weechat_string_mask_to_regex(__mask) \ - (weechat_plugin->string_mask_to_regex)(__mask) -#define weechat_string_regex_flags(__regex, __default_flags, __flags) \ - (weechat_plugin->string_regex_flags)(__regex, __default_flags, \ - __flags) -#define weechat_string_regcomp(__preg, __regex, __default_flags) \ - (weechat_plugin->string_regcomp)(__preg, __regex, __default_flags) -#define weechat_string_has_highlight(__string, __highlight_words) \ - (weechat_plugin->string_has_highlight)(__string, __highlight_words) -#define weechat_string_has_highlight_regex(__string, __regex) \ - (weechat_plugin->string_has_highlight_regex)(__string, __regex) -#define weechat_string_replace_regex(__string, __regex, __replace, \ - __reference_char, __callback, \ - __callback_data) \ - (weechat_plugin->string_replace_regex)(__string, __regex, \ - __replace, \ - __reference_char, \ - __callback, \ - __callback_data) -#define weechat_string_split(__string, __separator, __eol, __max, \ - __num_items) \ - (weechat_plugin->string_split)(__string, __separator, __eol, \ - __max, __num_items) -#define weechat_string_split_shell(__string, __num_items) \ - (weechat_plugin->string_split_shell)(__string, __num_items) -#define weechat_string_free_split(__split_string) \ - (weechat_plugin->string_free_split)(__split_string) -#define weechat_string_build_with_split_string(__split_string, \ - __separator) \ - (weechat_plugin->string_build_with_split_string)(__split_string, \ - __separator) -#define weechat_string_split_command(__command, __separator) \ - (weechat_plugin->string_split_command)(__command, __separator) -#define weechat_string_free_split_command(__split_command) \ - (weechat_plugin->string_free_split_command)(__split_command) -#define weechat_string_format_size(__size) \ - (weechat_plugin->string_format_size)(__size) -#define weechat_string_remove_color(__string, __replacement) \ - (weechat_plugin->string_remove_color)(__string, __replacement) -#define weechat_string_encode_base64(__from, __length, __to) \ - (weechat_plugin->string_encode_base64)(__from, __length, __to) -#define weechat_string_decode_base64(__from, __to) \ - (weechat_plugin->string_decode_base64)(__from, __to) -#define weechat_string_hex_dump(__data, __data_size, __bytes_per_line, \ - __prefix, __suffix) \ - (weechat_plugin->string_hex_dump)(__data, __data_size, \ - __bytes_per_line, __prefix, \ - __suffix) -#define weechat_string_is_command_char(__string) \ - (weechat_plugin->string_is_command_char)(__string) -#define weechat_string_input_for_buffer(__string) \ - (weechat_plugin->string_input_for_buffer)(__string) -#define weechat_string_eval_expression(__expr, __pointers, \ - __extra_vars, __options) \ - (weechat_plugin->string_eval_expression)(__expr, __pointers, \ - __extra_vars, __options) -#define weechat_string_dyn_alloc(__size_alloc) \ - (weechat_plugin->string_dyn_alloc)(__size_alloc) -#define weechat_string_dyn_copy(__string, __new_string) \ - (weechat_plugin->string_dyn_copy)(__string, __new_string) -#define weechat_string_dyn_concat(__string, __add) \ - (weechat_plugin->string_dyn_concat)(__string, __add) -#define weechat_string_dyn_free(__string, __free_string) \ - (weechat_plugin->string_dyn_free)(__string, __free_string) - -/* UTF-8 strings */ -#define weechat_utf8_has_8bits(__string) \ - (weechat_plugin->utf8_has_8bits)(__string) -#define weechat_utf8_is_valid(__string, __length, __error) \ - (weechat_plugin->utf8_is_valid)(__string, __length, __error) -#define weechat_utf8_normalize(__string, __char) \ - (weechat_plugin->utf8_normalize)(__string, __char) -#define weechat_utf8_prev_char(__start, __string) \ - (weechat_plugin->utf8_prev_char)(__start, __string) -#define weechat_utf8_next_char(__string) \ - (weechat_plugin->utf8_next_char)(__string) -#define weechat_utf8_char_int(__string) \ - (weechat_plugin->utf8_char_int)(__string) -#define weechat_utf8_char_size(__string) \ - (weechat_plugin->utf8_char_size)(__string) -#define weechat_utf8_strlen(__string) \ - (weechat_plugin->utf8_strlen)(__string) -#define weechat_utf8_strnlen(__string, __bytes) \ - (weechat_plugin->utf8_strnlen)(__string, __bytes) -#define weechat_utf8_strlen_screen(__string) \ - (weechat_plugin->utf8_strlen_screen)(__string) -#define weechat_utf8_charcmp(__string1, __string2) \ - (weechat_plugin->utf8_charcmp)(__string1, __string2) -#define weechat_utf8_charcasecmp(__string1, __string2) \ - (weechat_plugin->utf8_charcasecmp)(__string1, __string2) -#define weechat_utf8_char_size_screen(__string) \ - (weechat_plugin->utf8_char_size_screen)(__string) -#define weechat_utf8_add_offset(__string, __offset) \ - (weechat_plugin->utf8_add_offset)(__string, __offset) -#define weechat_utf8_real_pos(__string, __pos) \ - (weechat_plugin->utf8_real_pos)(__string, __pos) -#define weechat_utf8_pos(__string, __real_pos) \ - (weechat_plugin->utf8_pos)(__string, __real_pos) -#define weechat_utf8_strndup(__string, __length) \ - (weechat_plugin->utf8_strndup)(__string, __length) - -/* directories */ -#define weechat_mkdir_home(__directory, __mode) \ - (weechat_plugin->mkdir_home)(__directory, __mode) -#define weechat_mkdir(__directory, __mode) \ - (weechat_plugin->mkdir)(__directory, __mode) -#define weechat_mkdir_parents(__directory, __mode) \ - (weechat_plugin->mkdir_parents)(__directory, __mode) -#define weechat_exec_on_files(__directory, __recurse_subdirs, \ - __hidden_files, __callback, \ - __callback_data) \ - (weechat_plugin->exec_on_files)(__directory, __recurse_subdirs, \ - __hidden_files, \ - __callback, __callback_data) -#define weechat_file_get_content(__filename) \ - (weechat_plugin->file_get_content)(__filename) - -/* util */ -#define weechat_util_timeval_cmp(__time1, __time2) \ - (weechat_plugin->util_timeval_cmp)(__time1, __time2) -#define weechat_util_timeval_diff(__time1, __time2) \ - (weechat_plugin->util_timeval_diff)(__time1, __time2) -#define weechat_util_timeval_add(__time, __interval) \ - (weechat_plugin->util_timeval_add)(__time, __interval) -#define weechat_util_get_time_string(__date) \ - (weechat_plugin->util_get_time_string)(__date) -#define weechat_util_version_number(__version) \ - (weechat_plugin->util_version_number)(__version) - -/* sorted list */ -#define weechat_list_new() \ - (weechat_plugin->list_new)() -#define weechat_list_add(__list, __string, __where, __user_data) \ - (weechat_plugin->list_add)(__list, __string, __where, __user_data) -#define weechat_list_search(__list, __string) \ - (weechat_plugin->list_search)(__list, __string) -#define weechat_list_search_pos(__list, __string) \ - (weechat_plugin->list_search_pos)(__list, __string) -#define weechat_list_casesearch(__list, __string) \ - (weechat_plugin->list_casesearch)(__list, __string) -#define weechat_list_casesearch_pos(__list, __string) \ - (weechat_plugin->list_casesearch_pos)(__list, __string) -#define weechat_list_get(__list, __index) \ - (weechat_plugin->list_get)(__list, __index) -#define weechat_list_set(__item, __value) \ - (weechat_plugin->list_set)(__item, __value) -#define weechat_list_next(__item) \ - (weechat_plugin->list_next)(__item) -#define weechat_list_prev(__item) \ - (weechat_plugin->list_prev)(__item) -#define weechat_list_string(__item) \ - (weechat_plugin->list_string)(__item) -#define weechat_list_size(__list) \ - (weechat_plugin->list_size)(__list) -#define weechat_list_remove(__list, __item) \ - (weechat_plugin->list_remove)(__list, __item) -#define weechat_list_remove_all(__list) \ - (weechat_plugin->list_remove_all)(__list) -#define weechat_list_free(__list) \ - (weechat_plugin->list_free)(__list) - -/* array lists */ -#define weechat_arraylist_new(__initial_size, __sorted, \ - __allow_duplicates, __callback_cmp, \ - __callback_cmp_data, __callback_free, \ - __callback_free_data) \ - (weechat_plugin->arraylist_new)(__initial_size, __sorted, \ - __allow_duplicates, __callback_cmp, \ - __callback_cmp_data, __callback_free, \ - __callback_free_data) -#define weechat_arraylist_size(__arraylist) \ - (weechat_plugin->arraylist_size)(__arraylist) -#define weechat_arraylist_get(__arraylist, __index) \ - (weechat_plugin->arraylist_get)(__arraylist, __index) -#define weechat_arraylist_search(__arraylist, __pointer, __index, \ - __index_insert) \ - (weechat_plugin->arraylist_search)(__arraylist, __pointer, __index, \ - __index_insert) -#define weechat_arraylist_insert(__arraylist, __index, __pointer) \ - (weechat_plugin->arraylist_insert)(__arraylist, __index, __pointer) -#define weechat_arraylist_add(__arraylist, __pointer) \ - (weechat_plugin->arraylist_add)(__arraylist, __pointer) -#define weechat_arraylist_remove(__arraylist, __index) \ - (weechat_plugin->arraylist_remove)(__arraylist, __index) -#define weechat_arraylist_clear(__arraylist) \ - (weechat_plugin->arraylist_clear)(__arraylist) -#define weechat_arraylist_free(__arraylist) \ - (weechat_plugin->arraylist_free)(__arraylist) - -/* hash tables */ -#define weechat_hashtable_new(__size, __type_keys, __type_values, \ - __callback_hash_key, __callback_keycmp) \ - (weechat_plugin->hashtable_new)(__size, __type_keys, __type_values, \ - __callback_hash_key, \ - __callback_keycmp) -#define weechat_hashtable_set_with_size(__hashtable, __key, __key_size, \ - __value, __value_size) \ - (weechat_plugin->hashtable_set_with_size)(__hashtable, __key, \ - __key_size, __value, \ - __value_size) -#define weechat_hashtable_set(__hashtable, __key, __value) \ - (weechat_plugin->hashtable_set)(__hashtable, __key, __value) -#define weechat_hashtable_get(__hashtable, __key) \ - (weechat_plugin->hashtable_get)(__hashtable, __key) -#define weechat_hashtable_has_key(__hashtable, __key) \ - (weechat_plugin->hashtable_has_key)(__hashtable, __key) -#define weechat_hashtable_map(__hashtable, __cb_map, __cb_map_data) \ - (weechat_plugin->hashtable_map)(__hashtable, __cb_map, \ - __cb_map_data) -#define weechat_hashtable_map_string(__hashtable, __cb_map, \ - __cb_map_data) \ - (weechat_plugin->hashtable_map_string)(__hashtable, __cb_map, \ - __cb_map_data) -#define weechat_hashtable_dup(__hashtable) \ - (weechat_plugin->hashtable_dup)(__hashtable) -#define weechat_hashtable_get_integer(__hashtable, __property) \ - (weechat_plugin->hashtable_get_integer)(__hashtable, __property) -#define weechat_hashtable_get_string(__hashtable, __property) \ - (weechat_plugin->hashtable_get_string)(__hashtable, __property) -#define weechat_hashtable_set_pointer(__hashtable, __property, \ - __pointer) \ - (weechat_plugin->hashtable_set_pointer)(__hashtable, __property, \ - __pointer) -#define weechat_hashtable_add_to_infolist(__hashtable, __infolist_item, \ - __prefix) \ - (weechat_plugin->hashtable_add_to_infolist)(__hashtable, \ - __infolist_item, \ - __prefix) -#define weechat_hashtable_remove(__hashtable, __key) \ - (weechat_plugin->hashtable_remove)(__hashtable, __key) -#define weechat_hashtable_remove_all(__hashtable) \ - (weechat_plugin->hashtable_remove_all)(__hashtable) -#define weechat_hashtable_free(__hashtable) \ - (weechat_plugin->hashtable_free)(__hashtable) - -/* config files */ -#define weechat_config_new(__name, __callback_reload, \ - __callback_reload_pointer, \ - __callback_reload_data) \ - (weechat_plugin->config_new)(weechat_plugin, __name, \ - __callback_reload, \ - __callback_reload_pointer, \ - __callback_reload_data) -#define weechat_config_new_section(__config, __name, \ - __user_can_add_options, \ - __user_can_delete_options, \ - __cb_read, \ - __cb_read_pointer, \ - __cb_read_data, \ - __cb_write_std, \ - __cb_write_std_pointer, \ - __cb_write_std_data, \ - __cb_write_def, \ - __cb_write_def_pointer, \ - __cb_write_def_data, \ - __cb_create_option, \ - __cb_create_option_pointer, \ - __cb_create_option_data, \ - __cb_delete_option, \ - __cb_delete_option_pointer, \ - __cb_delete_option_data) \ - (weechat_plugin->config_new_section)(__config, __name, \ - __user_can_add_options, \ - __user_can_delete_options, \ - __cb_read, \ - __cb_read_pointer, \ - __cb_read_data, \ - __cb_write_std, \ - __cb_write_std_pointer, \ - __cb_write_std_data, \ - __cb_write_def, \ - __cb_write_def_pointer, \ - __cb_write_def_data, \ - __cb_create_option, \ - __cb_create_option_pointer, \ - __cb_create_option_data, \ - __cb_delete_option, \ - __cb_delete_option_pointer, \ - __cb_delete_option_data) -#define weechat_config_search_section(__config, __name) \ - (weechat_plugin->config_search_section)(__config, __name) -#define weechat_config_new_option(__config, __section, __name, __type, \ - __desc, __string_values, __min, \ - __max, __default, __value, \ - __null_value_allowed, \ - __callback_check, \ - __callback_check_pointer, \ - __callback_check_data, \ - __callback_change, \ - __callback_change_pointer, \ - __callback_change_data, \ - __callback_delete, \ - __callback_delete_pointer, \ - __callback_delete_data) \ - (weechat_plugin->config_new_option)(__config, __section, __name, \ - __type, __desc, \ - __string_values, \ - __min, __max, __default, \ - __value, \ - __null_value_allowed, \ - __callback_check, \ - __callback_check_pointer, \ - __callback_check_data, \ - __callback_change, \ - __callback_change_pointer, \ - __callback_change_data, \ - __callback_delete, \ - __callback_delete_pointer, \ - __callback_delete_data) -#define weechat_config_search_option(__config, __section, __name) \ - (weechat_plugin->config_search_option)(__config, __section, __name) -#define weechat_config_search_section_option(__config, __section, \ - __name, __section_found, \ - __option_found) \ - (weechat_plugin->config_search_section_option)(__config, __section, \ - __name, \ - __section_found, \ - __option_found); -#define weechat_config_search_with_string(__name, __config, __section, \ - __option, __pos_option) \ - (weechat_plugin->config_search_with_string)(__name, __config, \ - __section, __option, \ - __pos_option); -#define weechat_config_string_to_boolean(__string) \ - (weechat_plugin->config_string_to_boolean)(__string) -#define weechat_config_option_reset(__option, __run_callback) \ - (weechat_plugin->config_option_reset)(__option, __run_callback) -#define weechat_config_option_set(__option, __value, __run_callback) \ - (weechat_plugin->config_option_set)(__option, __value, \ - __run_callback) -#define weechat_config_option_set_null(__option, __run_callback) \ - (weechat_plugin->config_option_set_null)(__option, __run_callback) -#define weechat_config_option_unset(__option) \ - (weechat_plugin->config_option_unset)(__option) -#define weechat_config_option_rename(__option, __new_name) \ - (weechat_plugin->config_option_rename)(__option, __new_name) -#define weechat_config_option_get_string(__option, __property) \ - (weechat_plugin->config_option_get_string)(__option, __property) -#define weechat_config_option_get_pointer(__option, __property) \ - (weechat_plugin->config_option_get_pointer)(__option, __property) -#define weechat_config_option_is_null(__option) \ - (weechat_plugin->config_option_is_null)(__option) -#define weechat_config_option_default_is_null(__option) \ - (weechat_plugin->config_option_default_is_null)(__option) -#define weechat_config_boolean(__option) \ - (weechat_plugin->config_boolean)(__option) -#define weechat_config_boolean_default(__option) \ - (weechat_plugin->config_boolean_default)(__option) -#define weechat_config_integer(__option) \ - (weechat_plugin->config_integer)(__option) -#define weechat_config_integer_default(__option) \ - (weechat_plugin->config_integer_default)(__option) -#define weechat_config_string(__option) \ - (weechat_plugin->config_string)(__option) -#define weechat_config_string_default(__option) \ - (weechat_plugin->config_string_default)(__option) -#define weechat_config_color(__option) \ - (weechat_plugin->config_color)(__option) -#define weechat_config_color_default(__option) \ - (weechat_plugin->config_color_default)(__option) -#define weechat_config_write_option(__config, __option) \ - (weechat_plugin->config_write_option)(__config, __option) -#define weechat_config_write_line(__config, __option, __value...) \ - (weechat_plugin->config_write_line)(__config, __option, ##__value) -#define weechat_config_write(__config) \ - (weechat_plugin->config_write)(__config) -#define weechat_config_read(__config) \ - (weechat_plugin->config_read)(__config) -#define weechat_config_reload(__config) \ - (weechat_plugin->config_reload)(__config) -#define weechat_config_option_free(__option) \ - (weechat_plugin->config_option_free)(__option) -#define weechat_config_section_free_options(__section) \ - (weechat_plugin->config_section_free_options)(__section) -#define weechat_config_section_free(__section) \ - (weechat_plugin->config_section_free)(__section) -#define weechat_config_free(__config) \ - (weechat_plugin->config_free)(__config) -#define weechat_config_get(__option) \ - (weechat_plugin->config_get)(__option) -#define weechat_config_get_plugin(__option) \ - (weechat_plugin->config_get_plugin)(weechat_plugin, __option) -#define weechat_config_is_set_plugin(__option) \ - (weechat_plugin->config_is_set_plugin)(weechat_plugin, __option) -#define weechat_config_set_plugin(__option, __value) \ - (weechat_plugin->config_set_plugin)(weechat_plugin, __option, \ - __value) -#define weechat_config_set_desc_plugin(__option, __description) \ - (weechat_plugin->config_set_desc_plugin)(weechat_plugin, __option, \ - __description) -#define weechat_config_unset_plugin(__option) \ - (weechat_plugin->config_unset_plugin)(weechat_plugin, __option) - -/* key bindings */ -#define weechat_key_bind(__context, __keys) \ - (weechat_plugin->key_bind)(__context, __keys) -#define weechat_key_unbind(__context, __key) \ - (weechat_plugin->key_unbind)(__context, __key) - -/* display */ -#define weechat_prefix(__prefix) \ - (weechat_plugin->prefix)(__prefix) -#define weechat_color(__color_name) \ - (weechat_plugin->color)(__color_name) -#define weechat_printf(__buffer, __message, __argz...) \ - (weechat_plugin->printf_date_tags)(__buffer, 0, NULL, __message, \ - ##__argz) -#define weechat_printf_date_tags(__buffer, __date, __tags, __message, \ - __argz...) \ - (weechat_plugin->printf_date_tags)(__buffer, __date, __tags, \ - __message, ##__argz) -#define weechat_printf_y(__buffer, __y, __message, __argz...) \ - (weechat_plugin->printf_y)(__buffer, __y, __message, ##__argz) -#define weechat_log_printf(__message, __argz...) \ - (weechat_plugin->log_printf)(__message, ##__argz) - -/* hooks */ -#define weechat_hook_command(__command, __description, __args, \ - __args_desc, __completion, __callback, \ - __pointer, __data) \ - (weechat_plugin->hook_command)(weechat_plugin, __command, \ - __description, __args, __args_desc, \ - __completion, __callback, __pointer, \ - __data) -#define weechat_hook_command_run(__command, __callback, __pointer, \ - __data) \ - (weechat_plugin->hook_command_run)(weechat_plugin, __command, \ - __callback, __pointer, __data) -#define weechat_hook_timer(__interval, __align_second, __max_calls, \ - __callback, __pointer, __data) \ - (weechat_plugin->hook_timer)(weechat_plugin, __interval, \ - __align_second, __max_calls, \ - __callback, __pointer, __data) -#define weechat_hook_fd(__fd, __flag_read, __flag_write, \ - __flag_exception, __callback, __pointer, \ - __data) \ - (weechat_plugin->hook_fd)(weechat_plugin, __fd, __flag_read, \ - __flag_write, __flag_exception, \ - __callback, __pointer, __data) -#define weechat_hook_process(__command, __timeout, __callback, \ - __callback_pointer, __callback_data) \ - (weechat_plugin->hook_process)(weechat_plugin, __command, \ - __timeout, __callback, \ - __callback_pointer, __callback_data) -#define weechat_hook_process_hashtable(__command, __options, __timeout, \ - __callback, __callback_pointer, \ - __callback_data) \ - (weechat_plugin->hook_process_hashtable)(weechat_plugin, __command, \ - __options, __timeout, \ - __callback, \ - __callback_pointer, \ - __callback_data) -#define weechat_hook_connect(__proxy, __address, __port, __ipv6, \ - __retry, __gnutls_sess, __gnutls_cb, \ - __gnutls_dhkey_size, __gnutls_priorities, \ - __local_hostname, __callback, __pointer, \ - __data) \ - (weechat_plugin->hook_connect)(weechat_plugin, __proxy, __address, \ - __port, __ipv6, __retry, \ - __gnutls_sess, __gnutls_cb, \ - __gnutls_dhkey_size, \ - __gnutls_priorities, \ - __local_hostname, \ - __callback, __pointer, __data) -#define weechat_hook_print(__buffer, __tags, __msg, __strip__colors, \ - __callback, __pointer, __data) \ - (weechat_plugin->hook_print)(weechat_plugin, __buffer, __tags, \ - __msg, __strip__colors, __callback, \ - __pointer, __data) -#define weechat_hook_signal(__signal, __callback, __pointer, __data) \ - (weechat_plugin->hook_signal)(weechat_plugin, __signal, __callback, \ - __pointer, __data) -#define weechat_hook_signal_send(__signal, __type_data, __signal_data) \ - (weechat_plugin->hook_signal_send)(__signal, __type_data, \ - __signal_data) -#define weechat_hook_hsignal(__signal, __callback, __pointer, __data) \ - (weechat_plugin->hook_hsignal)(weechat_plugin, __signal, \ - __callback, __pointer, __data) -#define weechat_hook_hsignal_send(__signal, __hashtable) \ - (weechat_plugin->hook_hsignal_send)(__signal, __hashtable) -#define weechat_hook_config(__option, __callback, __pointer, __data) \ - (weechat_plugin->hook_config)(weechat_plugin, __option, __callback, \ - __pointer, __data) -#define weechat_hook_completion(__completion, __description, \ - __callback, __pointer, __data) \ - (weechat_plugin->hook_completion)(weechat_plugin, __completion, \ - __description, __callback, \ - __pointer, __data) -#define weechat_hook_completion_get_string(__completion, __property) \ - (weechat_plugin->hook_completion_get_string)(__completion, \ - __property) -#define weechat_hook_completion_list_add(__completion, __word, \ - __nick_completion, __where) \ - (weechat_plugin->hook_completion_list_add)(__completion, __word, \ - __nick_completion, \ - __where) -#define weechat_hook_modifier(__modifier, __callback, __pointer, \ - __data) \ - (weechat_plugin->hook_modifier)(weechat_plugin, __modifier, \ - __callback, __pointer, __data) -#define weechat_hook_modifier_exec(__modifier, __modifier_data, \ - __string) \ - (weechat_plugin->hook_modifier_exec)(weechat_plugin, __modifier, \ - __modifier_data, __string) -#define weechat_hook_info(__info_name, __description, \ - __args_description, __callback, __pointer, \ - __data) \ - (weechat_plugin->hook_info)(weechat_plugin, __info_name, \ - __description, __args_description, \ - __callback, __pointer, __data) -#define weechat_hook_info_hashtable(__info_name, __description, \ - __args_description, \ - __output_description, \ - __callback, \ - __pointer, \ - __data) \ - (weechat_plugin->hook_info_hashtable)(weechat_plugin, __info_name, \ - __description, \ - __args_description, \ - __output_description, \ - __callback, __pointer, \ - __data) -#define weechat_hook_infolist(__infolist_name, __description, \ - __pointer_description, \ - __args_description, __callback, \ - __pointer, __data) \ - (weechat_plugin->hook_infolist)(weechat_plugin, __infolist_name, \ - __description, \ - __pointer_description, \ - __args_description, __callback, \ - __pointer, __data) -#define weechat_hook_hdata(__hdata_name, __description, __callback, \ - __pointer, __data) \ - (weechat_plugin->hook_hdata)(weechat_plugin, __hdata_name, \ - __description, __callback, __pointer, \ - __data) -#define weechat_hook_focus(__area, __callback, __pointer, __data) \ - (weechat_plugin->hook_focus)(weechat_plugin, __area, __callback, \ - __pointer, __data) -#define weechat_hook_set(__hook, __property, __value) \ - (weechat_plugin->hook_set)(__hook, __property, __value) -#define weechat_unhook(__hook) \ - (weechat_plugin->unhook)( __hook) -#define weechat_unhook_all(__subplugin) \ - (weechat_plugin->unhook_all)(weechat_plugin, __subplugin) - -/* buffers */ -#define weechat_buffer_new(__name, __input_callback, \ - __input_callback_pointer, \ - __input_callback_data, \ - __close_callback, \ - __close_callback_pointer, \ - __close_callback_data) \ - (weechat_plugin->buffer_new)(weechat_plugin, __name, \ - __input_callback, \ - __input_callback_pointer, \ - __input_callback_data, \ - __close_callback, \ - __close_callback_pointer, \ - __close_callback_data) -#define weechat_buffer_search(__plugin, __name) \ - (weechat_plugin->buffer_search)(__plugin, __name) -#define weechat_buffer_search_main() \ - (weechat_plugin->buffer_search_main)() -#define weechat_current_buffer() \ - (weechat_plugin->buffer_search)(NULL, NULL) -#define weechat_buffer_clear(__buffer) \ - (weechat_plugin->buffer_clear)(__buffer) -#define weechat_buffer_close(__buffer) \ - (weechat_plugin->buffer_close)(__buffer) -#define weechat_buffer_merge(__buffer, __target_buffer) \ - (weechat_plugin->buffer_merge)(__buffer, __target_buffer) -#define weechat_buffer_unmerge(__buffer, __number) \ - (weechat_plugin->buffer_unmerge)(__buffer, __number) -#define weechat_buffer_get_integer(__buffer, __property) \ - (weechat_plugin->buffer_get_integer)(__buffer, __property) -#define weechat_buffer_get_string(__buffer, __property) \ - (weechat_plugin->buffer_get_string)(__buffer, __property) -#define weechat_buffer_get_pointer(__buffer, __property) \ - (weechat_plugin->buffer_get_pointer)(__buffer, __property) -#define weechat_buffer_set(__buffer, __property, __value) \ - (weechat_plugin->buffer_set)(__buffer, __property, __value) -#define weechat_buffer_set_pointer(__buffer, __property, __pointer) \ - (weechat_plugin->buffer_set_pointer)(__buffer, __property, \ - __pointer) -#define weechat_buffer_string_replace_local_var(__buffer, __string) \ - (weechat_plugin->buffer_string_replace_local_var)(__buffer, \ - __string) -#define weechat_buffer_match_list(__buffer, __string) \ - (weechat_plugin->buffer_match_list)(__buffer, __string) - -/* windows */ -#define weechat_window_search_with_buffer(__buffer) \ - (weechat_plugin->window_search_with_buffer)(__buffer) -#define weechat_window_get_integer(__window, __property) \ - (weechat_plugin->window_get_integer)(__window, __property) -#define weechat_window_get_string(__window, __property) \ - (weechat_plugin->window_get_string)(__window, __property) -#define weechat_window_get_pointer(__window, __property) \ - (weechat_plugin->window_get_pointer)(__window, __property) -#define weechat_current_window() \ - (weechat_plugin->window_get_pointer)(NULL, "current") -#define weechat_window_set_title(__title) \ - (weechat_plugin->window_set_title)(__title) - -/* nicklist */ -#define weechat_nicklist_add_group(__buffer, __parent_group, __name, \ - __color, __visible) \ - (weechat_plugin->nicklist_add_group)(__buffer, __parent_group, \ - __name, __color, __visible) -#define weechat_nicklist_search_group(__buffer, __from_group, __name) \ - (weechat_plugin->nicklist_search_group)(__buffer, __from_group, \ - __name) -#define weechat_nicklist_add_nick(__buffer, __group, __name, __color, \ - __prefix, __prefix_color, __visible) \ - (weechat_plugin->nicklist_add_nick)(__buffer, __group, __name, \ - __color, __prefix, \ - __prefix_color, __visible) -#define weechat_nicklist_search_nick(__buffer, __from_group, __name) \ - (weechat_plugin->nicklist_search_nick)(__buffer, __from_group, \ - __name) -#define weechat_nicklist_remove_group(__buffer, __group) \ - (weechat_plugin->nicklist_remove_group)(__buffer, __group) -#define weechat_nicklist_remove_nick(__buffer, __nick) \ - (weechat_plugin->nicklist_remove_nick)(__buffer, __nick) -#define weechat_nicklist_remove_all(__buffer) \ - (weechat_plugin->nicklist_remove_all)(__buffer) -#define weechat_nicklist_get_next_item(__buffer, __group, __nick) \ - (weechat_plugin->nicklist_get_next_item)(__buffer, __group, __nick) -#define weechat_nicklist_group_get_integer(__buffer, __group, \ - __property) \ - (weechat_plugin->nicklist_group_get_integer)(__buffer, __group, \ - __property) -#define weechat_nicklist_group_get_string(__buffer, __group, \ - __property) \ - (weechat_plugin->nicklist_group_get_string)(__buffer, __group, \ - __property) -#define weechat_nicklist_group_get_pointer(__buffer, __group, \ - __property) \ - (weechat_plugin->nicklist_group_get_pointer)(__buffer, __group, \ - __property) -#define weechat_nicklist_group_set(__buffer, __group, __property, \ - __value) \ - (weechat_plugin->nicklist_group_set)(__buffer, __group, __property, \ - __value) -#define weechat_nicklist_nick_get_integer(__buffer, __nick, __property) \ - (weechat_plugin->nicklist_nick_get_integer)(__buffer, __nick, \ - __property) -#define weechat_nicklist_nick_get_string(__buffer, __nick, __property) \ - (weechat_plugin->nicklist_nick_get_string)(__buffer, __nick, \ - __property) -#define weechat_nicklist_nick_get_pointer(__buffer, __nick, __property) \ - (weechat_plugin->nicklist_nick_get_pointer)(__buffer, __nick, \ - __property) -#define weechat_nicklist_nick_set(__buffer, __nick, __property, \ - __value) \ - (weechat_plugin->nicklist_nick_set)(__buffer, __nick, __property, \ - __value) - -/* bars */ -#define weechat_bar_item_search(__name) \ - (weechat_plugin->bar_item_search)(__name) -#define weechat_bar_item_new(__name, __build_callback, \ - __build_callback_pointer, \ - __build_callback_data) \ - (weechat_plugin->bar_item_new)(weechat_plugin, __name, \ - __build_callback, \ - __build_callback_pointer, \ - __build_callback_data) -#define weechat_bar_item_update(__name) \ - (weechat_plugin->bar_item_update)(__name) -#define weechat_bar_item_remove(__item) \ - (weechat_plugin->bar_item_remove)(__item) -#define weechat_bar_search(__name) \ - (weechat_plugin->bar_search)(__name) -#define weechat_bar_new(__name, __hidden, __priority, __type, \ - __condition, __position, __filling_top_bottom, \ - __filling_left_right, __size, __size_max, \ - __color_fg, __color_delim, __color_bg, \ - __separator, __items) \ - (weechat_plugin->bar_new)(__name, __hidden, __priority, __type, \ - __condition, __position, \ - __filling_top_bottom, \ - __filling_left_right, \ - __size, __size_max, __color_fg, \ - __color_delim, __color_bg, __separator, \ - __items) -#define weechat_bar_set(__bar, __property, __value) \ - (weechat_plugin->bar_set)(__bar, __property, __value) -#define weechat_bar_update(__name) \ - (weechat_plugin->bar_update)(__name) -#define weechat_bar_remove(__bar) \ - (weechat_plugin->bar_remove)(__bar) - -/* command */ -#define weechat_command(__buffer, __command) \ - (weechat_plugin->command)(weechat_plugin, __buffer, __command) - -/* network */ -#define weechat_network_pass_proxy(__proxy, __sock, __address, __port) \ - (weechat_plugin->network_pass_proxy)(__proxy, __sock, __address, \ - __port) -#define weechat_network_connect_to(__proxy, __address, \ - __address_length) \ - (weechat_plugin->network_connect_to)(__proxy, __address, \ - __address_length) - -/* infos */ -#define weechat_info_get(__info_name, __arguments) \ - (weechat_plugin->info_get)(weechat_plugin, __info_name, \ - __arguments) -#define weechat_info_get_hashtable(__info_name, __hashtable) \ - (weechat_plugin->info_get_hashtable)(weechat_plugin, __info_name, \ - __hashtable) - -/* infolists */ -#define weechat_infolist_new() \ - (weechat_plugin->infolist_new)(weechat_plugin) -#define weechat_infolist_new_item(__list) \ - (weechat_plugin->infolist_new_item)(__list) -#define weechat_infolist_new_var_integer(__item, __name, __value) \ - (weechat_plugin->infolist_new_var_integer)(__item, __name, __value) -#define weechat_infolist_new_var_string(__item, __name, __value) \ - (weechat_plugin->infolist_new_var_string)(__item, __name, __value) -#define weechat_infolist_new_var_pointer(__item, __name, __pointer) \ - (weechat_plugin->infolist_new_var_pointer)(__item, __name, \ - __pointer) -#define weechat_infolist_new_var_buffer(__item, __name, __buffer, \ - __size) \ - (weechat_plugin->infolist_new_var_buffer)(__item, __name, __buffer, \ - __size) -#define weechat_infolist_new_var_time(__item, __name, __time) \ - (weechat_plugin->infolist_new_var_time)(__item, __name, __time) -#define weechat_infolist_search_var(__list, __name) \ - (weechat_plugin->infolist_search_var)(__list, __name) -#define weechat_infolist_get(__infolist_name, __pointer, __arguments) \ - (weechat_plugin->infolist_get)(weechat_plugin, __infolist_name, \ - __pointer, __arguments) -#define weechat_infolist_next(__list) \ - (weechat_plugin->infolist_next)(__list) -#define weechat_infolist_prev(__list) \ - (weechat_plugin->infolist_prev)(__list) -#define weechat_infolist_reset_item_cursor(__list) \ - (weechat_plugin->infolist_reset_item_cursor)(__list) -#define weechat_infolist_fields(__list) \ - (weechat_plugin->infolist_fields)(__list) -#define weechat_infolist_integer(__item, __var) \ - (weechat_plugin->infolist_integer)(__item, __var) -#define weechat_infolist_string(__item, __var) \ - (weechat_plugin->infolist_string)(__item, __var) -#define weechat_infolist_pointer(__item, __var) \ - (weechat_plugin->infolist_pointer)(__item, __var) -#define weechat_infolist_buffer(__item, __var, __size) \ - (weechat_plugin->infolist_buffer)(__item, __var, __size) -#define weechat_infolist_time(__item, __var) \ - (weechat_plugin->infolist_time)(__item, __var) -#define weechat_infolist_free(__list) \ - (weechat_plugin->infolist_free)(__list) - -/* hdata */ -#define weechat_hdata_new(__hdata_name, __var_prev, __var_next, \ - __create_allowed, __delete_allowed, \ - __callback_update, __callback_update_data) \ - (weechat_plugin->hdata_new)(weechat_plugin, __hdata_name, \ - __var_prev, __var_next, \ - __create_allowed, __delete_allowed, \ - __callback_update, \ - __callback_update_data) -#define weechat_hdata_new_var(__hdata, __name, __offset, __type, \ - __update_allowed, __array_size, \ - __hdata_name) \ - (weechat_plugin->hdata_new_var)(__hdata, __name, __offset, __type, \ - __update_allowed, __array_size, \ - __hdata_name) -#define WEECHAT_HDATA_VAR(__struct, __name, __type, __update_allowed, \ - __array_size, __hdata_name) \ - weechat_hdata_new_var (hdata, #__name, offsetof (__struct, __name), \ - WEECHAT_HDATA_##__type, __update_allowed, \ - __array_size, __hdata_name) -#define weechat_hdata_new_list(__hdata, __name, __pointer, __flags) \ - (weechat_plugin->hdata_new_list)(__hdata, __name, __pointer, \ - __flags) -#define WEECHAT_HDATA_LIST(__name, __flags) \ - weechat_hdata_new_list (hdata, #__name, &(__name), __flags); -#define weechat_hdata_get(__hdata_name) \ - (weechat_plugin->hdata_get)(weechat_plugin, __hdata_name) -#define weechat_hdata_get_var_offset(__hdata, __name) \ - (weechat_plugin->hdata_get_var_offset)(__hdata, __name) -#define weechat_hdata_get_var_type(__hdata, __name) \ - (weechat_plugin->hdata_get_var_type)(__hdata, __name) -#define weechat_hdata_get_var_type_string(__hdata, __name) \ - (weechat_plugin->hdata_get_var_type_string)(__hdata, __name) -#define weechat_hdata_get_var_array_size(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_get_var_array_size)(__hdata, __pointer, \ - __name) -#define weechat_hdata_get_var_array_size_string(__hdata, __pointer, \ - __name) \ - (weechat_plugin->hdata_get_var_array_size_string)(__hdata, \ - __pointer, \ - __name) -#define weechat_hdata_get_var_hdata(__hdata, __name) \ - (weechat_plugin->hdata_get_var_hdata)(__hdata, __name) -#define weechat_hdata_get_var(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_get_var)(__hdata, __pointer, __name) -#define weechat_hdata_get_var_at_offset(__hdata, __pointer, __offset) \ - (weechat_plugin->hdata_get_var_at_offset)(__hdata, __pointer, \ - __offset) -#define weechat_hdata_get_list(__hdata, __name) \ - (weechat_plugin->hdata_get_list)(__hdata, __name) -#define weechat_hdata_check_pointer(__hdata, __list, __pointer) \ - (weechat_plugin->hdata_check_pointer)(__hdata, __list, __pointer) -#define weechat_hdata_move(__hdata, __pointer, __count) \ - (weechat_plugin->hdata_move)(__hdata, __pointer, __count) -#define weechat_hdata_search(__hdata, __pointer, __search, __move) \ - (weechat_plugin->hdata_search)(__hdata, __pointer, __search, \ - __move) -#define weechat_hdata_char(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_char)(__hdata, __pointer, __name) -#define weechat_hdata_integer(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_integer)(__hdata, __pointer, __name) -#define weechat_hdata_long(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_long)(__hdata, __pointer, __name) -#define weechat_hdata_string(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_string)(__hdata, __pointer, __name) -#define weechat_hdata_pointer(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_pointer)(__hdata, __pointer, __name) -#define weechat_hdata_time(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_time)(__hdata, __pointer, __name) -#define weechat_hdata_hashtable(__hdata, __pointer, __name) \ - (weechat_plugin->hdata_hashtable)(__hdata, __pointer, __name) -#define weechat_hdata_compare(__hdata, __pointer1, __pointer2, __name, \ - __case_sensitive) \ - (weechat_plugin->hdata_compare)(__hdata, __pointer1, __pointer2, \ - __name, __case_sensitive) -#define weechat_hdata_set(__hdata, __pointer, __name, __value) \ - (weechat_plugin->hdata_set)(__hdata, __pointer, __name, __value) -#define weechat_hdata_update(__hdata, __pointer, __hashtable) \ - (weechat_plugin->hdata_update)(__hdata, __pointer, __hashtable) -#define weechat_hdata_get_string(__hdata, __property) \ - (weechat_plugin->hdata_get_string)(__hdata, __property) - -/* upgrade */ -#define weechat_upgrade_new(__filename, __callback_read, \ - __callback_read_pointer, \ - __callback_read_data) \ - (weechat_plugin->upgrade_new)(__filename, __callback_read, \ - __callback_read_pointer, \ - __callback_read_data) -#define weechat_upgrade_write_object(__upgrade_file, __object_id, \ - __infolist) \ - (weechat_plugin->upgrade_write_object)(__upgrade_file, __object_id, \ - __infolist) -#define weechat_upgrade_read(__upgrade_file) \ - (weechat_plugin->upgrade_read)(__upgrade_file) -#define weechat_upgrade_close(__upgrade_file) \ - (weechat_plugin->upgrade_close)(__upgrade_file) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* WEECHAT_WEECHAT_PLUGIN_H */ diff --git a/xmpp.c b/xmpp.c index fcf24e2..d9ce258 100644 --- a/xmpp.c +++ b/xmpp.c @@ -8,7 +8,7 @@ #include #include -#include "weechat-plugin.h" +#include "weechat/weechat-plugin.h" #include "xmpp.h" //#include "slack-config.h" //#include "slack-command.h" @@ -74,7 +74,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { weechat_bar_new("typing", "off", "400", "window", "${typing}", "bottom", "horizontal", "vertical", - "1", "1", "default", "default", "default", + "1", "1", "default", "default", "default", "default", "off", "xmpp_typing"); } From 86bfc6359c392866bf6d67075881d2812398a686 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 Jun 2021 02:31:45 +0100 Subject: [PATCH 070/118] efforts --- .dir-locals.el | 4 +- Makefile | 7 +- slack-command.c | 4 +- slack-completion.c | 4 +- slack-config.h | 57 ------- slack-workspace.c | 2 +- slack-config.c => xmpp-config.c | 269 ++++++++++++++++++-------------- xmpp-config.h | 59 +++++++ xmpp.c | 55 ++++--- 9 files changed, 258 insertions(+), 203 deletions(-) delete mode 100644 slack-config.h rename slack-config.c => xmpp-config.c (51%) create mode 100644 xmpp-config.h diff --git a/.dir-locals.el b/.dir-locals.el index 6166711..89604c0 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -3,10 +3,10 @@ ((c-mode (eval . (setq-local flycheck-clang-include-path - (list (expand-file-name "libwebsockets/include" (projectile-project-root)) + (list (expand-file-name "libstrophe" (projectile-project-root)) (expand-file-name "json-c" (projectile-project-root))))) (eval . (setq-local company-clang-arguments - (list (concat "-I" (expand-file-name "libwebsockets/include" (projectile-project-root))) + (list (concat "-I" (expand-file-name "libstrophe" (projectile-project-root))) (concat "-I" (expand-file-name "json-c" (projectile-project-root)))))) (eval . (setq-local tags-table-list (expand-file-name ".git/tags" (projectile-project-root)))) (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) diff --git a/Makefile b/Makefile index b40bb4a..94bb22e 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,14 @@ RM=rm -f FIND=find CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibstrophe -Ijson-c LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) -LDLIBS= +LDLIBS=-lssl -lxml2 PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib INSTALL ?= /usr/bin/install SRCS=xmpp.c \ + xmpp-config.c \ OLDSRCS=slack.c \ slack-api.c \ @@ -48,10 +49,10 @@ OBJS=$(subst .c,.o,$(SRCS)) libstrophe/.libs/libstrophe.a json-c/libjson-c.a all: libstrophe/.libs/libstrophe.a json-c/libjson-c.a weechat-xmpp weechat-xmpp: $(OBJS) - $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(LDLIBS) + $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(LDLIBS) libstrophe/.libs/libstrophe.a: - cd libstrophe && ./bootstrap.sh && env CFLAGS= LDFLAGS= ./configure + cd libstrophe && ./bootstrap.sh && env CFLAGS=-fPIC LDFLAGS= ./configure $(MAKE) -C libstrophe libstrophe: libstrophe/.libs/libstrophe.a diff --git a/slack-command.c b/slack-command.c index b2dd04d..201ff4d 100644 --- a/slack-command.c +++ b/slack-command.c @@ -307,7 +307,7 @@ int slack_command_slack(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - /* make C compiler happy */ + (void) pointer; (void) data; (void) buffer; @@ -353,7 +353,7 @@ int slack_command_me(const void *pointer, void *data, struct t_slack_request *request; char *text; - /* make C compiler happy */ + (void) pointer; (void) data; (void) buffer; diff --git a/slack-completion.c b/slack-completion.c index 1002e0c..c8c6e80 100644 --- a/slack-completion.c +++ b/slack-completion.c @@ -54,7 +54,7 @@ int slack_completion_channel_nicks_cb(const void *pointer, void *data, struct t_slack_channel_member *ptr_member; struct t_slack_user *ptr_user; - /* make C compiler happy */ + (void) pointer; (void) data; (void) completion_item; @@ -108,7 +108,7 @@ int slack_completion_workspaces_cb(const void *pointer, void *data, { struct t_slack_workspace *ptr_workspace; - /* make C compiler happy */ + (void) pointer; (void) data; (void) completion_item; diff --git a/slack-config.h b/slack-config.h deleted file mode 100644 index 19d10b3..0000000 --- a/slack-config.h +++ /dev/null @@ -1,57 +0,0 @@ -// 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/. - -#ifndef _SLACK_CONFIG_H_ -#define _SLACK_CONFIG_H_ - -#define SLACK_CONFIG_NAME "slack" - -enum t_slack_config_nick_completion -{ - SLACK_CONFIG_NICK_COMPLETION_SMART_OFF = 0, - SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS, - SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, -}; - -extern struct t_config_file *slack_config_file; - -extern struct t_config_section *slack_config_section_workspace_default; -extern struct t_config_section *slack_config_section_workspace; - -extern struct t_config_option *slack_config_look_nick_completion_smart; - -extern struct t_config_option *slack_config_workspace_default[]; - -int slack_config_workspace_check_value_cb(const void *pointer, void *data, - struct t_config_option *option, - const char *value); - -void slack_config_workspace_change_cb(const void *pointer, void *data, - struct t_config_option *option); - -struct t_config_option *slack_config_workspace_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 slack_config_init(); -extern int slack_config_read(); -extern int slack_config_write(); -extern void slack_config_free(); - -#endif /*SLACK_CONFIG_H*/ diff --git a/slack-workspace.c b/slack-workspace.c index 23228fe..358cb24 100644 --- a/slack-workspace.c +++ b/slack-workspace.c @@ -823,7 +823,7 @@ int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_call struct t_slack_workspace *ptr_workspace; struct t_slack_request *ptr_request; - /* make C compiler happy */ + (void) pointer; (void) data; (void) remaining_calls; diff --git a/slack-config.c b/xmpp-config.c similarity index 51% rename from slack-config.c rename to xmpp-config.c index 62d125e..5783fdf 100644 --- a/slack-config.c +++ b/xmpp-config.c @@ -4,33 +4,36 @@ #include #include +#include +#include -#include "weechat-plugin.h" -#include "slack.h" -#include "slack-config.h" -#include "slack-workspace.h" +#include "xmpp.h" +#include "xmpp-config.h" -struct t_config_file *slack_config_file; +struct t_config_file *xmpp_config_file; -struct t_config_section *slack_config_section_workspace_default; -struct t_config_section *slack_config_section_workspace; +//struct t_config_section *xmpp_config_section_workspace_default; +//struct t_config_section *xmpp_config_section_workspace; -struct t_config_option *slack_config_look_nick_completion_smart; +struct t_config_option *xmpp_config_serverdef_jid; +struct t_config_option *xmpp_config_serverdef_password; +struct t_config_option *xmpp_config_look_nick_completion_smart; -struct t_config_option *slack_config_workspace_default[SLACK_WORKSPACE_NUM_OPTIONS]; +/* +struct t_config_option *xmpp_config_workspace_default[XMPP_WORKSPACE_NUM_OPTIONS]; -int slack_config_workspace_check_value_cb(const void *pointer, void *data, - struct t_config_option *option, +int xmpp_config_workspace_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; + return 1; } -void slack_config_workspace_change_cb(const void *pointer, void *data, +void xmpp_config_workspace_change_cb(const void *pointer, void *data, struct t_config_option *option) { (void) pointer; @@ -38,7 +41,7 @@ void slack_config_workspace_change_cb(const void *pointer, void *data, (void) option; } -void slack_config_workspace_default_change_cb(const void *pointer, void *data, +void xmpp_config_workspace_default_change_cb(const void *pointer, void *data, struct t_config_option *option) { (void) pointer; @@ -47,7 +50,7 @@ void slack_config_workspace_default_change_cb(const void *pointer, void *data, } struct t_config_option * -slack_config_workspace_new_option (struct t_config_file *config_file, +xmpp_config_workspace_new_option (struct t_config_file *config_file, struct t_config_section *section, int index_option, const char *option_name, @@ -66,17 +69,17 @@ slack_config_workspace_new_option (struct t_config_file *config_file, const void *callback_change_pointer, void *callback_change_data) { - struct t_config_option *new_option; + struct t_config_option *new_option; new_option = NULL; switch (index_option) { - case SLACK_WORKSPACE_OPTION_TOKEN: + case XMPP_WORKSPACE_OPTION_TOKEN: new_option = weechat_config_new_option ( config_file, section, option_name, "string", - N_("slack api token"), + N_("xmpp api token"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -88,62 +91,47 @@ slack_config_workspace_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; - case SLACK_WORKSPACE_NUM_OPTIONS: + case XMPP_WORKSPACE_NUM_OPTIONS: break; } return new_option; } -void slack_config_workspace_create_default_options(struct t_config_section *section) +void xmpp_config_workspace_create_default_options(struct t_config_section *section) { int i; - for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) - { - slack_config_workspace_default[i] = slack_config_workspace_new_option( - slack_config_file, - section, - i, - slack_workspace_options[i][0], - slack_workspace_options[i][1], - slack_workspace_options[i][1], - 0, - &slack_config_workspace_check_value_cb, - slack_workspace_options[i][0], - NULL, - &slack_config_workspace_default_change_cb, - slack_workspace_options[i][0], - NULL); - } -} - -int slack_config_reload (const void *pointer, void *data, - struct t_config_file *config_file) -{ - /* make C compiler happy */ - (void) pointer; - (void) data; - - //weechat_config_section_free_options(slack_config_section_workspace_default); - //weechat_config_section_free_options(slack_config_section_workspace); - //slack_workspace_free_all(); - - return weechat_config_reload(config_file); + for (i = 0; i < XMPP_WORKSPACE_NUM_OPTIONS; i++) + { + xmpp_config_workspace_default[i] = xmpp_config_workspace_new_option( + xmpp_config_file, + section, + i, + xmpp_workspace_options[i][0], + xmpp_workspace_options[i][1], + xmpp_workspace_options[i][1], + 0, + &xmpp_config_workspace_check_value_cb, + xmpp_workspace_options[i][0], + NULL, + &xmpp_config_workspace_default_change_cb, + xmpp_workspace_options[i][0], + NULL); + } } -int slack_config_workspace_read_cb (const void *pointer, void *data, +int xmpp_config_workspace_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_slack_workspace *ptr_workspace; + struct t_xmpp_workspace *ptr_workspace; int index_option, rc, i; char *pos_option, *workspace_domain; - /* make C compiler happy */ (void) pointer; (void) data; (void) config_file; @@ -161,18 +149,18 @@ int slack_config_workspace_read_cb (const void *pointer, void *data, pos_option++; if (workspace_domain) { - index_option = slack_workspace_search_option(pos_option); + index_option = xmpp_workspace_search_option(pos_option); if (index_option >= 0) { - ptr_workspace = slack_workspace_search(workspace_domain); + ptr_workspace = xmpp_workspace_search(workspace_domain); if (!ptr_workspace) - ptr_workspace = slack_workspace_alloc(workspace_domain); + ptr_workspace = xmpp_workspace_alloc(workspace_domain); if (ptr_workspace) { if (ptr_workspace->reloading_from_config && !ptr_workspace->reloaded_from_config) { - for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + for (i = 0; i < XMPP_WORKSPACE_NUM_OPTIONS; i++) { weechat_config_option_set( ptr_workspace->options[i], NULL, 1); @@ -187,7 +175,7 @@ int slack_config_workspace_read_cb (const void *pointer, void *data, weechat_printf( NULL, _("%s%s: error adding workspace \"%s\""), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_prefix("error"), XMPP_PLUGIN_NAME, workspace_domain); } } @@ -201,30 +189,29 @@ int slack_config_workspace_read_cb (const void *pointer, void *data, weechat_printf( NULL, _("%s%s: error creating workspace option \"%s\""), - weechat_prefix("error"), SLACK_PLUGIN_NAME, option_name); + weechat_prefix("error"), XMPP_PLUGIN_NAME, option_name); } return rc; } -int slack_config_workspace_write_cb (const void *pointer, void *data, +int xmpp_config_workspace_write_cb (const void *pointer, void *data, struct t_config_file *config_file, const char *section_name) { - struct t_slack_workspace *ptr_workspace; + struct t_xmpp_workspace *ptr_workspace; int i; - /* make C compiler happy */ (void) pointer; (void) data; if (!weechat_config_write_line(config_file, section_name, NULL)) return WEECHAT_CONFIG_WRITE_ERROR; - for (ptr_workspace = slack_workspaces; ptr_workspace; + for (ptr_workspace = xmpp_workspaces; ptr_workspace; ptr_workspace = ptr_workspace->next_workspace) { - for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) + for (i = 0; i < XMPP_WORKSPACE_NUM_OPTIONS; i++) { if (!weechat_config_write_option(config_file, ptr_workspace->options[i])) @@ -234,19 +221,35 @@ int slack_config_workspace_write_cb (const void *pointer, void *data, return WEECHAT_CONFIG_WRITE_OK; } +*/ + +int xmpp_config_reload (const void *pointer, void *data, + struct t_config_file *config_file) +{ + (void) pointer; + (void) data; + + //weechat_config_section_free_options(xmpp_config_section_workspace_default); + //weechat_config_section_free_options(xmpp_config_section_workspace); + //xmpp_workspace_free_all(); + + return weechat_config_reload(config_file); +} -int slack_config_init() +int xmpp_config_init() { - struct t_config_section *ptr_section; + struct t_config_section *ptr_section_serverdef; + struct t_config_section *ptr_section_server; + struct t_config_section *ptr_section_look; - slack_config_file = weechat_config_new(SLACK_CONFIG_NAME, - &slack_config_reload, NULL, NULL); + xmpp_config_file = weechat_config_new(XMPP_CONFIG_NAME, + &xmpp_config_reload, NULL, NULL); - if(!slack_config_file) + if(!xmpp_config_file) return 0; - ptr_section = weechat_config_new_section( - slack_config_file, "look", + ptr_section_serverdef = weechat_config_new_section( + xmpp_config_file, "server_default", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, @@ -254,24 +257,17 @@ int slack_config_init() NULL, NULL, NULL, NULL, NULL, NULL); - if (!ptr_section) - { - weechat_config_free(slack_config_file); - slack_config_file = NULL; - return 0; - } - - slack_config_look_nick_completion_smart = weechat_config_new_option ( - slack_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_server = weechat_config_new_section( + xmpp_config_file, "server", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); - ptr_section = weechat_config_new_section( - slack_config_file, "workspace_default", + ptr_section_look = weechat_config_new_section( + xmpp_config_file, "look", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, @@ -279,52 +275,93 @@ int slack_config_init() NULL, NULL, NULL, NULL, NULL, NULL); - if (!ptr_section) + if (!ptr_section_serverdef + || !ptr_section_server + || !ptr_section_look) { - weechat_config_free(slack_config_file); - slack_config_file = NULL; + weechat_config_free(xmpp_config_file); + xmpp_config_file = NULL; return 0; } - slack_config_section_workspace_default = ptr_section; - - slack_config_workspace_create_default_options(ptr_section); + xmpp_config_serverdef_jid = weechat_config_new_option ( + xmpp_config_file, ptr_section_serverdef, + "jid", "string", + N_("XMPP Server JID"), + NULL, 0, 0, "", "", 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - ptr_section = weechat_config_new_section( - slack_config_file, "workspace", - 0, 0, - &slack_config_workspace_read_cb, NULL, NULL, - &slack_config_workspace_write_cb, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); + xmpp_config_serverdef_password = weechat_config_new_option ( + xmpp_config_file, ptr_section_serverdef, + "password", "string", + N_("XMPP Server Password"), + NULL, 0, 0, "", "", 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (!ptr_section) - { - weechat_config_free(slack_config_file); - slack_config_file = NULL; - return 0; - } + xmpp_config_look_nick_completion_smart = weechat_config_new_option ( + xmpp_config_file, ptr_section_look, + "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); - slack_config_section_workspace = ptr_section; + //ptr_section = weechat_config_new_section( + // xmpp_config_file, "workspace_default", + // 0, 0, + // NULL, NULL, NULL, + // NULL, NULL, NULL, + // NULL, NULL, NULL, + // NULL, NULL, NULL, + // NULL, NULL, NULL); + + //if (!ptr_section) + //{ + // weechat_config_free(xmpp_config_file); + // xmpp_config_file = NULL; + // return 0; + //} + + //xmpp_config_section_workspace_default = ptr_section; + + //xmpp_config_workspace_create_default_options(ptr_section); + + // ptr_section = weechat_config_new_section( + // xmpp_config_file, "workspace", + // 0, 0, + // &xmpp_config_workspace_read_cb, NULL, NULL, + // &xmpp_config_workspace_write_cb, NULL, NULL, + // NULL, NULL, NULL, + // NULL, NULL, NULL, + // NULL, NULL, NULL); + + //if (!ptr_section) + //{ + // weechat_config_free(xmpp_config_file); + // xmpp_config_file = NULL; + // return 0; + //} + + //xmpp_config_section_workspace = ptr_section; return 1; } -int slack_config_read() +int xmpp_config_read() { - int rc; + int rc; - rc = weechat_config_read(slack_config_file); + rc = weechat_config_read(xmpp_config_file); return rc; } -int slack_config_write() +int xmpp_config_write() { - return weechat_config_write(slack_config_file); + return weechat_config_write(xmpp_config_file); } -void slack_config_free() +void xmpp_config_free() { } diff --git a/xmpp-config.h b/xmpp-config.h new file mode 100644 index 0000000..c514960 --- /dev/null +++ b/xmpp-config.h @@ -0,0 +1,59 @@ +// 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/. + +#ifndef _XMPP_CONFIG_H_ +#define _XMPP_CONFIG_H_ + +#define XMPP_CONFIG_NAME "xmpp" + +enum t_xmpp_config_nick_completion +{ + XMPP_CONFIG_NICK_COMPLETION_SMART_OFF = 0, + XMPP_CONFIG_NICK_COMPLETION_SMART_SPEAKERS, + XMPP_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, +}; + +extern struct t_config_file *xmpp_config_file; + +//extern struct t_config_section *xmpp_config_section_workspace_default; +//extern struct t_config_section *xmpp_config_section_workspace; + +extern struct t_config_option *xmpp_config_serverdef_jid; +extern struct t_config_option *xmpp_config_serverdef_password; +extern struct t_config_option *xmpp_config_look_nick_completion_smart; + +//extern struct t_config_option *xmpp_config_workspace_default[]; + +//int xmpp_config_workspace_check_value_cb(const void *pointer, void *data, +// struct t_config_option *option, +// const char *value); + +//void xmpp_config_workspace_change_cb(const void *pointer, void *data, +// struct t_config_option *option); + +//struct t_config_option *xmpp_config_workspace_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 xmpp_config_init(); +extern int xmpp_config_read(); +extern int xmpp_config_write(); +extern void xmpp_config_free(); + +#endif /*XMPP_CONFIG_H*/ diff --git a/xmpp.c b/xmpp.c index d9ce258..7e5974e 100644 --- a/xmpp.c +++ b/xmpp.c @@ -7,10 +7,10 @@ #include #include #include +#include -#include "weechat/weechat-plugin.h" #include "xmpp.h" -//#include "slack-config.h" +#include "xmpp-config.h" //#include "slack-command.h" //#include "slack-workspace.h" //#include "slack-api.h" @@ -31,34 +31,47 @@ struct t_hook *xmpp_hook_timer = NULL; struct t_gui_bar_item *xmpp_typing_bar_item = NULL; -void xmpp_lwsl_emit_weechat(int level, const char *line) +xmpp_ctx_t *xmpp_context = NULL; + +xmpp_conn_t *xmpp_connection = NULL; + +void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg) { - char buf[50]; - //lwsl_timestamp(level, buf, sizeof(buf)); + (void) userdata; + time_t date = time(NULL); + const char *timestamp = weechat_util_get_time_string(&date); weechat_printf( NULL, - _("%s%s: %s%s"), + _("%s%s %d | %s: %s - %s"), weechat_prefix("error"), XMPP_PLUGIN_NAME, - buf, line); + level, timestamp, area, msg); } +xmpp_log_t xmpp_logger = { + &xmpp_log_emit_weechat, + NULL +}; + int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { - (void) argc; - (void) argv; + (void) argc; + (void) argv; weechat_plugin = plugin; - //lws_set_log_level(LLL_ERR | LLL_WARN /*| LLL_NOTICE | LLL_INFO | LLL_DEBUG - // | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT - // | LLL_LATENCY | LLL_USER | LLL_COUNT*/, - // xmpp_lwsl_emit_weechat); + if (!xmpp_config_init()) + return WEECHAT_RC_ERROR; - //if (!xmpp_config_init()) - // return WEECHAT_RC_ERROR; + xmpp_config_read(); - //xmpp_config_read(); + xmpp_initialize(); + xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); + xmpp_connection = xmpp_conn_new(xmpp_context); + xmpp_conn_set_jid(xmpp_connection, + weechat_config_string(xmpp_config_serverdef_jid)); + xmpp_conn_set_pass(xmpp_connection, + weechat_config_string(xmpp_config_serverdef_password)); //xmpp_command_init(); @@ -87,7 +100,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) int weechat_plugin_end(struct t_weechat_plugin *plugin) { - /* make C compiler happy */ + // make C compiler happy (void) plugin; if (xmpp_typing_bar_item) @@ -96,11 +109,13 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) if (xmpp_hook_timer) weechat_unhook(xmpp_hook_timer); - //xmpp_config_write(); + xmpp_config_write(); + + xmpp_conn_release(xmpp_connection); - //xmpp_workspace_disconnect_all(); + xmpp_ctx_free(xmpp_context); - //xmpp_workspace_free_all(); + xmpp_shutdown(); return WEECHAT_RC_OK; } From 4acb753cae4dd3d22cfd7f2feb0296d02ed52ed6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 26 Jun 2021 15:17:00 +0100 Subject: [PATCH 071/118] basic connection --- Makefile | 1 + slack-api.c | 291 ---------------------------------------------- slack-api.h | 15 --- xmpp-connection.c | 146 +++++++++++++++++++++++ xmpp-connection.h | 19 +++ xmpp.c | 34 +----- 6 files changed, 168 insertions(+), 338 deletions(-) delete mode 100644 slack-api.c delete mode 100644 slack-api.h create mode 100644 xmpp-connection.c create mode 100644 xmpp-connection.h diff --git a/Makefile b/Makefile index 94bb22e..dcc399f 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ INSTALL ?= /usr/bin/install SRCS=xmpp.c \ xmpp-config.c \ + xmpp-connection.c \ OLDSRCS=slack.c \ slack-api.c \ diff --git a/slack-api.c b/slack-api.c deleted file mode 100644 index fc86b4a..0000000 --- a/slack-api.c +++ /dev/null @@ -1,291 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-api.h" -#include "api/slack-api-hello.h" -#include "api/slack-api-error.h" -#include "api/slack-api-message.h" -#include "api/slack-api-user-typing.h" - -struct stringcase -{ - const char *string; - int (*func)(struct t_slack_workspace *workspace, - json_object *message); -}; - -static struct stringcase cases[] = -{ { "hello", &slack_api_hello } -, { "error", &slack_api_error } -, { "message", &slack_api_message } -, { "user_typing", &slack_api_user_typing } -}; - -static int stringcase_cmp(const void *p1, const void *p2) -{ - return strcasecmp(((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string); -} - -void slack_api_init() -{ - size_t case_count = sizeof(cases) / sizeof(cases[0]); - qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); - - slack_api_message_init(); -} - -static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, - void *user, void* in, size_t len) -{ - struct t_slack_workspace *workspace = (struct t_slack_workspace *)user; - - (void) wsi; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - workspace->buffer, - _("%s%s: error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - in ? (char *)in : "(null)"); - workspace->client_wsi = NULL; - break; - - case LWS_CALLBACK_CLIENT_ESTABLISHED: - weechat_printf( - workspace->buffer, - _("%s%s: waiting for hello..."), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - break; - - /* data is never chunked */ - case LWS_CALLBACK_CLIENT_RECEIVE: - weechat_printf( - workspace->buffer, - _("%s%s: received data: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - (const char *)in); - { - int data_size; - char *json_string; - json_object *response, *type; - struct t_json_chunk *new_chunk, *last_chunk, *chunk_ptr; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc(((int)len) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (workspace->json_chunks) - { - for (last_chunk = workspace->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - workspace->json_chunks = new_chunk; - } - - data_size = 0; - for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next) - { - data_size += strlen(chunk_ptr->data); - } - - json_string = malloc(data_size + 1); - json_string[0] = '\0'; - - for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next) - { - strcat(json_string, chunk_ptr->data); - } - - response = json_tokener_parse(json_string); - if (response) - { - for (chunk_ptr = workspace->json_chunks; chunk_ptr; workspace->json_chunks = chunk_ptr) - { - chunk_ptr = chunk_ptr->next; - free(workspace->json_chunks->data); - free(workspace->json_chunks); - } - - type = json_object_object_get(response, "type"); - if (!type) - { - weechat_printf( - workspace->buffer, - _("%s%s: unexpected data received from websocket: closing"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - - slack_workspace_disconnect(workspace, 0); - - json_object_put(response); - free(json_string); - return -1; - } - - if (!slack_api_route_message(workspace, - json_object_get_string(type), response)) - { - weechat_printf( - workspace->buffer, - _("%s%s: error while handling message: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - json_string); - weechat_printf( - workspace->buffer, - _("%s%s: closing connection."), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - - slack_workspace_disconnect(workspace, 0); - - json_object_put(response); - free(json_string); - return -1; - } - - json_object_put(response); - free(json_string); - } - else - { - free(json_string); - } - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_CLIENT_WRITEABLE: - weechat_printf( - workspace->buffer, - _("%s%s: websocket is writeable"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - break; - - case LWS_CALLBACK_CLOSED: - workspace->client_wsi = NULL; - workspace->disconnected = 1; - /* start reconnect timer */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "default", - callback_ws, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -void slack_api_connect(struct t_slack_workspace *workspace) -{ - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - const char *url_protocol, *url_path; - char path[512]; - - memset(&ctxinfo, 0, sizeof(ctxinfo)); - memset(&ccinfo, 0, sizeof(ccinfo)); - - ccinfo.port = 443; - - if (lws_parse_uri(workspace->ws_url, - &url_protocol, &ccinfo.address, - &ccinfo.port, &url_path)) - { - weechat_printf( - workspace->buffer, - _("%s%s: error connecting to slack: bad websocket uri"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - - path[0] = '/'; - strncpy(path + 1, url_path, sizeof(path) - 2); - path[sizeof(path) - 1] = '\0'; - - ccinfo.path = path; - - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; - ctxinfo.protocols = protocols; - ctxinfo.uid = -1; - ctxinfo.gid = -1; - - workspace->context = lws_create_context(&ctxinfo); - if (!workspace->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: connecting to %s://%s:%d%s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - url_protocol, ccinfo.address, ccinfo.port, path); - } - - ccinfo.context = workspace->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.ietf_version_or_minus_one = -1; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &workspace->client_wsi; - ccinfo.userdata = workspace; - - lws_client_connect_via_info(&ccinfo); -} - -int slack_api_route_message(struct t_slack_workspace *workspace, - const char *type, json_object *message) -{ - struct stringcase key; - key.string = type; - - size_t case_count = sizeof(cases) / sizeof(cases[0]); - void *entry_ptr = bsearch(&key, cases, case_count, - sizeof(struct stringcase), stringcase_cmp); - - if (entry_ptr) - { - struct stringcase *entry = (struct stringcase *)entry_ptr; - return (*entry->func)(workspace, message); - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: got unhandled message of type: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - type); - return 1; - } -} diff --git a/slack-api.h b/slack-api.h deleted file mode 100644 index 723b3b9..0000000 --- a/slack-api.h +++ /dev/null @@ -1,15 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_H_ -#define _SLACK_API_H_ - -void slack_api_init(); - -void slack_api_connect(struct t_slack_workspace *workspace); - -int slack_api_route_message(struct t_slack_workspace *workspace, - const char *type, json_object *message); - -#endif /*SLACK_API_H*/ diff --git a/xmpp-connection.c b/xmpp-connection.c new file mode 100644 index 0000000..47152f1 --- /dev/null +++ b/xmpp-connection.c @@ -0,0 +1,146 @@ +// 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 + +#include "xmpp.h" +#include "xmpp-config.h" +#include "xmpp-connection.h" +//#include "api/xmpp-api-hello.h" +//#include "api/xmpp-api-error.h" +//#include "api/xmpp-api-message.h" +//#include "api/xmpp-api-user-typing.h" + +xmpp_ctx_t *xmpp_context = NULL; + +xmpp_conn_t *xmpp_connection = NULL; + +void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg) +{ + (void) userdata; + time_t date = time(NULL); + const char *timestamp = weechat_util_get_time_string(&date); + + weechat_printf( + NULL, + _("%s%s %d | %s: %s - %s"), + weechat_prefix("error"), XMPP_PLUGIN_NAME, + level, timestamp, area, msg); +} + +xmpp_log_t xmpp_logger = { + &xmpp_log_emit_weechat, + NULL +}; + +void xmpp_connection_init() +{ + + xmpp_initialize(); + xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); + xmpp_connection = xmpp_conn_new(xmpp_context); + xmpp_conn_set_jid(xmpp_connection, + weechat_config_string(xmpp_config_serverdef_jid)); + xmpp_conn_set_pass(xmpp_connection, + weechat_config_string(xmpp_config_serverdef_password)); + //size_t case_count = sizeof(cases) / sizeof(cases[0]); + //qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); + + //xmpp_api_message_init(); +} + +void xmpp_connection_connect(xmpp_conn_t *connection) +{ + //struct lws_context_creation_info ctxinfo; + //struct lws_client_connect_info ccinfo; + //const char *url_protocol, *url_path; + //char path[512]; + + //memset(&ctxinfo, 0, sizeof(ctxinfo)); + //memset(&ccinfo, 0, sizeof(ccinfo)); + + //ccinfo.port = 443; + + //if (lws_parse_uri(workspace->ws_url, + // &url_protocol, &ccinfo.address, + // &ccinfo.port, &url_path)) + //{ + // weechat_printf( + // workspace->buffer, + // _("%s%s: error connecting to xmpp: bad websocket uri"), + // weechat_prefix("error"), XMPP_PLUGIN_NAME); + // return; + //} + + //path[0] = '/'; + //strncpy(path + 1, url_path, sizeof(path) - 2); + //path[sizeof(path) - 1] = '\0'; + + //ccinfo.path = path; + + //ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + //ctxinfo.port = CONTEXT_PORT_NO_LISTEN; + //ctxinfo.protocols = protocols; + //ctxinfo.uid = -1; + //ctxinfo.gid = -1; + + //workspace->context = lws_create_context(&ctxinfo); + //if (!workspace->context) + //{ + // weechat_printf( + // workspace->buffer, + // _("%s%s: error connecting to xmpp: lws init failed"), + // weechat_prefix("error"), XMPP_PLUGIN_NAME); + // return; + //} + //else + //{ + // weechat_printf( + // workspace->buffer, + // _("%s%s: connecting to %s://%s:%d%s"), + // weechat_prefix("network"), XMPP_PLUGIN_NAME, + // url_protocol, ccinfo.address, ccinfo.port, path); + //} + + //ccinfo.context = workspace->context; + //ccinfo.ssl_connection = LCCSCF_USE_SSL; + //ccinfo.host = ccinfo.address; + //ccinfo.origin = ccinfo.address; + //ccinfo.ietf_version_or_minus_one = -1; + //ccinfo.protocol = protocols[0].name; + //ccinfo.pwsi = &workspace->client_wsi; + //ccinfo.userdata = workspace; + + //lws_client_connect_via_info(&ccinfo); +} + +int xmpp_connection_route_message(xmpp_conn_t *workspace, + const char *type, json_object *message) +{ + //struct stringcase key; + //key.string = type; + + //size_t case_count = sizeof(cases) / sizeof(cases[0]); + //void *entry_ptr = bsearch(&key, cases, case_count, + // sizeof(struct stringcase), stringcase_cmp); + + //if (entry_ptr) + //{ + // struct stringcase *entry = (struct stringcase *)entry_ptr; + // return (*entry->func)(workspace, message); + //} + //else + //{ + // weechat_printf( + // workspace->buffer, + // _("%s%s: got unhandled message of type: %s"), + // weechat_prefix("error"), XMPP_PLUGIN_NAME, + // type); + return 1; + //} +} diff --git a/xmpp-connection.h b/xmpp-connection.h new file mode 100644 index 0000000..f6e7979 --- /dev/null +++ b/xmpp-connection.h @@ -0,0 +1,19 @@ +// 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/. + +#ifndef _XMPP_CONNECTION_H_ +#define _XMPP_CONNECTION_H_ + +extern xmpp_ctx_t *xmpp_context; + +extern xmpp_conn_t *xmpp_connection; + +void xmpp_connection_init(); + +void xmpp_connection_connect(xmpp_conn_t *connection); + +int xmpp_connection_route_message(xmpp_conn_t *connection, + const char *type, json_object *message); + +#endif /*XMPP_CONNECTION_H*/ diff --git a/xmpp.c b/xmpp.c index 7e5974e..c489c66 100644 --- a/xmpp.c +++ b/xmpp.c @@ -11,9 +11,9 @@ #include "xmpp.h" #include "xmpp-config.h" +#include "xmpp-connection.h" //#include "slack-command.h" //#include "slack-workspace.h" -//#include "slack-api.h" //#include "slack-buffer.h" //#include "slack-completion.h" @@ -31,28 +31,6 @@ struct t_hook *xmpp_hook_timer = NULL; struct t_gui_bar_item *xmpp_typing_bar_item = NULL; -xmpp_ctx_t *xmpp_context = NULL; - -xmpp_conn_t *xmpp_connection = NULL; - -void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg) -{ - (void) userdata; - time_t date = time(NULL); - const char *timestamp = weechat_util_get_time_string(&date); - - weechat_printf( - NULL, - _("%s%s %d | %s: %s - %s"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, - level, timestamp, area, msg); -} - -xmpp_log_t xmpp_logger = { - &xmpp_log_emit_weechat, - NULL -}; - int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { (void) argc; @@ -65,18 +43,10 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) xmpp_config_read(); - xmpp_initialize(); - xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); - xmpp_connection = xmpp_conn_new(xmpp_context); - xmpp_conn_set_jid(xmpp_connection, - weechat_config_string(xmpp_config_serverdef_jid)); - xmpp_conn_set_pass(xmpp_connection, - weechat_config_string(xmpp_config_serverdef_password)); + xmpp_connection_init(); //xmpp_command_init(); - //xmpp_api_init(); - //xmpp_completion_init(); //xmpp_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, From e7a4dd34c97825cc332ee3aa7321f60842e53a61 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 27 Jun 2021 23:51:05 +0100 Subject: [PATCH 072/118] linkage shenanigans --- .envrc | 24 +-- .gitmodules | 3 - Makefile | 83 ++++---- libstrophe | 1 - slack-command.c => xmpp-command.c | 317 +++++++++++++++--------------- slack-command.h => xmpp-command.h | 8 +- xmpp-connection.c | 33 ++-- xmpp-connection.h | 6 +- xmpp.c | 33 +++- 9 files changed, 260 insertions(+), 248 deletions(-) delete mode 160000 libstrophe rename slack-command.c => xmpp-command.c (51%) rename slack-command.h => xmpp-command.h (65%) diff --git a/.envrc b/.envrc index 3381671..ec1a23e 100644 --- a/.envrc +++ b/.envrc @@ -34,27 +34,19 @@ use_guix() fi # Miscellaneous packages. - PACKAGES_MAINTENANCE=( - direnv - git - git:send-email - gnupg - guile-colorized - guile-readline - less - ncurses - openssh - xdot + ENVIRONMENTS=( + weechat ) # Environment packages. - PACKAGES=(help2man guile-sqlite3 guile-gcrypt - autoconf autoconf-archive automake libtool - make cmake gcc-toolchain pkg-config - libressl libxml2 libstrophe json-c weechat) + PACKAGES=( + autoconf autoconf-archive automake libtool + make cmake gcc-toolchain pkg-config patchelf + weechat xz libxml2 libstrophe json-c + ) # Thanks - eval "$(guix environment --search-paths --root="$gcroot" --ad-hoc ${PACKAGES[@]} ${PACKAGES_MAINTENANCE[@]} "$@")" + eval "$(guix environment --search-paths --root="$gcroot" ${ENVIRONMENTS[@]} --ad-hoc ${PACKAGES[@]} "$@")" export CC=gcc } diff --git a/.gitmodules b/.gitmodules index 1c84e5a..fc93d6e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "json-c"] path = json-c url = https://github.com/json-c/json-c -[submodule "libstrophe"] - path = libstrophe - url = https://github.com/strophe/libstrophe diff --git a/Makefile b/Makefile index dcc399f..3b28f64 100644 --- a/Makefile +++ b/Makefile @@ -4,67 +4,68 @@ ifdef DEBUG endif RM=rm -f FIND=find -CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -Ilibstrophe -Ijson-c +INCLUDES=-Ilibstrophe -Ijson-c +CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers $(INCLUDES) LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) -LDLIBS=-lssl -lxml2 +LDLIBS=-lstrophe -lpthread PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib INSTALL ?= /usr/bin/install SRCS=xmpp.c \ + xmpp-command.c \ xmpp-config.c \ xmpp-connection.c \ +DEPS=json-c/libjson-c.a OLDSRCS=slack.c \ - slack-api.c \ - slack-buffer.c \ - slack-channel.c \ - slack-config.c \ - slack-command.c \ - slack-completion.c \ - slack-emoji.c \ - slack-input.c \ - slack-message.c \ - slack-oauth.c \ - slack-request.c \ - slack-teaminfo.c \ - slack-user.c \ - slack-workspace.c \ - api/slack-api-hello.c \ - api/slack-api-error.c \ - api/slack-api-message.c \ - api/slack-api-user-typing.c \ - api/message/slack-api-message-bot-message.c \ - api/message/slack-api-message-slackbot-response.c \ - api/message/slack-api-message-me-message.c \ - api/message/slack-api-message-unimplemented.c \ - request/slack-request-chat-memessage.c \ - request/slack-request-chat-postmessage.c \ - request/slack-request-channels-list.c \ - request/slack-request-conversations-members.c \ - request/slack-request-emoji-list.c \ - request/slack-request-users-list.c -OBJS=$(subst .c,.o,$(SRCS)) libstrophe/.libs/libstrophe.a json-c/libjson-c.a - -all: libstrophe/.libs/libstrophe.a json-c/libjson-c.a weechat-xmpp + slack-api.c \ + slack-buffer.c \ + slack-channel.c \ + slack-config.c \ + slack-command.c \ + slack-completion.c \ + slack-emoji.c \ + slack-input.c \ + slack-message.c \ + slack-oauth.c \ + slack-request.c \ + slack-teaminfo.c \ + slack-user.c \ + slack-workspace.c \ + api/slack-api-hello.c \ + api/slack-api-error.c \ + api/slack-api-message.c \ + api/slack-api-user-typing.c \ + api/message/slack-api-message-bot-message.c \ + api/message/slack-api-message-slackbot-response.c \ + api/message/slack-api-message-me-message.c \ + api/message/slack-api-message-unimplemented.c \ + request/slack-request-chat-memessage.c \ + request/slack-request-chat-postmessage.c \ + request/slack-request-channels-list.c \ + request/slack-request-conversations-members.c \ + request/slack-request-emoji-list.c \ + request/slack-request-users-list.c +OBJS=$(subst .c,.o,$(SRCS)) + +all: $(DEPS) weechat-xmpp weechat-xmpp: $(OBJS) $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(LDLIBS) - -libstrophe/.libs/libstrophe.a: - cd libstrophe && ./bootstrap.sh && env CFLAGS=-fPIC LDFLAGS= ./configure - $(MAKE) -C libstrophe -libstrophe: libstrophe/.libs/libstrophe.a + which patchelf >/dev/null && \ + patchelf --set-rpath $(LIBRARY_PATH):$(shell patchelf --print-rpath xmpp.so) xmpp.so || true json-c/libjson-c.a: - cd json-c && env CFLAGS= LDFLAGS= cmake -DCMAKE_C_FLAGS=-fPIC . + cd json-c && env CFLAGS= LDFLAGS= \ + cmake -DCMAKE_C_FLAGS=-fPIC . $(MAKE) -C json-c json-c-static json-c: json-c/libjson-c.a depend: .depend -.depend: libstrophe/.libs/libstrophe.a json-c/libjson-c.a $(SRCS) +.depend: json-c/libjson-c.a $(SRCS) $(RM) ./.depend $(CC) $(CFLAGS) -MM $^>>./.depend @@ -73,8 +74,6 @@ tidy: clean: $(RM) $(OBJS) - $(MAKE) -C libstrophe clean || true - $(MAKE) -C libwebsockets clean || true $(MAKE) -C json-c clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true diff --git a/libstrophe b/libstrophe deleted file mode 160000 index 2d5424b..0000000 --- a/libstrophe +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2d5424bcff4e9d810b73444b02708f69743ff65d diff --git a/slack-command.c b/xmpp-command.c similarity index 51% rename from slack-command.c rename to xmpp-command.c index 201ff4d..44ae73c 100644 --- a/slack-command.c +++ b/xmpp-command.c @@ -2,32 +2,33 @@ // 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-oauth.h" -#include "slack-teaminfo.h" -#include "slack-workspace.h" -#include "slack-channel.h" -#include "slack-buffer.h" -#include "slack-message.h" -#include "slack-command.h" -#include "request/slack-request-chat-memessage.h" - -void slack_command_display_workspace(struct t_slack_workspace *workspace) +#include + +#include "xmpp.h" +//#include "xmpp-oauth.h" +//#include "xmpp-teaminfo.h" +//#include "xmpp-workspace.h" +//#include "xmpp-channel.h" +//#include "xmpp-buffer.h" +//#include "xmpp-message.h" +#include "xmpp-command.h" +//#include "request/xmpp-request-chat-memessage.h" + +/* +void xmpp_command_display_workspace(xmpp_conn_t *workspace) { int num_channels, num_pv; if (workspace->is_connected) { - num_channels = 0;//slack_workspace_get_channel_count(workspace); - num_pv = 0;//slack_workspace_get_pv_count(workspace); + num_channels = 0;//xmpp_workspace_get_channel_count(workspace); + num_pv = 0;//xmpp_workspace_get_pv_count(workspace); weechat_printf( NULL, - " %s %s%s%s.slack.com %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv", + " %s %s%s%s.xmpp.com %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv", (workspace->is_connected) ? "*" : " ", weechat_color("chat_server"), workspace->domain, @@ -50,7 +51,7 @@ void slack_command_display_workspace(struct t_slack_workspace *workspace) { weechat_printf( NULL, - " %s%s%s.slack.com %s(%s%s%s)%s", + " %s%s%s.xmpp.com %s(%s%s%s)%s", weechat_color("chat_server"), workspace->domain, weechat_color("reset"), @@ -63,10 +64,10 @@ void slack_command_display_workspace(struct t_slack_workspace *workspace) } } -void slack_command_workspace_list(int argc, char **argv) +void xmpp_command_workspace_list(int argc, char **argv) { int i, one_workspace_found; - struct t_slack_workspace *ptr_workspace2; + xmpp_conn_t *ptr_workspace2; char *workspace_name = NULL; for (i = 2; i < argc; i++) @@ -76,14 +77,14 @@ void slack_command_workspace_list(int argc, char **argv) } if (!workspace_name) { - if (slack_workspaces) + if (xmpp_workspaces) { weechat_printf(NULL, ""); weechat_printf(NULL, _("All workspaces:")); - for (ptr_workspace2 = slack_workspaces; ptr_workspace2; + for (ptr_workspace2 = xmpp_workspaces; ptr_workspace2; ptr_workspace2 = ptr_workspace2->next_workspace) { - slack_command_display_workspace(ptr_workspace2); + xmpp_command_display_workspace(ptr_workspace2); } } else @@ -92,7 +93,7 @@ void slack_command_workspace_list(int argc, char **argv) else { one_workspace_found = 0; - for (ptr_workspace2 = slack_workspaces; ptr_workspace2; + for (ptr_workspace2 = xmpp_workspaces; ptr_workspace2; ptr_workspace2 = ptr_workspace2->next_workspace) { if (weechat_strcasestr(ptr_workspace2->name, workspace_name)) @@ -105,7 +106,7 @@ void slack_command_workspace_list(int argc, char **argv) workspace_name); } one_workspace_found = 1; - slack_command_display_workspace(ptr_workspace2); + xmpp_command_display_workspace(ptr_workspace2); } } if (!one_workspace_found) @@ -115,40 +116,40 @@ void slack_command_workspace_list(int argc, char **argv) } } -void slack_command_add_workspace(struct t_slack_teaminfo *slack_teaminfo) +void xmpp_command_add_workspace(struct t_xmpp_teaminfo *xmpp_teaminfo) { - struct t_slack_workspace *workspace; + xmpp_conn_t *workspace; - workspace = slack_workspace_casesearch(slack_teaminfo->domain); + workspace = xmpp_workspace_casesearch(xmpp_teaminfo->domain); if (workspace) { weechat_printf( NULL, _("%s%s: workspace \"%s\" already exists, can't add it!"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - slack_teaminfo->domain); + weechat_prefix("error"), XMPP_PLUGIN_NAME, + xmpp_teaminfo->domain); return; } - workspace = slack_workspace_alloc(slack_teaminfo->domain); + workspace = xmpp_workspace_alloc(xmpp_teaminfo->domain); if (!workspace) { weechat_printf( NULL, _("%s%s: unable to add workspace"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); + weechat_prefix("error"), XMPP_PLUGIN_NAME); return; } - workspace->id = strdup(slack_teaminfo->id); - workspace->name = strdup(slack_teaminfo->name); - weechat_config_option_set(workspace->options[SLACK_WORKSPACE_OPTION_TOKEN], - slack_teaminfo->token, 1); + workspace->id = strdup(xmpp_teaminfo->id); + workspace->name = strdup(xmpp_teaminfo->name); + weechat_config_option_set(workspace->options[XMPP_WORKSPACE_OPTION_TOKEN], + xmpp_teaminfo->token, 1); weechat_printf ( NULL, - _("%s: workspace %s%s%s.slack.com %s(%s%s%s)%s added"), - SLACK_PLUGIN_NAME, + _("%s: workspace %s%s%s.xmpp.com %s(%s%s%s)%s added"), + XMPP_PLUGIN_NAME, weechat_color("chat_server"), workspace->domain, weechat_color("reset"), @@ -158,47 +159,47 @@ void slack_command_add_workspace(struct t_slack_teaminfo *slack_teaminfo) weechat_color("chat_delimiters"), weechat_color("reset")); - free_teaminfo(slack_teaminfo); + free_teaminfo(xmpp_teaminfo); } -void slack_command_fetch_workspace(char *token) +void xmpp_command_fetch_workspace(char *token) { - slack_teaminfo_fetch(token, &slack_command_add_workspace); + xmpp_teaminfo_fetch(token, &xmpp_command_add_workspace); free(token); } -void slack_command_workspace_register(int argc, char **argv) +void xmpp_command_workspace_register(int argc, char **argv) { char *code; if (argc > 2) { code = argv[2]; - + if (strncmp("xoxp", code, 4) == 0) { - slack_command_fetch_workspace(strdup(code)); + xmpp_command_fetch_workspace(strdup(code)); } else { - slack_oauth_request_token(code, &slack_command_fetch_workspace); + xmpp_oauth_request_token(code, &xmpp_command_fetch_workspace); } } else { weechat_printf(NULL, - _("\n#### Retrieving a Slack token via OAUTH ####\n" - "1) Paste this into a browser: https://slack.com/oauth/authorize?client_id=%s&scope=client\n" + _("\n#### Retrieving a Xmpp token via OAUTH ####\n" + "1) Paste this into a browser: https://xmpp.com/oauth/authorize?client_id=%s&scope=client\n" "2) Select the team you wish to access from weechat in your browser.\n" "3) Click \"Authorize\" in the browser **IMPORTANT: the redirect will fail, this is expected**\n" "4) Copy the \"code\" portion of the URL to your clipboard\n" - "5) Return to weechat and run `/slack register [code]`\n"), - SLACK_CLIENT_ID); + "5) Return to weechat and run `/xmpp register [code]`\n"), + XMPP_CLIENT_ID); } } -int slack_command_connect_workspace(struct t_slack_workspace *workspace) +int xmpp_command_connect_workspace(xmpp_conn_t *workspace) { if (!workspace) return 0; @@ -208,19 +209,19 @@ int slack_command_connect_workspace(struct t_slack_workspace *workspace) weechat_printf( NULL, _("%s%s: already connected to workspace \"%s\"!"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + weechat_prefix("error"), XMPP_PLUGIN_NAME, workspace->domain); } - slack_workspace_connect(workspace); + xmpp_workspace_connect(workspace); return 1; } -int slack_command_workspace_connect(int argc, char **argv) +int xmpp_command_workspace_connect(int argc, char **argv) { int i, nb_connect, connect_ok; - struct t_slack_workspace *ptr_workspace; + xmpp_conn_t *ptr_workspace; (void) argc; (void) argv; @@ -231,10 +232,10 @@ int slack_command_workspace_connect(int argc, char **argv) for (i = 2; i < argc; i++) { nb_connect++; - ptr_workspace = slack_workspace_search(argv[i]); + ptr_workspace = xmpp_workspace_search(argv[i]); if (ptr_workspace) { - if (!slack_command_connect_workspace(ptr_workspace)) + if (!xmpp_command_connect_workspace(ptr_workspace)) { connect_ok = 0; } @@ -244,8 +245,8 @@ int slack_command_workspace_connect(int argc, char **argv) weechat_printf( NULL, _("%s%s: workspace not found \"%s\" " - "(register first with: /slack register)"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + "(register first with: /xmpp register)"), + weechat_prefix("error"), XMPP_PLUGIN_NAME, argv[i]); } } @@ -253,9 +254,9 @@ int slack_command_workspace_connect(int argc, char **argv) return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; } -void slack_command_workspace_delete(int argc, char **argv) +void xmpp_command_workspace_delete(int argc, char **argv) { - struct t_slack_workspace *workspace; + xmpp_conn_t *workspace; char *workspace_domain; if (argc < 3) @@ -269,14 +270,14 @@ void slack_command_workspace_delete(int argc, char **argv) return; } - workspace = slack_workspace_search(argv[2]); + workspace = xmpp_workspace_search(argv[2]); if (!workspace) { weechat_printf( NULL, _("%s%s: workspace \"%s\" not found for \"%s\" command"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - argv[2], "slack delete"); + weechat_prefix("error"), XMPP_PLUGIN_NAME, + argv[2], "xmpp delete"); return; } if (workspace->is_connected) @@ -284,151 +285,151 @@ void slack_command_workspace_delete(int argc, char **argv) weechat_printf( NULL, _("%s%s: you cannot delete workspace \"%s\" because you" - "are connected. Try \"/slack disconnect %s\" first."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, + "are connected. Try \"/xmpp disconnect %s\" first."), + weechat_prefix("error"), XMPP_PLUGIN_NAME, argv[2], argv[2]); return; } workspace_domain = strdup(workspace->domain); - slack_workspace_free(workspace); + xmpp_workspace_free(workspace); weechat_printf ( NULL, _("%s: workspace %s%s%s has been deleted"), - SLACK_PLUGIN_NAME, + XMPP_PLUGIN_NAME, weechat_color("chat_server"), (workspace_domain) ? workspace_domain : "???", weechat_color("reset")); if (workspace_domain) free(workspace_domain); } +*/ -int slack_command_slack(const void *pointer, void *data, +int xmpp_command_xmpp(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - + (void) pointer; (void) data; (void) buffer; - if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) - { - slack_command_workspace_list(argc, argv); - return WEECHAT_RC_OK; - } - - if (argc > 1) - { - if (weechat_strcasecmp(argv[1], "register") == 0) - { - slack_command_workspace_register(argc, argv); - return WEECHAT_RC_OK; - } - - if (weechat_strcasecmp(argv[1], "connect") == 0) - { - slack_command_workspace_connect(argc, argv); - return WEECHAT_RC_OK; - } - - if (weechat_strcasecmp(argv[1], "delete") == 0) - { - slack_command_workspace_delete(argc, argv); - return WEECHAT_RC_OK; - } - - WEECHAT_COMMAND_ERROR; - } + //if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) + //{ + // xmpp_command_workspace_list(argc, argv); + // return WEECHAT_RC_OK; + //} + + //if (argc > 1) + //{ + // if (weechat_strcasecmp(argv[1], "register") == 0) + // { + // xmpp_command_workspace_register(argc, argv); + // return WEECHAT_RC_OK; + // } + + // if (weechat_strcasecmp(argv[1], "connect") == 0) + // { + // xmpp_command_workspace_connect(argc, argv); + // return WEECHAT_RC_OK; + // } + + // if (weechat_strcasecmp(argv[1], "delete") == 0) + // { + // xmpp_command_workspace_delete(argc, argv); + // return WEECHAT_RC_OK; + // } + + // WEECHAT_COMMAND_ERROR; + //} return WEECHAT_RC_OK; } -int slack_command_me(const void *pointer, void *data, +int xmpp_command_me(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_slack_workspace *ptr_workspace = NULL; - struct t_slack_channel *ptr_channel = NULL; - struct t_slack_request *request; + xmpp_conn_t *ptr_workspace = NULL; + //struct t_xmpp_channel *ptr_channel = NULL; + //struct t_xmpp_request *request; char *text; - - + (void) pointer; (void) data; (void) buffer; (void) argv; - slack_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel); - - if (!ptr_workspace) - return WEECHAT_RC_ERROR; - - if (!ptr_channel) - { - weechat_printf ( - ptr_workspace->buffer, - _("%s%s: \"%s\" command can not be executed on a workspace buffer"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, "me"); - return WEECHAT_RC_OK; - } - - if (!ptr_workspace->is_connected) - { - weechat_printf(buffer, - _("%s%s: you are not connected to server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return WEECHAT_RC_OK; - } - - if (argc > 1) - { - text = malloc(SLACK_MESSAGE_MAX_LENGTH); - if (!text) - { - weechat_printf(buffer, - _("%s%s: error allocating string"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return WEECHAT_RC_ERROR; - } - lws_urlencode(text, argv_eol[1], SLACK_MESSAGE_MAX_LENGTH); - - request = slack_request_chat_memessage(ptr_workspace, - weechat_config_string( - ptr_workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - ptr_channel->id, text); - if (request) - slack_workspace_register_request(ptr_workspace, request); - - free(text); - } + //xmpp_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel); + + //if (!ptr_workspace) + // return WEECHAT_RC_ERROR; + + //if (!ptr_channel) + //{ + // weechat_printf ( + // ptr_workspace->buffer, + // _("%s%s: \"%s\" command can not be executed on a workspace buffer"), + // weechat_prefix("error"), XMPP_PLUGIN_NAME, "me"); + // return WEECHAT_RC_OK; + //} + + //if (!ptr_workspace->is_connected) + //{ + // weechat_printf(buffer, + // _("%s%s: you are not connected to server"), + // weechat_prefix("error"), XMPP_PLUGIN_NAME); + // return WEECHAT_RC_OK; + //} + + //if (argc > 1) + //{ + // text = malloc(XMPP_MESSAGE_MAX_LENGTH); + // if (!text) + // { + // weechat_printf(buffer, + // _("%s%s: error allocating string"), + // weechat_prefix("error"), XMPP_PLUGIN_NAME); + // return WEECHAT_RC_ERROR; + // } + // lws_urlencode(text, argv_eol[1], XMPP_MESSAGE_MAX_LENGTH); + + // request = xmpp_request_chat_memessage(ptr_workspace, + // weechat_config_string( + // ptr_workspace->options[XMPP_WORKSPACE_OPTION_TOKEN]), + // ptr_channel->id, text); + // if (request) + // xmpp_workspace_register_request(ptr_workspace, request); + + // free(text); + //} return WEECHAT_RC_OK; } -void slack_command_init() +void xmpp_command_init() { weechat_hook_command( - "slack", - N_("slack control"), + "xmpp", + N_("xmpp control"), N_("list" " || register [token]" " || connect " " || delete "), N_(" list: list workspaces\n" - "register: add a slack workspace\n" - " connect: connect to a slack workspace\n" - " delete: delete a slack workspace\n"), + "register: add a xmpp workspace\n" + " connect: connect to a xmpp workspace\n" + " delete: delete a xmpp workspace\n"), "list" - " || register %(slack_token)" - " || connect %(slack_workspace)" - " || delete %(slack_workspace)", - &slack_command_slack, NULL, NULL); + " || register %(xmpp_token)" + " || connect %(xmpp_workspace)" + " || delete %(xmpp_workspace)", + &xmpp_command_xmpp, NULL, NULL); weechat_hook_command( "me", - N_("send a slack action to the current channel"), + N_("send a xmpp action to the current channel"), N_(""), N_("message: message to send"), - NULL, &slack_command_me, NULL, NULL); + NULL, &xmpp_command_me, NULL, NULL); } diff --git a/slack-command.h b/xmpp-command.h similarity index 65% rename from slack-command.h rename to xmpp-command.h index 9d27194..62be0e5 100644 --- a/slack-command.h +++ b/xmpp-command.h @@ -2,9 +2,9 @@ // 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/. -#ifndef _SLACK_COMMAND_H_ -#define _SLACK_COMMAND_H_ +#ifndef _XMPP_COMMAND_H_ +#define _XMPP_COMMAND_H_ -extern void slack_command_init(); +extern void xmpp_command_init(); -#endif /*SLACK_COMMAND_H*/ +#endif /*XMPP_COMMAND_H*/ diff --git a/xmpp-connection.c b/xmpp-connection.c index 47152f1..993996d 100644 --- a/xmpp-connection.c +++ b/xmpp-connection.c @@ -16,13 +16,12 @@ //#include "api/xmpp-api-message.h" //#include "api/xmpp-api-user-typing.h" -xmpp_ctx_t *xmpp_context = NULL; - -xmpp_conn_t *xmpp_connection = NULL; +xmpp_conn_t *xmpp_connection; void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg) { (void) userdata; + time_t date = time(NULL); const char *timestamp = weechat_util_get_time_string(&date); @@ -40,22 +39,27 @@ xmpp_log_t xmpp_logger = { void xmpp_connection_init() { - xmpp_initialize(); - xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); - xmpp_connection = xmpp_conn_new(xmpp_context); - xmpp_conn_set_jid(xmpp_connection, - weechat_config_string(xmpp_config_serverdef_jid)); - xmpp_conn_set_pass(xmpp_connection, - weechat_config_string(xmpp_config_serverdef_password)); - //size_t case_count = sizeof(cases) / sizeof(cases[0]); - //qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); +} - //xmpp_api_message_init(); +void xmpp_connection_autoconnect() +{ + xmpp_connection_connect(weechat_config_string(xmpp_config_serverdef_jid), + weechat_config_string(xmpp_config_serverdef_password)); + weechat_printf(NULL, _("xmpp: %s # %s"), + weechat_config_string(xmpp_config_serverdef_jid), + weechat_config_string(xmpp_config_serverdef_password)); } -void xmpp_connection_connect(xmpp_conn_t *connection) +void xmpp_connection_connect(const char* jid, const char* password) { + xmpp_ctx_t *xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); + + xmpp_conn_t *xmpp_connection = xmpp_conn_new(xmpp_context); + + xmpp_connection = xmpp_conn_new(xmpp_context); + xmpp_conn_set_jid(xmpp_connection, jid); + xmpp_conn_set_pass(xmpp_connection, password); //struct lws_context_creation_info ctxinfo; //struct lws_client_connect_info ccinfo; //const char *url_protocol, *url_path; @@ -117,6 +121,7 @@ void xmpp_connection_connect(xmpp_conn_t *connection) //ccinfo.userdata = workspace; //lws_client_connect_via_info(&ccinfo); + return xmpp_connection; } int xmpp_connection_route_message(xmpp_conn_t *workspace, diff --git a/xmpp-connection.h b/xmpp-connection.h index f6e7979..339b6db 100644 --- a/xmpp-connection.h +++ b/xmpp-connection.h @@ -5,13 +5,13 @@ #ifndef _XMPP_CONNECTION_H_ #define _XMPP_CONNECTION_H_ -extern xmpp_ctx_t *xmpp_context; - extern xmpp_conn_t *xmpp_connection; void xmpp_connection_init(); -void xmpp_connection_connect(xmpp_conn_t *connection); +void xmpp_connection_autoconnect(); + +void xmpp_connection_connect(const char* jid, const char* password); int xmpp_connection_route_message(xmpp_conn_t *connection, const char *type, json_object *message); diff --git a/xmpp.c b/xmpp.c index c489c66..788f573 100644 --- a/xmpp.c +++ b/xmpp.c @@ -12,10 +12,10 @@ #include "xmpp.h" #include "xmpp-config.h" #include "xmpp-connection.h" -//#include "slack-command.h" -//#include "slack-workspace.h" -//#include "slack-buffer.h" -//#include "slack-completion.h" +#include "xmpp-command.h" +//#include "xmpp-workspace.h" +//#include "xmpp-buffer.h" +//#include "xmpp-completion.h" WEECHAT_PLUGIN_NAME(XMPP_PLUGIN_NAME); @@ -31,6 +31,15 @@ struct t_hook *xmpp_hook_timer = NULL; struct t_gui_bar_item *xmpp_typing_bar_item = NULL; +/* +void connection_check_events(void) +{ + conn.xmpp_in_event_loop = TRUE; + xmpp_run_once(conn.xmpp_ctx, 10); + conn.xmpp_in_event_loop = FALSE; +} +*/ + int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { (void) argc; @@ -45,7 +54,9 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) xmpp_connection_init(); - //xmpp_command_init(); + xmpp_command_init(); + + xmpp_connection_autoconnect(); //xmpp_completion_init(); @@ -81,9 +92,17 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) xmpp_config_write(); - xmpp_conn_release(xmpp_connection); + if (xmpp_connection) + { + xmpp_ctx_t *xmpp_context = xmpp_conn_get_context(xmpp_connection); + + if (xmpp_conn_is_connected(xmpp_connection)) + xmpp_disconnect(xmpp_connection); - xmpp_ctx_free(xmpp_context); + xmpp_conn_release(xmpp_connection); + + xmpp_ctx_free(xmpp_context); + } xmpp_shutdown(); From ae0ada316eebd358616786498e852906c1bbe2ba Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 28 Jun 2021 02:00:49 +0100 Subject: [PATCH 073/118] basic function --- xmpp-config.c | 24 ++----- xmpp-config.h | 4 +- xmpp-connection.c | 159 ++++++++++++++++++++++++++++++++++++++++++---- xmpp-connection.h | 4 +- xmpp.c | 21 ++---- 5 files changed, 166 insertions(+), 46 deletions(-) diff --git a/xmpp-config.c b/xmpp-config.c index 5783fdf..2169e49 100644 --- a/xmpp-config.c +++ b/xmpp-config.c @@ -15,8 +15,8 @@ struct t_config_file *xmpp_config_file; //struct t_config_section *xmpp_config_section_workspace_default; //struct t_config_section *xmpp_config_section_workspace; -struct t_config_option *xmpp_config_serverdef_jid; -struct t_config_option *xmpp_config_serverdef_password; +struct t_config_option *xmpp_config_server_jid; +struct t_config_option *xmpp_config_server_password; struct t_config_option *xmpp_config_look_nick_completion_smart; /* @@ -238,7 +238,6 @@ int xmpp_config_reload (const void *pointer, void *data, int xmpp_config_init() { - struct t_config_section *ptr_section_serverdef; struct t_config_section *ptr_section_server; struct t_config_section *ptr_section_look; @@ -248,15 +247,6 @@ int xmpp_config_init() if(!xmpp_config_file) return 0; - ptr_section_serverdef = weechat_config_new_section( - xmpp_config_file, "server_default", - 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - ptr_section_server = weechat_config_new_section( xmpp_config_file, "server", 0, 0, @@ -275,7 +265,7 @@ int xmpp_config_init() NULL, NULL, NULL, NULL, NULL, NULL); - if (!ptr_section_serverdef + if (!ptr_section_server || !ptr_section_server || !ptr_section_look) { @@ -284,15 +274,15 @@ int xmpp_config_init() return 0; } - xmpp_config_serverdef_jid = weechat_config_new_option ( - xmpp_config_file, ptr_section_serverdef, + xmpp_config_server_jid = weechat_config_new_option ( + xmpp_config_file, ptr_section_server, "jid", "string", N_("XMPP Server JID"), NULL, 0, 0, "", "", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - xmpp_config_serverdef_password = weechat_config_new_option ( - xmpp_config_file, ptr_section_serverdef, + xmpp_config_server_password = weechat_config_new_option ( + xmpp_config_file, ptr_section_server, "password", "string", N_("XMPP Server Password"), NULL, 0, 0, "", "", 0, diff --git a/xmpp-config.h b/xmpp-config.h index c514960..128d8a4 100644 --- a/xmpp-config.h +++ b/xmpp-config.h @@ -19,8 +19,8 @@ extern struct t_config_file *xmpp_config_file; //extern struct t_config_section *xmpp_config_section_workspace_default; //extern struct t_config_section *xmpp_config_section_workspace; -extern struct t_config_option *xmpp_config_serverdef_jid; -extern struct t_config_option *xmpp_config_serverdef_password; +extern struct t_config_option *xmpp_config_server_jid; +extern struct t_config_option *xmpp_config_server_password; extern struct t_config_option *xmpp_config_look_nick_completion_smart; //extern struct t_config_option *xmpp_config_workspace_default[]; diff --git a/xmpp-connection.c b/xmpp-connection.c index 993996d..1fdc6d6 100644 --- a/xmpp-connection.c +++ b/xmpp-connection.c @@ -22,14 +22,16 @@ void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, c { (void) userdata; + static const char *log_level_name[4] = {"debug", "info", "warn", "error"}; + time_t date = time(NULL); const char *timestamp = weechat_util_get_time_string(&date); weechat_printf( NULL, - _("%s%s %d | %s: %s - %s"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, - level, timestamp, area, msg); + _("%s%s/%s (%s): %s"), + weechat_prefix("error"), XMPP_PLUGIN_NAME, area, + log_level_name[level], msg); } xmpp_log_t xmpp_logger = { @@ -42,24 +44,142 @@ void xmpp_connection_init() xmpp_initialize(); } -void xmpp_connection_autoconnect() +int xmpp_connection_autoconnect(const void *pointer, void *data, int remaining_calls) +{ + xmpp_connection_connect(weechat_config_string(xmpp_config_server_jid), + weechat_config_string(xmpp_config_server_password)); + + return WEECHAT_RC_OK; +} + +int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +{ + xmpp_stanza_t *reply, *query, *name, *version, *text; + const char *ns; + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + + weechat_printf(NULL, "Received version request from %s", xmpp_stanza_get_from(stanza)); + + reply = xmpp_stanza_reply(stanza); + xmpp_stanza_set_type(reply, "result"); + + query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, "query"); + ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)); + if (ns) { + xmpp_stanza_set_ns(query, ns); + } + + name = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(name, "name"); + xmpp_stanza_add_child(query, name); + xmpp_stanza_release(name); + + text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text, "libstrophe example bot"); + xmpp_stanza_add_child(name, text); + xmpp_stanza_release(text); + + version = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(version, "version"); + xmpp_stanza_add_child(query, version); + xmpp_stanza_release(version); + + text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text, "1.0"); + xmpp_stanza_add_child(version, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(reply, query); + xmpp_stanza_release(query); + + xmpp_send(conn, reply); + xmpp_stanza_release(reply); + return 1; +} + +int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +{ + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + xmpp_stanza_t *body, *reply; + const char *type; + char *intext, *replytext; + int quit = 0; + + body = xmpp_stanza_get_child_by_name(stanza, "body"); + if (body == NULL) + return 1; + type = xmpp_stanza_get_type(stanza); + if (type != NULL && strcmp(type, "error") == 0) + return 1; + + intext = xmpp_stanza_get_text(body); + + weechat_printf(NULL, "Incoming message from %s: %s", xmpp_stanza_get_from(stanza), + intext); + + reply = xmpp_stanza_reply(stanza); + if (xmpp_stanza_get_type(reply) == NULL) + xmpp_stanza_set_type(reply, "chat"); + + if (strcmp(intext, "quit") == 0) { + replytext = strdup("bye!"); + quit = 1; + } else { + replytext = (char *)malloc(strlen(" to you too!") + strlen(intext) + 1); + strcpy(replytext, intext); + strcat(replytext, " to you too!"); + } + xmpp_free(ctx, intext); + xmpp_message_set_body(reply, replytext); + + xmpp_send(conn, reply); + xmpp_stanza_release(reply); + free(replytext); + + if (quit) + xmpp_disconnect(conn); + + return 1; +} + +void xmpp_connection_on_connected(xmpp_conn_t *conn, xmpp_conn_event_t status, + int error, xmpp_stream_error_t *stream_error, + void *userdata) { - xmpp_connection_connect(weechat_config_string(xmpp_config_serverdef_jid), - weechat_config_string(xmpp_config_serverdef_password)); - weechat_printf(NULL, _("xmpp: %s # %s"), - weechat_config_string(xmpp_config_serverdef_jid), - weechat_config_string(xmpp_config_serverdef_password)); + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + + (void)error; + (void)stream_error; + + if (status == XMPP_CONN_CONNECT) { + xmpp_stanza_t *pres; + weechat_printf(NULL, "DEBUG: connected"); + xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, + ctx); + xmpp_handler_add(conn, message_handler, NULL, "message", NULL, ctx); + + /* Send initial so that we appear online to contacts */ + pres = xmpp_presence_new(ctx); + xmpp_send(conn, pres); + xmpp_stanza_release(pres); + } else { + weechat_printf(NULL, "DEBUG: disconnected"); + xmpp_stop(ctx); + } } void xmpp_connection_connect(const char* jid, const char* password) { xmpp_ctx_t *xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); - xmpp_conn_t *xmpp_connection = xmpp_conn_new(xmpp_context); - xmpp_connection = xmpp_conn_new(xmpp_context); xmpp_conn_set_jid(xmpp_connection, jid); xmpp_conn_set_pass(xmpp_connection, password); + auto flags = xmpp_conn_get_flags(xmpp_connection); + //flags |= XMPP_CONN_FLAG_TRUST_TLS; + xmpp_conn_set_flags(xmpp_connection, flags); + xmpp_connect_client(xmpp_connection, NULL, 0, xmpp_connection_on_connected, xmpp_context); //struct lws_context_creation_info ctxinfo; //struct lws_client_connect_info ccinfo; //const char *url_protocol, *url_path; @@ -121,7 +241,22 @@ void xmpp_connection_connect(const char* jid, const char* password) //ccinfo.userdata = workspace; //lws_client_connect_via_info(&ccinfo); - return xmpp_connection; +} + +int xmpp_connection_check_events(const void *pointer, void *data, int remaining_calls) +{ + (void) pointer; + (void) data; + (void) remaining_calls; + + if (xmpp_connection) + { + xmpp_ctx_t *xmpp_context = xmpp_conn_get_context(xmpp_connection); + + xmpp_run_once(xmpp_context, 10); + } + + return WEECHAT_RC_OK; } int xmpp_connection_route_message(xmpp_conn_t *workspace, diff --git a/xmpp-connection.h b/xmpp-connection.h index 339b6db..9d323fb 100644 --- a/xmpp-connection.h +++ b/xmpp-connection.h @@ -9,10 +9,12 @@ extern xmpp_conn_t *xmpp_connection; void xmpp_connection_init(); -void xmpp_connection_autoconnect(); +int xmpp_connection_autoconnect(const void *pointer, void *data, int remaining_calls); void xmpp_connection_connect(const char* jid, const char* password); +int xmpp_connection_check_events(const void *pointer, void *data, int remaining_calls); + int xmpp_connection_route_message(xmpp_conn_t *connection, const char *type, json_object *message); diff --git a/xmpp.c b/xmpp.c index 788f573..6138be1 100644 --- a/xmpp.c +++ b/xmpp.c @@ -31,15 +31,6 @@ struct t_hook *xmpp_hook_timer = NULL; struct t_gui_bar_item *xmpp_typing_bar_item = NULL; -/* -void connection_check_events(void) -{ - conn.xmpp_in_event_loop = TRUE; - xmpp_run_once(conn.xmpp_ctx, 10); - conn.xmpp_in_event_loop = FALSE; -} -*/ - int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { (void) argc; @@ -56,13 +47,15 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) xmpp_command_init(); - xmpp_connection_autoconnect(); - //xmpp_completion_init(); - //xmpp_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, - // &xmpp_workspace_timer_cb, - // NULL, NULL); + xmpp_hook_timer = weechat_hook_timer(1 * 1000, 0, 1, + &xmpp_connection_autoconnect, + NULL, NULL); + + xmpp_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, + &xmpp_connection_check_events, + NULL, NULL); if (!weechat_bar_search("typing")) { From a97d77f33211e1a97b74fc0692279829de1f9d1a Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 28 Jun 2021 02:17:02 +0100 Subject: [PATCH 074/118] cleanup --- Makefile | 8 +- api/message/slack-api-message-bot-message.c | 155 -- api/message/slack-api-message-bot-message.h | 12 - api/message/slack-api-message-me-message.c | 102 - api/message/slack-api-message-me-message.h | 12 - .../slack-api-message-message-changed.c | 104 - .../slack-api-message-message-changed.h | 12 - .../slack-api-message-slackbot-response.c | 98 - .../slack-api-message-slackbot-response.h | 12 - .../slack-api-message-thread-broadcast.c | 99 - .../slack-api-message-thread-broadcast.h | 12 - api/message/slack-api-message-unimplemented.c | 50 - api/message/slack-api-message-unimplemented.h | 12 - api/slack-api-error.c | 63 - api/slack-api-error.h | 11 - api/slack-api-hello.c | 54 - api/slack-api-hello.h | 11 - api/slack-api-message.c | 240 --- api/slack-api-message.h | 13 - api/slack-api-user-typing.c | 67 - api/slack-api-user-typing.h | 11 - xmpp-command.c => command.c | 4 +- xmpp-command.h => command.h | 6 +- xmpp-config.c => config.c | 6 +- xmpp-config.h => config.h | 8 +- xmpp-connection.c => connection.c | 8 +- xmpp-connection.h => connection.h | 6 +- xmpp.c => plugin.c | 12 +- xmpp.h => plugin.h | 10 +- request/slack-request-bots-info.c | 272 --- request/slack-request-bots-info.h | 12 - request/slack-request-channels-list.c | 431 ----- request/slack-request-channels-list.h | 12 - request/slack-request-chat-memessage.c | 270 --- request/slack-request-chat-memessage.h | 13 - request/slack-request-chat-postmessage.c | 271 --- request/slack-request-chat-postmessage.h | 13 - request/slack-request-conversations-members.c | 330 ---- request/slack-request-conversations-members.h | 13 - request/slack-request-emoji-list.c | 287 --- request/slack-request-emoji-list.h | 12 - request/slack-request-users-list.c | 375 ---- request/slack-request-users-list.h | 12 - slack-buffer.c | 164 -- slack-buffer.h | 27 - slack-channel.c | 642 ------- slack-channel.h | 147 -- slack-completion.c | 162 -- slack-completion.h | 10 - slack-emoji.c | 289 --- slack-emoji.h | 29 - slack-emoji.inc | 1702 ----------------- slack-input.c | 77 - slack-input.h | 12 - slack-message.c | 249 --- slack-message.h | 13 - slack-oauth.c | 245 --- slack-oauth.h | 10 - slack-request.c | 27 - slack-request.h | 29 - slack-teaminfo.c | 348 ---- slack-teaminfo.h | 20 - slack-user.c | 241 --- slack-user.h | 74 - slack-workspace.c | 972 ---------- slack-workspace.h | 95 - 66 files changed, 34 insertions(+), 9091 deletions(-) delete mode 100644 api/message/slack-api-message-bot-message.c delete mode 100644 api/message/slack-api-message-bot-message.h delete mode 100644 api/message/slack-api-message-me-message.c delete mode 100644 api/message/slack-api-message-me-message.h delete mode 100644 api/message/slack-api-message-message-changed.c delete mode 100644 api/message/slack-api-message-message-changed.h delete mode 100644 api/message/slack-api-message-slackbot-response.c delete mode 100644 api/message/slack-api-message-slackbot-response.h delete mode 100644 api/message/slack-api-message-thread-broadcast.c delete mode 100644 api/message/slack-api-message-thread-broadcast.h delete mode 100644 api/message/slack-api-message-unimplemented.c delete mode 100644 api/message/slack-api-message-unimplemented.h delete mode 100644 api/slack-api-error.c delete mode 100644 api/slack-api-error.h delete mode 100644 api/slack-api-hello.c delete mode 100644 api/slack-api-hello.h delete mode 100644 api/slack-api-message.c delete mode 100644 api/slack-api-message.h delete mode 100644 api/slack-api-user-typing.c delete mode 100644 api/slack-api-user-typing.h rename xmpp-command.c => command.c (99%) rename xmpp-command.h => command.h (70%) rename xmpp-config.c => config.c (99%) rename xmpp-config.h => config.h (95%) rename xmpp-connection.c => connection.c (98%) rename xmpp-connection.h => connection.h (85%) rename xmpp.c => plugin.c (93%) rename xmpp.h => plugin.h (66%) delete mode 100644 request/slack-request-bots-info.c delete mode 100644 request/slack-request-bots-info.h delete mode 100644 request/slack-request-channels-list.c delete mode 100644 request/slack-request-channels-list.h delete mode 100644 request/slack-request-chat-memessage.c delete mode 100644 request/slack-request-chat-memessage.h delete mode 100644 request/slack-request-chat-postmessage.c delete mode 100644 request/slack-request-chat-postmessage.h delete mode 100644 request/slack-request-conversations-members.c delete mode 100644 request/slack-request-conversations-members.h delete mode 100644 request/slack-request-emoji-list.c delete mode 100644 request/slack-request-emoji-list.h delete mode 100644 request/slack-request-users-list.c delete mode 100644 request/slack-request-users-list.h delete mode 100644 slack-buffer.c delete mode 100644 slack-buffer.h delete mode 100644 slack-channel.c delete mode 100644 slack-channel.h delete mode 100644 slack-completion.c delete mode 100644 slack-completion.h delete mode 100644 slack-emoji.c delete mode 100644 slack-emoji.h delete mode 100644 slack-emoji.inc delete mode 100644 slack-input.c delete mode 100644 slack-input.h delete mode 100644 slack-message.c delete mode 100644 slack-message.h delete mode 100644 slack-oauth.c delete mode 100644 slack-oauth.h delete mode 100644 slack-request.c delete mode 100644 slack-request.h delete mode 100644 slack-teaminfo.c delete mode 100644 slack-teaminfo.h delete mode 100644 slack-user.c delete mode 100644 slack-user.h delete mode 100644 slack-workspace.c delete mode 100644 slack-workspace.h diff --git a/Makefile b/Makefile index 3b28f64..704f6b1 100644 --- a/Makefile +++ b/Makefile @@ -13,10 +13,10 @@ PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib INSTALL ?= /usr/bin/install -SRCS=xmpp.c \ - xmpp-command.c \ - xmpp-config.c \ - xmpp-connection.c \ +SRCS=plugin.c \ + command.c \ + config.c \ + connection.c \ DEPS=json-c/libjson-c.a OLDSRCS=slack.c \ diff --git a/api/message/slack-api-message-bot-message.c b/api/message/slack-api-message-bot-message.c deleted file mode 100644 index 5a7b488..0000000 --- a/api/message/slack-api-message-bot-message.c +++ /dev/null @@ -1,155 +0,0 @@ -// 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 "../../weechat-plugin.h" -#include "../../slack.h" -#include "../../slack-workspace.h" -#include "../../slack-message.h" -#include "../../slack-api.h" -#include "../../slack-channel.h" -#include "../../slack-user.h" -#include "../slack-api-message.h" -#include "slack-api-message-bot-message.h" - -static const char *subtype = "bot_message"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %smessage.%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), subtype, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_bot_message_handle(struct t_slack_workspace *workspace, - const char *channel, const char *bot_id, - const char *username, const char *text, - const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_bot_search(workspace, bot_id); - if (!ptr_user) - return 1; /* silently ignore if bot user hasn't been loaded yet */ - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message,slack_bot_message", - _("%s%s"), - slack_user_as_prefix(workspace, ptr_user, username), - message); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - - return 1; -} - -int slack_api_message_slackbot_message_handle(struct t_slack_workspace *workspace, - const char *channel, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; /* silently ignore if slackbot user hasn't been loaded yet */ - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message,slack_slackbot_message", - _("%s%s"), - slack_user_as_prefix(workspace, ptr_user, user), - message); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - - return 1; -} - -int slack_api_message_bot_message(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *channel, *bot_id, *username, *user, *text, *ts; - channel = json_object_object_get(message, "channel"); - if (!json_valid(channel, workspace)) - return 0; - - username = json_object_object_get(message, "username"); - if (!json_valid(username, workspace)) - return 0; - - text = json_object_object_get(message, "text"); - if (!json_valid(text, workspace)) - return 0; - - ts = json_object_object_get(message, "ts"); - if (!json_valid(ts, workspace)) - return 0; - - if (strcmp("slackbot", json_object_get_string(username)) == 0) - { - user = json_object_object_get(message, "user"); - if (!json_valid(user, workspace)) - return 0; - - return slack_api_message_slackbot_message_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user), - json_object_get_string(text), - json_object_get_string(ts)); - } - else - { - bot_id = json_object_object_get(message, "bot_id"); - if (!json_valid(bot_id, workspace)) - return 0; - - return slack_api_message_bot_message_handle(workspace, - json_object_get_string(channel), - json_object_get_string(bot_id), - json_object_get_string(username), - json_object_get_string(text), - json_object_get_string(ts)); - } -} - diff --git a/api/message/slack-api-message-bot-message.h b/api/message/slack-api-message-bot-message.h deleted file mode 100644 index 93d55fc..0000000 --- a/api/message/slack-api-message-bot-message.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_BOT_MESSAGE_H_ -#define _SLACK_API_MESSAGE_BOT_MESSAGE_H_ - -int slack_api_message_bot_message( - struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_MESSAGE_BOT_MESSAGE_H*/ diff --git a/api/message/slack-api-message-me-message.c b/api/message/slack-api-message-me-message.c deleted file mode 100644 index fcc91d1..0000000 --- a/api/message/slack-api-message-me-message.c +++ /dev/null @@ -1,102 +0,0 @@ -// 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 "../../weechat-plugin.h" -#include "../../slack.h" -#include "../../slack-workspace.h" -#include "../../slack-message.h" -#include "../../slack-api.h" -#include "../../slack-channel.h" -#include "../../slack-user.h" -#include "../slack-api-message.h" -#include "slack-api-message-me-message.h" - -static const char *subtype = "me_message"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %smessage.%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), subtype, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_me_message_handle(struct t_slack_workspace *workspace, - const char *channel, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; /* silently ignore if user hasn't been loaded yet */ - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message,slack_me_message", - _("%s%s%s%s%s%s"), - weechat_prefix("action"), - slack_user_get_colour(ptr_user), - ptr_user->profile.display_name, - weechat_color("reset"), - message[0] ? " " : "", - message); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - - return 1; -} - -int slack_api_message_me_message(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *channel, *user, *text, *ts; - channel = json_object_object_get(message, "channel"); - if (!json_valid(channel, workspace)) - return 0; - - user = json_object_object_get(message, "user"); - if (!json_valid(user, workspace)) - return 0; - - text = json_object_object_get(message, "text"); - if (!json_valid(text, workspace)) - return 0; - - ts = json_object_object_get(message, "ts"); - if (!json_valid(ts, workspace)) - return 0; - - return slack_api_message_me_message_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user), - json_object_get_string(text), - json_object_get_string(ts)); -} - diff --git a/api/message/slack-api-message-me-message.h b/api/message/slack-api-message-me-message.h deleted file mode 100644 index 1131898..0000000 --- a/api/message/slack-api-message-me-message.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_ME_MESSAGE_H_ -#define _SLACK_API_MESSAGE_ME_MESSAGE_H_ - -int slack_api_message_me_message( - struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_MESSAGE_ME_MESSAGE_H*/ diff --git a/api/message/slack-api-message-message-changed.c b/api/message/slack-api-message-message-changed.c deleted file mode 100644 index 95b2a29..0000000 --- a/api/message/slack-api-message-message-changed.c +++ /dev/null @@ -1,104 +0,0 @@ -// 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 "../../weechat-plugin.h" -#include "../../slack.h" -#include "../../slack-workspace.h" -#include "../../slack-message.h" -#include "../../slack-api.h" -#include "../../slack-channel.h" -#include "../../slack-user.h" -#include "../slack-api-message.h" -#include "slack-api-message-message-changed.h" - -static const char *subtype = "message_changed"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %smessage.%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), subtype, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_message_changed_handle(struct t_slack_workspace *workspace, - json_object *root, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - /* - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; // silently ignore if channel hasn't been loaded yet - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; // silently ignore if user hasn't been loaded yet - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message,slack_thread_broadcast", - _("%s%s"), - slack_user_as_prefix(workspace, ptr_user, NULL), - message); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - */ - - return 1; -} - -int slack_api_message_message_changed(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *channel, *oldmsg, *user, *text, *ts; - channel = json_object_object_get(message, "channel"); - if (!json_valid(channel, workspace)) - return 0; - - oldmsg = json_object_object_get(message, "message"); - if (!json_valid(oldmsg, workspace)) - return 0; - - user = json_object_object_get(oldmsg, "user"); - if (!json_valid(user, workspace)) - return 0; - - text = json_object_object_get(message, "text"); - if (!json_valid(text, workspace)) - return 0; - - ts = json_object_object_get(message, "ts"); - if (!json_valid(ts, workspace)) - return 0; - - return slack_api_message_message_changed_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user), - json_object_get_string(text), - json_object_get_string(ts)); -} - diff --git a/api/message/slack-api-message-message-changed.h b/api/message/slack-api-message-message-changed.h deleted file mode 100644 index 2fd4239..0000000 --- a/api/message/slack-api-message-message-changed.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_MESSAGE_CHANGED_H_ -#define _SLACK_API_MESSAGE_MESSAGE_CHANGED_H_ - -int slack_api_message_message_changed( - struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_MESSAGE_MESSAGE_CHANGED_H*/ diff --git a/api/message/slack-api-message-slackbot-response.c b/api/message/slack-api-message-slackbot-response.c deleted file mode 100644 index 8252d28..0000000 --- a/api/message/slack-api-message-slackbot-response.c +++ /dev/null @@ -1,98 +0,0 @@ -// 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 "../../weechat-plugin.h" -#include "../../slack.h" -#include "../../slack-workspace.h" -#include "../../slack-message.h" -#include "../../slack-api.h" -#include "../../slack-channel.h" -#include "../../slack-user.h" -#include "../slack-api-message.h" -#include "slack-api-message-slackbot-response.h" - -static const char *subtype = "slackbot_response"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %smessage.%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), subtype, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_slackbot_response_handle(struct t_slack_workspace *workspace, - const char *channel, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; /* silently ignore if slackbot user hasn't been loaded yet */ - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message,slack_slackbot_response", - _("%s%s"), - slack_user_as_prefix(workspace, ptr_user, "slackbot"), - message); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - - return 1; -} - -int slack_api_message_slackbot_response(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *channel, *user, *text, *ts; - channel = json_object_object_get(message, "channel"); - if (!json_valid(channel, workspace)) - return 0; - - user = json_object_object_get(message, "user"); - if (!json_valid(user, workspace)) - return 0; - - text = json_object_object_get(message, "text"); - if (!json_valid(text, workspace)) - return 0; - - ts = json_object_object_get(message, "ts"); - if (!json_valid(ts, workspace)) - return 0; - - return slack_api_message_slackbot_response_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user), - json_object_get_string(text), - json_object_get_string(ts)); -} - diff --git a/api/message/slack-api-message-slackbot-response.h b/api/message/slack-api-message-slackbot-response.h deleted file mode 100644 index edab623..0000000 --- a/api/message/slack-api-message-slackbot-response.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_ -#define _SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H_ - -int slack_api_message_slackbot_response( - struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_MESSAGE_SLACKBOT_RESPONSE_H*/ diff --git a/api/message/slack-api-message-thread-broadcast.c b/api/message/slack-api-message-thread-broadcast.c deleted file mode 100644 index ce59478..0000000 --- a/api/message/slack-api-message-thread-broadcast.c +++ /dev/null @@ -1,99 +0,0 @@ -// 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 "../../weechat-plugin.h" -#include "../../slack.h" -#include "../../slack-workspace.h" -#include "../../slack-message.h" -#include "../../slack-api.h" -#include "../../slack-channel.h" -#include "../../slack-user.h" -#include "../slack-api-message.h" -#include "slack-api-message-thread-broadcast.h" - -static const char *subtype = "thread_broadcast"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %smessage.%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), subtype, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_thread_broadcast_handle(struct t_slack_workspace *workspace, - json_object *root, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - /* - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; // silently ignore if channel hasn't been loaded yet - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; // silently ignore if user hasn't been loaded yet - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message,slack_thread_broadcast", - _("%s%s"), - slack_user_as_prefix(workspace, ptr_user, NULL), - message); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - */ - - return 1; -} - -int slack_api_message_thread_broadcast(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *root, *user, *text, *ts; - root = json_object_object_get(message, "root"); - if (!json_valid(root, workspace)) - return 0; - - user = json_object_object_get(message, "user"); - if (!json_valid(user, workspace)) - return 0; - - text = json_object_object_get(message, "text"); - if (!json_valid(text, workspace)) - return 0; - - ts = json_object_object_get(message, "ts"); - if (!json_valid(ts, workspace)) - return 0; - - return slack_api_message_thread_broadcast_handle(workspace, - root, json_object_get_string(user), - json_object_get_string(text), - json_object_get_string(ts)); -} - diff --git a/api/message/slack-api-message-thread-broadcast.h b/api/message/slack-api-message-thread-broadcast.h deleted file mode 100644 index ea56ce7..0000000 --- a/api/message/slack-api-message-thread-broadcast.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_THREAD_BROADCAST_H_ -#define _SLACK_API_MESSAGE_THREAD_BROADCAST_H_ - -int slack_api_message_thread_broadcast( - struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_MESSAGE_THREAD_BROADCAST_H*/ diff --git a/api/message/slack-api-message-unimplemented.c b/api/message/slack-api-message-unimplemented.c deleted file mode 100644 index d9b3490..0000000 --- a/api/message/slack-api-message-unimplemented.c +++ /dev/null @@ -1,50 +0,0 @@ -// 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 "../../weechat-plugin.h" -#include "../../slack.h" -#include "../../slack-workspace.h" -#include "../../slack-api.h" -#include "../../slack-channel.h" -#include "../../slack-user.h" -#include "../slack-api-message.h" -#include "slack-api-message-unimplemented.h" - -static const char *subtype = "unimplemented"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %smessage.%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), subtype, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_unimplemented(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *subtype = json_object_object_get(message, "subtype"); - if (!json_valid(subtype, workspace)) - return 0; - - weechat_printf( - workspace->buffer, - _("%s%s: got unhandled message of type: message.%s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - json_object_get_string(subtype)); - - return 1; -} - diff --git a/api/message/slack-api-message-unimplemented.h b/api/message/slack-api-message-unimplemented.h deleted file mode 100644 index 0e46d70..0000000 --- a/api/message/slack-api-message-unimplemented.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_UNIMPLEMENTED_H_ -#define _SLACK_API_MESSAGE_UNIMPLEMENTED_H_ - -int slack_api_message_unimplemented( - struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_MESSAGE_UNIMPLEMENTED_H*/ diff --git a/api/slack-api-error.c b/api/slack-api-error.c deleted file mode 100644 index 0ed9b4b..0000000 --- a/api/slack-api-error.c +++ /dev/null @@ -1,63 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-api.h" -#include "slack-api-error.h" - -static const char *type = "error"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %s%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), type, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_error_handle(struct t_slack_workspace *workspace, - int code, const char *msg) -{ - weechat_printf( - workspace->buffer, - _("%s%s: error %d: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - code, msg); - - return 0; -} - -int slack_api_error(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *error, *code, *msg; - - error = json_object_object_get(message, "error"); - if (!json_valid(error, workspace)) - return 0; - - code = json_object_object_get(error, "code"); - if (!json_valid(code, workspace)) - return 0; - - msg = json_object_object_get(error, "msg"); - if (!json_valid(msg, workspace)) - return 0; - - return slack_api_error_handle(workspace, - json_object_get_int(code), - json_object_get_string(msg)); -} diff --git a/api/slack-api-error.h b/api/slack-api-error.h deleted file mode 100644 index d6f52ed..0000000 --- a/api/slack-api-error.h +++ /dev/null @@ -1,11 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_ERROR_H_ -#define _SLACK_API_ERROR_H_ - -int slack_api_error(struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_ERROR_H*/ diff --git a/api/slack-api-hello.c b/api/slack-api-hello.c deleted file mode 100644 index 611cfc6..0000000 --- a/api/slack-api-hello.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-api.h" -#include "slack-api-hello.h" -#include "../request/slack-request-channels-list.h" -#include "../request/slack-request-users-list.h" -#include "../request/slack-request-emoji-list.h" - -int slack_api_hello_handle(struct t_slack_workspace *workspace) -{ - struct t_slack_request *request; - - weechat_printf( - workspace->buffer, - _("%s%s: connected!"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - - request = slack_request_users_list(workspace, - weechat_config_string( - workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - ""); - if (request) - slack_workspace_register_request(workspace, request); - - request = slack_request_channels_list(workspace, - weechat_config_string( - workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - ""); - if (request) - slack_workspace_register_request(workspace, request); - - request = slack_request_emoji_list(workspace, - weechat_config_string( - workspace->options[SLACK_WORKSPACE_OPTION_TOKEN])); - if (request) - slack_workspace_register_request(workspace, request); - - return 1; -} - -int slack_api_hello(struct t_slack_workspace *workspace, - json_object *message) -{ - (void) message; - - return slack_api_hello_handle(workspace); -} diff --git a/api/slack-api-hello.h b/api/slack-api-hello.h deleted file mode 100644 index f3786d8..0000000 --- a/api/slack-api-hello.h +++ /dev/null @@ -1,11 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_HELLO_H_ -#define _SLACK_API_HELLO_H_ - -int slack_api_hello(struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_HELLO_H*/ diff --git a/api/slack-api-message.c b/api/slack-api-message.c deleted file mode 100644 index f755c19..0000000 --- a/api/slack-api-message.c +++ /dev/null @@ -1,240 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-api.h" -#include "../slack-channel.h" -#include "../slack-user.h" -#include "../slack-message.h" -#include "slack-api-message.h" -#include "message/slack-api-message-unimplemented.h" -#include "message/slack-api-message-bot-message.h" -#include "message/slack-api-message-me-message.h" -#include "message/slack-api-message-slackbot-response.h" - -static const char *type = "message"; - -struct stringcase -{ - const char *string; - int (*func)(struct t_slack_workspace *workspace, - json_object *message); -}; - -static struct stringcase cases[] = -{ { "bot_message", &slack_api_message_bot_message } -, { "channel_archive", &slack_api_message_unimplemented } -, { "channel_join", &slack_api_message_unimplemented } -, { "channel_leave", &slack_api_message_unimplemented } -, { "channel_name", &slack_api_message_unimplemented } -, { "channel_purpose", &slack_api_message_unimplemented } -, { "channel_topic", &slack_api_message_unimplemented } -, { "channel_unarchive", &slack_api_message_unimplemented } -, { "file_comment", &slack_api_message_unimplemented } -, { "file_mention", &slack_api_message_unimplemented } -, { "file_share", &slack_api_message_unimplemented } -, { "group_archive", &slack_api_message_unimplemented } -, { "group_join", &slack_api_message_unimplemented } -, { "group_leave", &slack_api_message_unimplemented } -, { "group_name", &slack_api_message_unimplemented } -, { "group_purpose", &slack_api_message_unimplemented } -, { "group_topic", &slack_api_message_unimplemented } -, { "group_unarchive", &slack_api_message_unimplemented } -, { "me_message", &slack_api_message_me_message } -, { "message_changed", &slack_api_message_unimplemented } -, { "message_deleted", &slack_api_message_unimplemented } -, { "message_replied", &slack_api_message_unimplemented } -, { "pinned_item", &slack_api_message_unimplemented } -, { "reply_broadcast", &slack_api_message_unimplemented } -, { "slackbot_response", &slack_api_message_slackbot_response } -, { "thread_broadcast", &slack_api_message_unimplemented } -, { "unpinned_item", &slack_api_message_unimplemented } -}; - -static int stringcase_cmp(const void *p1, const void *p2) -{ - return strcasecmp(((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string); -} - -void slack_api_message_init() -{ - size_t case_count = sizeof(cases) / sizeof(cases[0]); - qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp); -} - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %s%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), type, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_message_message_handle(struct t_slack_workspace *workspace, - const char *channel, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - struct t_slack_channel_typing *ptr_typing; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; /* silently ignore if user hasn't been loaded yet */ - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message", - _("%s%s"), - slack_user_as_prefix(workspace, ptr_user, NULL), - message); - slack_channel_member_speaking_add(ptr_channel, ptr_user->profile.display_name, - weechat_string_has_highlight( - message, - ptr_user->profile.display_name)); - free(message); - - ptr_typing = slack_channel_typing_search(ptr_channel, - ptr_user->profile.display_name); - if (ptr_typing) - { - slack_channel_typing_free(ptr_channel, ptr_typing); - slack_channel_typing_cb(ptr_channel, NULL, 0); - } - - return 1; -} - -int slack_api_message_attachment_handle(struct t_slack_workspace *workspace, - const char *channel, const char *user, - const char *text, const char *ts) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; /* silently ignore if user hasn't been loaded yet */ - - char *message = slack_message_decode(workspace, text); - weechat_printf_date_tags( - ptr_channel->buffer, - (time_t)atof(ts), - "slack_message", - _("%s%s"), - "++\t", - message); - free(message); - - return 1; -} - -int slack_api_message_route_message(struct t_slack_workspace *workspace, - const char *subtype, - json_object *message) -{ - struct stringcase key; - key.string = subtype; - - size_t case_count = sizeof(cases) / sizeof(cases[0]); - void *entry_ptr = bsearch(&key, cases, case_count, - sizeof(struct stringcase), stringcase_cmp); - - if (entry_ptr) - { - struct stringcase *entry = (struct stringcase *)entry_ptr; - return (*entry->func)(workspace, message); - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: got unhandled message of type: message.%s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - subtype); - return 1; - } -} - -int slack_api_message(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *subtype, *channel, *user, *text, *ts; - json_object *attachments, *attachment, *fallback; - int i, rc; - - subtype = json_object_object_get(message, "subtype"); - if (!subtype) - { /* normal message */ - channel = json_object_object_get(message, "channel"); - if (!json_valid(channel, workspace)) - return 0; - - user = json_object_object_get(message, "user"); - if (!json_valid(user, workspace)) - return 0; - - text = json_object_object_get(message, "text"); - if (!json_valid(text, workspace)) - return 0; - - ts = json_object_object_get(message, "ts"); - if (!json_valid(ts, workspace)) - return 0; - - rc = slack_api_message_message_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user), - json_object_get_string(text), - json_object_get_string(ts)); - attachments = json_object_object_get(message, "attachments"); - if (json_valid(attachments, workspace)) - { - for (i = json_object_array_length(attachments); i > 0; i--) - { - attachment = json_object_array_get_idx(attachments, i - 1); - if (!json_valid(attachment, workspace)) - continue; - - fallback = json_object_object_get(attachment, "fallback"); - if (!json_valid(fallback, workspace)) - continue; - - slack_api_message_attachment_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user), - json_object_get_string(fallback), - json_object_get_string(ts)); - } - } - return rc; - } - else - { /* special message */ - return slack_api_message_route_message(workspace, - json_object_get_string(subtype), - message); - } -} diff --git a/api/slack-api-message.h b/api/slack-api-message.h deleted file mode 100644 index b72ffa4..0000000 --- a/api/slack-api-message.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_MESSAGE_H_ -#define _SLACK_API_MESSAGE_H_ - -int slack_api_message(struct t_slack_workspace *workspace, - json_object *message); - -void slack_api_message_init(); - -#endif /*SLACK_API_MESSAGE_H*/ diff --git a/api/slack-api-user-typing.c b/api/slack-api-user-typing.c deleted file mode 100644 index 1909dbd..0000000 --- a/api/slack-api-user-typing.c +++ /dev/null @@ -1,67 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-user.h" -#include "../slack-channel.h" -#include "../slack-api.h" -#include "slack-api-user-typing.h" - -static const char *type = "user_typing"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error handling websocket %s%s%s message: " - "unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - weechat_color("chat_value"), type, weechat_color("reset")); - return 0; - } - - return 1; -} - -int slack_api_user_typing_handle(struct t_slack_workspace *workspace, - const char *channel, const char *user) -{ - struct t_slack_channel *ptr_channel; - struct t_slack_user *ptr_user; - - ptr_channel = slack_channel_search(workspace, channel); - if (!ptr_channel) - return 1; /* silently ignore if channel hasn't been loaded yet */ - ptr_user = slack_user_search(workspace, user); - if (!ptr_user) - return 1; /* silently ignore if user hasn't been loaded yet */ - - slack_channel_add_typing(ptr_channel, ptr_user); - - return 1; -} - -int slack_api_user_typing(struct t_slack_workspace *workspace, - json_object *message) -{ - json_object *channel, *user; - - channel = json_object_object_get(message, "channel"); - if (!json_valid(channel, workspace)) - return 0; - - user = json_object_object_get(message, "user"); - if (!json_valid(user, workspace)) - return 0; - - return slack_api_user_typing_handle(workspace, - json_object_get_string(channel), - json_object_get_string(user)); -} diff --git a/api/slack-api-user-typing.h b/api/slack-api-user-typing.h deleted file mode 100644 index c036333..0000000 --- a/api/slack-api-user-typing.h +++ /dev/null @@ -1,11 +0,0 @@ -// 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/. - -#ifndef _SLACK_API_USER_TYPING_H_ -#define _SLACK_API_USER_TYPING_H_ - -int slack_api_user_typing(struct t_slack_workspace *workspace, - json_object *message); - -#endif /*SLACK_API_USER_TYPING_H*/ diff --git a/xmpp-command.c b/command.c similarity index 99% rename from xmpp-command.c rename to command.c index 44ae73c..ff62b1a 100644 --- a/xmpp-command.c +++ b/command.c @@ -7,14 +7,14 @@ #include #include -#include "xmpp.h" +#include "plugin.h" //#include "xmpp-oauth.h" //#include "xmpp-teaminfo.h" //#include "xmpp-workspace.h" //#include "xmpp-channel.h" //#include "xmpp-buffer.h" //#include "xmpp-message.h" -#include "xmpp-command.h" +#include "command.h" //#include "request/xmpp-request-chat-memessage.h" /* diff --git a/xmpp-command.h b/command.h similarity index 70% rename from xmpp-command.h rename to command.h index 62be0e5..1e79a41 100644 --- a/xmpp-command.h +++ b/command.h @@ -2,9 +2,9 @@ // 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/. -#ifndef _XMPP_COMMAND_H_ -#define _XMPP_COMMAND_H_ +#ifndef _WEECHAT_XMPP_COMMAND_H_ +#define _WEECHAT_XMPP_COMMAND_H_ extern void xmpp_command_init(); -#endif /*XMPP_COMMAND_H*/ +#endif /*WEECHAT_XMPP_COMMAND_H*/ diff --git a/xmpp-config.c b/config.c similarity index 99% rename from xmpp-config.c rename to config.c index 2169e49..cc5789b 100644 --- a/xmpp-config.c +++ b/config.c @@ -7,8 +7,8 @@ #include #include -#include "xmpp.h" -#include "xmpp-config.h" +#include "plugin.h" +#include "config.h" struct t_config_file *xmpp_config_file; @@ -241,7 +241,7 @@ int xmpp_config_init() struct t_config_section *ptr_section_server; struct t_config_section *ptr_section_look; - xmpp_config_file = weechat_config_new(XMPP_CONFIG_NAME, + xmpp_config_file = weechat_config_new(WEECHAT_XMPP_CONFIG_NAME, &xmpp_config_reload, NULL, NULL); if(!xmpp_config_file) diff --git a/xmpp-config.h b/config.h similarity index 95% rename from xmpp-config.h rename to config.h index 128d8a4..c291cc4 100644 --- a/xmpp-config.h +++ b/config.h @@ -2,10 +2,10 @@ // 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/. -#ifndef _XMPP_CONFIG_H_ -#define _XMPP_CONFIG_H_ +#ifndef _WEECHAT_XMPP_CONFIG_H_ +#define _WEECHAT_XMPP_CONFIG_H_ -#define XMPP_CONFIG_NAME "xmpp" +#define WEECHAT_XMPP_CONFIG_NAME "xmpp" enum t_xmpp_config_nick_completion { @@ -56,4 +56,4 @@ extern int xmpp_config_read(); extern int xmpp_config_write(); extern void xmpp_config_free(); -#endif /*XMPP_CONFIG_H*/ +#endif /*WEECHAT_XMPP_CONFIG_H*/ diff --git a/xmpp-connection.c b/connection.c similarity index 98% rename from xmpp-connection.c rename to connection.c index 1fdc6d6..6ac95a2 100644 --- a/xmpp-connection.c +++ b/connection.c @@ -8,9 +8,9 @@ #include #include -#include "xmpp.h" -#include "xmpp-config.h" -#include "xmpp-connection.h" +#include "plugin.h" +#include "config.h" +#include "connection.h" //#include "api/xmpp-api-hello.h" //#include "api/xmpp-api-error.h" //#include "api/xmpp-api-message.h" @@ -30,7 +30,7 @@ void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, c weechat_printf( NULL, _("%s%s/%s (%s): %s"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, area, + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, area, log_level_name[level], msg); } diff --git a/xmpp-connection.h b/connection.h similarity index 85% rename from xmpp-connection.h rename to connection.h index 9d323fb..d2f3448 100644 --- a/xmpp-connection.h +++ b/connection.h @@ -2,8 +2,8 @@ // 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/. -#ifndef _XMPP_CONNECTION_H_ -#define _XMPP_CONNECTION_H_ +#ifndef _WEECHAT_XMPP_CONNECTION_H_ +#define _WEECHAT_XMPP_CONNECTION_H_ extern xmpp_conn_t *xmpp_connection; @@ -18,4 +18,4 @@ int xmpp_connection_check_events(const void *pointer, void *data, int remaining_ int xmpp_connection_route_message(xmpp_conn_t *connection, const char *type, json_object *message); -#endif /*XMPP_CONNECTION_H*/ +#endif /*WEECHAT_XMPP_CONNECTION_H*/ diff --git a/xmpp.c b/plugin.c similarity index 93% rename from xmpp.c rename to plugin.c index 6138be1..1381694 100644 --- a/xmpp.c +++ b/plugin.c @@ -9,19 +9,19 @@ #include #include -#include "xmpp.h" -#include "xmpp-config.h" -#include "xmpp-connection.h" -#include "xmpp-command.h" +#include "plugin.h" +#include "config.h" +#include "connection.h" +#include "command.h" //#include "xmpp-workspace.h" //#include "xmpp-buffer.h" //#include "xmpp-completion.h" -WEECHAT_PLUGIN_NAME(XMPP_PLUGIN_NAME); +WEECHAT_PLUGIN_NAME(WEECHAT_XMPP_PLUGIN_NAME); WEECHAT_PLUGIN_DESCRIPTION(N_("XMPP protocol")); WEECHAT_PLUGIN_AUTHOR("bqv "); -WEECHAT_PLUGIN_VERSION(XMPP_PLUGIN_VERSION); +WEECHAT_PLUGIN_VERSION(WEECHAT_XMPP_PLUGIN_VERSION); WEECHAT_PLUGIN_LICENSE("MPL2"); WEECHAT_PLUGIN_PRIORITY(5500); diff --git a/xmpp.h b/plugin.h similarity index 66% rename from xmpp.h rename to plugin.h index a70ebae..bc5ff5d 100644 --- a/xmpp.h +++ b/plugin.h @@ -2,13 +2,13 @@ // 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/. -#ifndef _XMPP_H_ -#define _XMPP_H_ +#ifndef _WEECHAT_XMPP_H_ +#define _WEECHAT_XMPP_H_ #define weechat_plugin weechat_xmpp_plugin -#define XMPP_PLUGIN_NAME "xmpp" -#define XMPP_PLUGIN_VERSION "0.1" +#define WEECHAT_XMPP_PLUGIN_NAME "xmpp" +#define WEECHAT_XMPP_PLUGIN_VERSION "0.1" extern struct t_weechat_plugin *weechat_xmpp_plugin; -#endif /*XMPP_H*/ +#endif /*WEECHAT_XMPP_H*/ diff --git a/request/slack-request-bots-info.c b/request/slack-request-bots-info.c deleted file mode 100644 index 278d467..0000000 --- a/request/slack-request-bots-info.c +++ /dev/null @@ -1,272 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-channel.h" -#include "../slack-request.h" -#include "../slack-user.h" -#include "../request/slack-request-bots-info.h" - -static const char *const endpoint = "/api/bots.info?" - "token=%s&bot=%s"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error retrieving bot info: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) retrieving bot info... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - char cursor[64]; - json_object *response, *ok, *error, *members, *metadata; - json_object *user, *id, *name, *profile, *display_name, *next_cursor; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - // TODO: this - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to retrieve users: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_bots_info( - struct t_slack_workspace *workspace, - const char *token, const char *cursor) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - - size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token, cursor); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-bots-info.h b/request/slack-request-bots-info.h deleted file mode 100644 index f743f13..0000000 --- a/request/slack-request-bots-info.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_BOTS_INFO_H_ -#define _SLACK_REQUEST_BOTS_INFO_H_ - -struct t_slack_request *slack_request_bots_info( - struct t_slack_workspace *workspace, - const char *token, const char *cursor); - -#endif /*SLACK_REQUEST_BOTS_INFO_H*/ diff --git a/request/slack-request-channels-list.c b/request/slack-request-channels-list.c deleted file mode 100644 index 6e2d30e..0000000 --- a/request/slack-request-channels-list.c +++ /dev/null @@ -1,431 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-request.h" -#include "../slack-channel.h" -#include "../request/slack-request-channels-list.h" - -static const char *const endpoint = "/api/channels.list?" - "token=%s&cursor=%s&" - "exclude_archived=false&exclude_members=true&limit=20"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error retrieving channels: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) retrieving channels... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - char cursor[64]; - json_object *response, *ok, *error, *channels, *metadata; - json_object *channel, *id, *name, *created; - json_object *is_general, *name_normalized, *is_shared, *is_org_shared, *is_member; - json_object *topic, *purpose, *is_archived; - json_object *sub_value, *sub_creator, *sub_last_set; - json_object *creator, *next_cursor; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - channels = json_object_object_get(response, "channels"); - if (!json_valid(channels, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - for (i = json_object_array_length(channels); i > 0; i--) - { - struct t_slack_channel *new_channel; - - channel = json_object_array_get_idx(channels, i - 1); - if (!json_valid(channel, request->workspace)) - { - continue; - } - - id = json_object_object_get(channel, "id"); - if (!json_valid(id, request->workspace)) - { - continue; - } - - name = json_object_object_get(channel, "name"); - if (!json_valid(name, request->workspace)) - { - continue; - } - - new_channel = slack_channel_new( - request->workspace, - SLACK_CHANNEL_TYPE_CHANNEL, - json_object_get_string(id), - json_object_get_string(name)); - - created = json_object_object_get(channel, "created"); - if (json_valid(created, request->workspace)) - { - new_channel->created = json_object_get_int(created); - } - - is_general = json_object_object_get(channel, "is_general"); - if (json_valid(is_general, request->workspace)) - { - new_channel->is_general = json_object_get_boolean(is_general); - } - - name_normalized = json_object_object_get(channel, "name_normalized"); - if (json_valid(name_normalized, request->workspace)) - { - new_channel->name_normalized = strdup( - json_object_get_string(name_normalized)); - } - - is_shared = json_object_object_get(channel, "is_shared"); - if (json_valid(is_shared, request->workspace)) - { - new_channel->is_shared = json_object_get_boolean(is_shared); - } - - is_org_shared = json_object_object_get(channel, "is_org_shared"); - if (json_valid(is_org_shared, request->workspace)) - { - new_channel->is_org_shared = json_object_get_boolean(is_org_shared); - } - - is_member = json_object_object_get(channel, "is_member"); - if (json_valid(is_member, request->workspace)) - { - new_channel->is_member = json_object_get_boolean(is_member); - } - - topic = json_object_object_get(channel, "topic"); - if (json_valid(topic, request->workspace)) - { - sub_value = json_object_object_get(topic, "value"); - - sub_creator = json_object_object_get(topic, "creator"); - - sub_last_set = json_object_object_get(topic, "last_set"); - - slack_channel_update_topic(new_channel, - json_valid(sub_value, request->workspace) ? - json_object_get_string(sub_value) : - NULL, - json_valid(sub_creator, request->workspace) ? - json_object_get_string(sub_creator) : - NULL, - json_valid(sub_last_set, request->workspace) ? - json_object_get_int(sub_last_set) : - 0); - } - - purpose = json_object_object_get(channel, "purpose"); - if (json_valid(purpose, request->workspace)) - { - sub_value = json_object_object_get(topic, "value"); - - sub_creator = json_object_object_get(topic, "creator"); - - sub_last_set = json_object_object_get(topic, "last_set"); - - slack_channel_update_purpose(new_channel, - json_valid(sub_value, request->workspace) ? - json_object_get_string(sub_value) : - NULL, - json_valid(sub_creator, request->workspace) ? - json_object_get_string(sub_creator) : - NULL, - json_valid(sub_last_set, request->workspace) ? - json_object_get_int(sub_last_set) : - 0); - } - - is_archived = json_object_object_get(response, "is_archived"); - if (json_valid(is_archived, request->workspace)) - { - new_channel->is_archived = json_object_get_boolean(is_archived); - } - - creator = json_object_object_get(response, "creator"); - if (json_valid(creator, request->workspace)) - { - new_channel->creator = strdup(json_object_get_string(creator)); - } - } - - metadata = json_object_object_get(response, "response_metadata"); - if (!json_valid(metadata, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - next_cursor = json_object_object_get(metadata, "next_cursor"); - if (!json_valid(next_cursor, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor)); - - if (cursor[0]) - { - struct t_slack_request *next_request; - - next_request = slack_request_channels_list(request->workspace, - weechat_config_string( - request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - cursor); - if (next_request) - slack_workspace_register_request(request->workspace, next_request); - } - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to retrieve channels: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_channels_list( - struct t_slack_workspace *workspace, - const char *token, const char *cursor) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - - size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token, cursor); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-channels-list.h b/request/slack-request-channels-list.h deleted file mode 100644 index d965538..0000000 --- a/request/slack-request-channels-list.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_CHANNELS_LIST_H_ -#define _SLACK_REQUEST_CHANNELS_LIST_H_ - -struct t_slack_request *slack_request_channels_list( - struct t_slack_workspace *workspace, - const char *token, const char *cursor); - -#endif /*SLACK_REQUEST_CHANNELS_LIST_H*/ diff --git a/request/slack-request-chat-memessage.c b/request/slack-request-chat-memessage.c deleted file mode 100644 index 38a0487..0000000 --- a/request/slack-request-chat-memessage.c +++ /dev/null @@ -1,270 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-request.h" -#include "../slack-user.h" -#include "../request/slack-request-chat-memessage.h" - -static const char *const endpoint = "/api/chat.meMessage?" - "token=%s&channel=%s&text=%s&"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error sending me-message: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) sending me-message... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - json_object *response, *ok, *error; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - /* wait for websocket to catch up */ - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to send me-message: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_chat_memessage( - struct t_slack_workspace *workspace, - const char *token, const char *channel, - const char *text) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - - size_t urilen = snprintf(NULL, 0, endpoint, token, channel, text) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token, channel, text); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-chat-memessage.h b/request/slack-request-chat-memessage.h deleted file mode 100644 index d93c95b..0000000 --- a/request/slack-request-chat-memessage.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_CHAT_MEMESSAGE_H_ -#define _SLACK_REQUEST_CHAT_MEMESSAGE_H_ - -struct t_slack_request *slack_request_chat_memessage( - struct t_slack_workspace *workspace, - const char *token, const char *channel, - const char *text); - -#endif /*SLACK_REQUEST_CHAT_MEMESSAGE_H*/ diff --git a/request/slack-request-chat-postmessage.c b/request/slack-request-chat-postmessage.c deleted file mode 100644 index 1bf644c..0000000 --- a/request/slack-request-chat-postmessage.c +++ /dev/null @@ -1,271 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-request.h" -#include "../slack-user.h" -#include "../request/slack-request-chat-postmessage.h" - -static const char *const endpoint = "/api/chat.postMessage?" - "token=%s&channel=%s&text=%s&" - "as_user=true&link_names=true&mrkdwn=false&parse=full"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error posting message: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) posting message... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - json_object *response, *ok, *error; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - /* wait for websocket to catch up */ - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to post message: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_chat_postmessage( - struct t_slack_workspace *workspace, - const char *token, const char *channel, - const char *text) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - - size_t urilen = snprintf(NULL, 0, endpoint, token, channel, text) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token, channel, text); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-chat-postmessage.h b/request/slack-request-chat-postmessage.h deleted file mode 100644 index 55be2a3..0000000 --- a/request/slack-request-chat-postmessage.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_CHAT_POSTMESSAGE_H_ -#define _SLACK_REQUEST_CHAT_POSTMESSAGE_H_ - -struct t_slack_request *slack_request_chat_postmessage( - struct t_slack_workspace *workspace, - const char *token, const char *channel, - const char *text); - -#endif /*SLACK_REQUEST_CHAT_POSTMESSAGE_H*/ diff --git a/request/slack-request-conversations-members.c b/request/slack-request-conversations-members.c deleted file mode 100644 index 1b9bd5f..0000000 --- a/request/slack-request-conversations-members.c +++ /dev/null @@ -1,330 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-channel.h" -#include "../slack-request.h" -#include "../slack-user.h" -#include "../request/slack-request-conversations-members.h" - -static const char *const endpoint = "/api/conversations.members?" - "token=%s&channel=%s&cursor=%s&limit=100"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error retrieving members: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - struct t_slack_channel *channel; - const char *channelid; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) retrieving members... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - char cursor[64]; - json_object *response, *ok, *error, *members; - json_object *user, *metadata, *next_cursor; - struct t_json_chunk *chunk_ptr; - - channelid = (const char *)request->pointer; - channel = slack_channel_search(request->workspace, channelid); - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - members = json_object_object_get(response, "members"); - if (!json_valid(members, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - for (i = json_object_array_length(members); i > 0; i--) - { - user = json_object_array_get_idx(members, i - 1); - if (!json_valid(user, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - slack_channel_add_member(request->workspace, - channel, - json_object_get_string(user)); - } - - metadata = json_object_object_get(response, "response_metadata"); - if (!json_valid(metadata, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - next_cursor = json_object_object_get(metadata, "next_cursor"); - if (!json_valid(next_cursor, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor)); - - if (cursor[0]) - { - struct t_slack_request *next_request; - - next_request = slack_request_conversations_members(request->workspace, - weechat_config_string( - request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - channelid, - cursor); - if (next_request) - slack_workspace_register_request(request->workspace, next_request); - } - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to retrieve users: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_conversations_members( - struct t_slack_workspace *workspace, - const char *token, const char *channel, - const char *cursor) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - request->pointer = channel; - - size_t urilen = snprintf(NULL, 0, endpoint, token, channel, cursor) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token, channel, cursor); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-conversations-members.h b/request/slack-request-conversations-members.h deleted file mode 100644 index d5a1458..0000000 --- a/request/slack-request-conversations-members.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_ -#define _SLACK_REQUEST_CONVERSATIONS_MEMBERS_H_ - -struct t_slack_request *slack_request_conversations_members( - struct t_slack_workspace *workspace, - const char *token, const char *channel, - const char *cursor); - -#endif /*SLACK_REQUEST_CONVERSATIONS_MEMBERS_H*/ diff --git a/request/slack-request-emoji-list.c b/request/slack-request-emoji-list.c deleted file mode 100644 index abc303b..0000000 --- a/request/slack-request-emoji-list.c +++ /dev/null @@ -1,287 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-request.h" -#include "../slack-channel.h" -#include "../request/slack-request-emoji-list.h" - -static const char *const endpoint = "/api/emoji.list?" - "token=%s"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error retrieving emoji: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) retrieving emoji... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - json_object *response, *ok, *error, *emoji; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - emoji = json_object_object_get(response, "emoji"); - if (!json_valid(emoji, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - json_object_object_foreach(emoji, key, val) - { - if (!json_valid(val, request->workspace)) - { - continue; - } - - slack_workspace_add_emoji( - request->workspace, - key, json_object_get_string(val)); - } - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to retrieve emoji: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_emoji_list( - struct t_slack_workspace *workspace, - const char *token) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - - size_t urilen = snprintf(NULL, 0, endpoint, token) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-emoji-list.h b/request/slack-request-emoji-list.h deleted file mode 100644 index 19101d1..0000000 --- a/request/slack-request-emoji-list.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_EMOJI_LIST_H_ -#define _SLACK_REQUEST_EMOJI_LIST_H_ - -struct t_slack_request *slack_request_emoji_list( - struct t_slack_workspace *workspace, - const char *token); - -#endif /*SLACK_REQUEST_EMOJI_LIST_H*/ diff --git a/request/slack-request-users-list.c b/request/slack-request-users-list.c deleted file mode 100644 index 33e2dab..0000000 --- a/request/slack-request-users-list.c +++ /dev/null @@ -1,375 +0,0 @@ -// 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 "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-channel.h" -#include "../slack-request.h" -#include "../slack-user.h" -#include "../request/slack-request-conversations-members.h" -#include "../request/slack-request-users-list.h" - -static const char *const endpoint = "/api/users.list?" - "token=%s&cursor=%s&" - "exclude_archived=false&exclude_members=true&limit=20"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error retrieving users: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - //__asm__("int3"); - return 0; - } - - return 1; -} - -static const struct lws_protocols protocols[]; - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_request *request = (struct t_slack_request *)user; - struct lws_client_connect_info ccinfo; - - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - in ? (char *)in : "(null)"); - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) reconnecting..."), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) retrieving users... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (request->json_chunks) - { - for (last_chunk = request->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - request->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - char cursor[64]; - json_object *response, *ok, *error, *members; - json_object *user, *id, *name; - json_object *profile, *display_name, *bot_id; - json_object *metadata, *next_cursor; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (request->json_chunks) - { - chunk_count++; - for (chunk_ptr = request->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = request->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(request->json_chunks->data); - free(request->json_chunks); - request->json_chunks = chunk_ptr; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - members = json_object_object_get(response, "members"); - if (!json_valid(members, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - for (i = json_object_array_length(members); i > 0; i--) - { - struct t_slack_user *new_user; - - user = json_object_array_get_idx(members, i - 1); - if (!json_valid(user, request->workspace)) - { - continue; - } - - id = json_object_object_get(user, "id"); - if (!json_valid(id, request->workspace)) - { - continue; - } - - name = json_object_object_get(user, "name"); - if (!json_valid(name, request->workspace)) - { - continue; - } - - profile = json_object_object_get(user, "profile"); - if (!json_valid(profile, request->workspace)) - { - continue; - } - - display_name = json_object_object_get(profile, "display_name"); - if (!json_valid(display_name, request->workspace)) - { - continue; - } - - new_user = slack_user_new(request->workspace, - json_object_get_string(id), - json_object_get_string(display_name)[0] ? - json_object_get_string(display_name) : - json_object_get_string(name)); - - bot_id = json_object_object_get(profile, "bot_id"); - if (json_valid(bot_id, request->workspace)) - { - new_user->profile.bot_id = strdup(json_object_get_string(bot_id)); - } - } - - metadata = json_object_object_get(response, "response_metadata"); - if (!json_valid(metadata, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - next_cursor = json_object_object_get(metadata, "next_cursor"); - if (!json_valid(next_cursor, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - lws_urlencode(cursor, json_object_get_string(next_cursor), sizeof(cursor)); - - if (cursor[0]) - { - struct t_slack_request *next_request; - - next_request = slack_request_users_list(request->workspace, - weechat_config_string( - request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - cursor); - if (next_request) - slack_workspace_register_request(request->workspace, next_request); - } - else - { - struct t_slack_request *next_request; - struct t_slack_channel *ptr_channel; - - for (ptr_channel = request->workspace->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) - { - next_request = slack_request_conversations_members(request->workspace, - weechat_config_string( - request->workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - ptr_channel->id, - cursor); - if (next_request) - slack_workspace_register_request(request->workspace, next_request); - } - } - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, request->workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - request->workspace->buffer, - _("%s%s: (%d) failed to retrieve users: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - request->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_request *slack_request_users_list( - struct t_slack_workspace *workspace, - const char *token, const char *cursor) -{ - struct t_slack_request *request; - struct lws_context_creation_info ctxinfo; - struct lws_client_connect_info ccinfo; - - request = slack_request_alloc(workspace); - - size_t urilen = snprintf(NULL, 0, endpoint, token, cursor) + 1; - request->uri = malloc(urilen); - snprintf(request->uri, urilen, endpoint, token, cursor); - - memset(&ctxinfo, 0, sizeof(ctxinfo)); /* otherwise uninitialized garbage */ - ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctxinfo.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - ctxinfo.protocols = protocols; - - request->context = lws_create_context(&ctxinfo); - if (!request->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, request->idx); - return NULL; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: (%d) contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, request->idx); - } - - memset(&ccinfo, 0, sizeof(ccinfo)); /* otherwise uninitialized garbage */ - ccinfo.context = request->context; - ccinfo.ssl_connection = LCCSCF_USE_SSL; - ccinfo.port = 443; - ccinfo.address = "slack.com"; - ccinfo.path = request->uri; - ccinfo.host = ccinfo.address; - ccinfo.origin = ccinfo.address; - ccinfo.method = "GET"; - ccinfo.protocol = protocols[0].name; - ccinfo.pwsi = &request->client_wsi; - ccinfo.userdata = request; - - lws_client_connect_via_info(&ccinfo); - - return request; -} diff --git a/request/slack-request-users-list.h b/request/slack-request-users-list.h deleted file mode 100644 index e5e3825..0000000 --- a/request/slack-request-users-list.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_USERS_LIST_H_ -#define _SLACK_REQUEST_USERS_LIST_H_ - -struct t_slack_request *slack_request_users_list( - struct t_slack_workspace *workspace, - const char *token, const char *cursor); - -#endif /*SLACK_REQUEST_USERS_LIST_H*/ diff --git a/slack-buffer.c b/slack-buffer.c deleted file mode 100644 index c922cfc..0000000 --- a/slack-buffer.c +++ /dev/null @@ -1,164 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-channel.h" -#include "slack-buffer.h" - -void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, - struct t_slack_workspace **workspace, - struct t_slack_channel **channel) -{ - struct t_slack_workspace *ptr_workspace; - struct t_slack_channel *ptr_channel; - - if (!buffer) - return; - - /* look for a workspace or channel using this buffer */ - for (ptr_workspace = slack_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) - { - if (ptr_workspace->buffer == buffer) - { - if (workspace) - *workspace = ptr_workspace; - return; - } - - for (ptr_channel = ptr_workspace->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) - { - if (ptr_channel->buffer == buffer) - { - if (workspace) - *workspace = ptr_workspace; - if (channel) - *channel = ptr_channel; - return; - } - } - } - - /* no workspace or channel found */ -} - -char *slack_buffer_typing_bar_cb(const void *pointer, - void *data, - struct t_gui_bar_item *item, - struct t_gui_window *window, - struct t_gui_buffer *buffer, - struct t_hashtable *extra_info) -{ - struct t_slack_channel_typing *ptr_typing; - struct t_slack_workspace *workspace; - struct t_slack_channel *channel; - char notification[256]; - unsigned typecount; - - (void) pointer; - (void) data; - (void) item; - (void) window; - (void) extra_info; - - workspace = NULL; - channel = NULL; - - slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); - - if (!channel) - return strdup(""); - - typecount = 0; - - for (ptr_typing = channel->typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) - { - switch (++typecount) - { - case 1: - strcpy(notification, ptr_typing->name); - break; - case 2: - strcat(notification, ", "); - strcat(notification, ptr_typing->name); - break; - case 3: - default: - strcpy(notification, "Several people"); - break; - } - } - - if (typecount) - { - strcat(notification, NG_(" is typing...", - " are typing...", - typecount)); - return strdup(notification); - } - else - { - return strdup(""); - } -} - -int slack_buffer_nickcmp_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *nick1, - const char *nick2) -{ - struct t_slack_workspace *workspace; - - (void) data; - - if (pointer) - workspace = (struct t_slack_workspace *)pointer; - else - slack_buffer_get_workspace_and_channel(buffer, &workspace, NULL); - - if (workspace) - { - return weechat_strcasecmp(nick1, nick2); - } - else - { - return weechat_strcasecmp(nick1, nick2); - } -} - -int slack_buffer_close_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer) -{ - struct t_weechat_plugin *buffer_plugin = NULL; - struct t_slack_workspace *ptr_workspace = NULL; - struct t_slack_channel *ptr_channel = NULL; - - buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin"); - if (buffer_plugin == weechat_slack_plugin) - slack_buffer_get_workspace_and_channel(buffer, - &ptr_workspace, &ptr_channel); - - (void) pointer; - (void) data; - (void) buffer; - - if (ptr_workspace) - { - if (!ptr_workspace->disconnected) - { - //slack_command_quit_workspace(ptr_workspace, NULL); - slack_workspace_disconnect(ptr_workspace, 0); - } - - ptr_workspace->buffer = NULL; - } - - return WEECHAT_RC_OK; -} diff --git a/slack-buffer.h b/slack-buffer.h deleted file mode 100644 index 3f4bc66..0000000 --- a/slack-buffer.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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/. - -#ifndef _SLACK_BUFFER_H_ -#define _SLACK_BUFFER_H_ - -void slack_buffer_get_workspace_and_channel(struct t_gui_buffer *buffer, - struct t_slack_workspace **workspace, - struct t_slack_channel **channel); - -char *slack_buffer_typing_bar_cb(const void *pointer, - void *data, - struct t_gui_bar_item *item, - struct t_gui_window *window, - struct t_gui_buffer *buffer, - struct t_hashtable *extra_info); - -int slack_buffer_nickcmp_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *nick1, - const char *nick2); - -int slack_buffer_close_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer); - -#endif /*SLACK_BUFFER_H*/ diff --git a/slack-channel.c b/slack-channel.c deleted file mode 100644 index 33efb9e..0000000 --- a/slack-channel.c +++ /dev/null @@ -1,642 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-user.h" -#include "slack-channel.h" -#include "slack-input.h" -#include "slack-buffer.h" - -struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace, - const char *id) -{ - struct t_slack_channel *ptr_channel; - - if (!workspace || !id) - return NULL; - - for (ptr_channel = workspace->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) - { - if (weechat_strcasecmp(ptr_channel->id, id) == 0) - return ptr_channel; - } - - return NULL; -} - -struct t_gui_buffer *slack_channel_search_buffer(struct t_slack_workspace *workspace, - enum t_slack_channel_type type, - const char *name) -{ - struct t_hdata *hdata_buffer; - struct t_gui_buffer *ptr_buffer; - const char *ptr_type, *ptr_workspace_name, *ptr_channel_name; - - hdata_buffer = weechat_hdata_get("buffer"); - ptr_buffer = weechat_hdata_get_list(hdata_buffer, "gui_buffers"); - - while (ptr_buffer) - { - if (weechat_buffer_get_pointer(ptr_buffer, "plugin") == weechat_slack_plugin) - { - ptr_type = weechat_buffer_get_string(ptr_buffer, "localvar_type"); - ptr_workspace_name = weechat_buffer_get_string(ptr_buffer, - "localvar_server"); - ptr_channel_name = weechat_buffer_get_string(ptr_buffer, - "localvar_channel"); - if (ptr_type && ptr_type[0] - && ptr_workspace_name && ptr_workspace_name[0] - && ptr_channel_name && ptr_channel_name[0] - && ( (( (type == SLACK_CHANNEL_TYPE_CHANNEL) - || (type == SLACK_CHANNEL_TYPE_GROUP)) - && (strcmp(ptr_type, "channel") == 0)) - || (( (type == SLACK_CHANNEL_TYPE_MPIM) - || (type == SLACK_CHANNEL_TYPE_IM)) - && (strcmp(ptr_type, "private") == 0))) - && (strcmp(ptr_workspace_name, workspace->domain) == 0) - && (weechat_strcasecmp(ptr_channel_name, name) == 0)) - { - return ptr_buffer; - } - } - ptr_buffer = weechat_hdata_move(hdata_buffer, ptr_buffer, 1); - } - - return NULL; -} - -struct t_gui_buffer *slack_channel_create_buffer(struct t_slack_workspace *workspace, - enum t_slack_channel_type type, - const char *name) -{ - struct t_gui_buffer *ptr_buffer; - int buffer_created; - const char *short_name, *localvar_channel; - char buffer_name[256]; - - buffer_created = 0; - - snprintf(buffer_name, sizeof(buffer_name), - "%s.%s", workspace->domain, name); - - ptr_buffer = slack_channel_search_buffer(workspace, type, name); - if (ptr_buffer) - { - weechat_nicklist_remove_all(ptr_buffer); - } - else - { - ptr_buffer = weechat_buffer_new(buffer_name, - &slack_input_data_cb, NULL, NULL, - &slack_buffer_close_cb, NULL, NULL); - if (!ptr_buffer) - return NULL; - - buffer_created = 1; - } - - if (buffer_created) - { - if (!weechat_buffer_get_integer(ptr_buffer, "short_name_is_set")) - weechat_buffer_set(ptr_buffer, "short_name", name); - } - else - { - short_name = weechat_buffer_get_string (ptr_buffer, "short_name"); - localvar_channel = weechat_buffer_get_string (ptr_buffer, - "localvar_channel"); - - if (!short_name || - (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) - { - weechat_buffer_set (ptr_buffer, "short_name", name); - } - } - - weechat_buffer_set(ptr_buffer, "name", buffer_name); - weechat_buffer_set(ptr_buffer, "localvar_set_type", - (type == SLACK_CHANNEL_TYPE_IM || - type == SLACK_CHANNEL_TYPE_MPIM) ? "private" : "channel"); - weechat_buffer_set(ptr_buffer, "localvar_set_nick", workspace->nick); - weechat_buffer_set(ptr_buffer, "localvar_set_server", workspace->domain); - weechat_buffer_set(ptr_buffer, "localvar_set_channel", name); - - if (buffer_created) - { - (void) weechat_hook_signal_send ("logger_backlog", - WEECHAT_HOOK_SIGNAL_POINTER, - ptr_buffer); - weechat_buffer_set(ptr_buffer, "input_get_unknown_commands", "1"); - if (type != SLACK_CHANNEL_TYPE_IM) - { - weechat_buffer_set(ptr_buffer, "nicklist", "1"); - weechat_buffer_set(ptr_buffer, "nicklist_display_groups", "0"); - weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback", - &slack_buffer_nickcmp_cb); - weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback_pointer", - workspace); - } - - weechat_buffer_set(ptr_buffer, "highlight_words_add", - workspace->nick); - weechat_buffer_set(ptr_buffer, "highlight_tags_restrict", - "slack_message"); - } - - return ptr_buffer; -} - -void slack_channel_add_nicklist_groups(struct t_slack_workspace *workspace, - struct t_slack_channel *channel) -{ - struct t_gui_buffer *ptr_buffer; - char str_group[32]; - - if (channel && channel->type == SLACK_CHANNEL_TYPE_MPIM) - return; - if (channel && channel->type == SLACK_CHANNEL_TYPE_IM) - return; - - ptr_buffer = channel ? channel->buffer : workspace->buffer; - - snprintf(str_group, sizeof(str_group), "%03d|%s", - 000, "+"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, - "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", - 999, "..."); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, - "weechat.color.nicklist_group", 1); -} - -struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, - enum t_slack_channel_type type, - const char *id, const char *name) -{ - struct t_slack_channel *new_channel, *ptr_channel; - struct t_gui_buffer *ptr_buffer; - struct t_hook *typing_timer; - char buffer_name[SLACK_CHANNEL_NAME_MAX_LEN + 2]; - - if (!workspace || !id || !name || !name[0]) - return NULL; - - ptr_channel = slack_channel_search(workspace, id); - if (ptr_channel) - { - return ptr_channel; - } - - buffer_name[0] = '#'; - strncpy(&buffer_name[1], name, SLACK_CHANNEL_NAME_MAX_LEN + 1); - - ptr_buffer = slack_channel_create_buffer(workspace, type, buffer_name); - if (!ptr_buffer) - return NULL; - - if ((new_channel = malloc(sizeof(*new_channel))) == NULL) - return NULL; - - typing_timer = weechat_hook_timer(1 * 1000, 0, 0, - &slack_channel_typing_cb, - new_channel, NULL); - - new_channel->type = type; - new_channel->id = strdup(id); - new_channel->name = strdup(name); - new_channel->created = 0; - - new_channel->is_general = 0; - new_channel->name_normalized = NULL; - new_channel->is_shared = 0; - new_channel->is_org_shared = 0; - new_channel->is_member = 0; - - new_channel->topic.value = NULL; - new_channel->topic.creator = NULL; - new_channel->topic.last_set = 0; - new_channel->purpose.value = NULL; - new_channel->purpose.creator = NULL; - new_channel->purpose.last_set = 0; - new_channel->is_archived = 0; - - new_channel->creator = NULL; - new_channel->last_read = 0.0; - new_channel->unread_count = 0; - new_channel->unread_count_display = 0; - - new_channel->is_user_deleted = 0; - - new_channel->typing_hook_timer = typing_timer; - new_channel->members_speaking[0] = NULL; - new_channel->members_speaking[1] = 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 = workspace->last_channel; - new_channel->next_channel = NULL; - if (workspace->last_channel) - (workspace->last_channel)->next_channel = new_channel; - else - workspace->channels = new_channel; - workspace->last_channel = new_channel; - - return new_channel; -} - -void slack_channel_member_speaking_add_to_list(struct t_slack_channel *channel, - 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(); - - /* remove item if it was already in list */ - ptr_item = weechat_list_casesearch(channel->members_speaking[highlight], nick); - if (ptr_item) - weechat_list_remove(channel->members_speaking[highlight], ptr_item); - - /* add nick in list */ - weechat_list_add(channel->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]); - if (size > SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT) - { - to_remove = size - SLACK_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)); - } - } -} - -void slack_channel_member_speaking_add(struct t_slack_channel *channel, - const char *nick, int highlight) -{ - if (highlight < 0) - highlight = 0; - if (highlight > 1) - highlight = 1; - if (highlight) - slack_channel_member_speaking_add_to_list(channel, nick, 1); - - slack_channel_member_speaking_add_to_list(channel, nick, 0); -} - -void slack_channel_member_speaking_rename(struct t_slack_channel *channel, - 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]) - { - ptr_item = weechat_list_search(channel->members_speaking[i], old_nick); - if (ptr_item) - weechat_list_set(ptr_item, new_nick); - } - } -} - -void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - const char *nick) -{ - struct t_weelist_item *ptr_item; - int i, j, list_size; - - (void) workspace; - - for (i = 0; i < 2; i++) - { - if (channel->members_speaking[i]) - { - list_size = weechat_list_size(channel->members_speaking[i]); - for (j = 0; j < list_size; j++) - { - ptr_item = weechat_list_get (channel->members_speaking[i], j); - if (ptr_item && (strcasecmp(weechat_list_string(ptr_item), nick) == 0)) - weechat_list_set(ptr_item, nick); - } - } - } -} - -void slack_channel_typing_free(struct t_slack_channel *channel, - struct t_slack_channel_typing *typing) -{ - struct t_slack_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 slack_channel_typing_free_all(struct t_slack_channel *channel) -{ - while (channel->typings) - slack_channel_typing_free(channel, channel->typings); -} - -int slack_channel_typing_cb(const void *pointer, - void *data, - int remaining_calls) -{ - struct t_slack_channel_typing *ptr_typing, *next_typing; - struct t_slack_channel *channel; - const char *localvar; - unsigned typecount; - time_t now; - - (void) data; - (void) remaining_calls; - - if (!pointer) - return WEECHAT_RC_ERROR; - - channel = (struct t_slack_channel *)pointer; - - now = time(NULL); - - typecount = 0; - - for (ptr_typing = channel->typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) - { - next_typing = ptr_typing->next_typing; - - while (ptr_typing && now - ptr_typing->ts > 5) - { - slack_channel_typing_free(channel, ptr_typing); - ptr_typing = next_typing; - if (ptr_typing) - next_typing = ptr_typing->next_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", - typecount > 0 ? "1" : "0"); - weechat_bar_item_update("slack_typing"); - - return WEECHAT_RC_OK; -} - -struct t_slack_channel_typing *slack_channel_typing_search( - struct t_slack_channel *channel, - const char *id) -{ - struct t_slack_channel_typing *ptr_typing; - - if (!channel || !id) - return NULL; - - for (ptr_typing = channel->typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) - { - if (weechat_strcasecmp(ptr_typing->id, id) == 0) - return ptr_typing; - } - - return NULL; -} - -void slack_channel_add_typing(struct t_slack_channel *channel, - struct t_slack_user *user) -{ - struct t_slack_channel_typing *new_typing; - - new_typing = slack_channel_typing_search(channel, user->id); - if (!new_typing) - { - new_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; - } - new_typing->ts = time(NULL); - - slack_channel_typing_cb(channel, NULL, 0); -} - -void slack_channel_member_free(struct t_slack_channel *channel, - struct t_slack_channel_member *member) -{ - struct t_slack_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); - - free(member); - - channel->members = new_members; -} - -void slack_channel_member_free_all(struct t_slack_channel *channel) -{ - while (channel->members) - slack_channel_member_free(channel, channel->members); -} - -void slack_channel_free(struct t_slack_workspace *workspace, - struct t_slack_channel *channel) -{ - struct t_slack_channel *new_channels; - - if (!workspace || !channel) - return; - - /* remove channel from channels list */ - if (workspace->last_channel == channel) - workspace->last_channel = channel->prev_channel; - if (channel->prev_channel) - { - (channel->prev_channel)->next_channel = channel->next_channel; - new_channels = workspace->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); - - /* free linked lists */ - slack_channel_typing_free_all(channel); - slack_channel_member_free_all(channel); - - /* free channel data */ - if (channel->id) - free(channel->id); - if (channel->name) - free(channel->name); - if (channel->name_normalized) - free(channel->name_normalized); - if (channel->topic.value) - free(channel->topic.value); - if (channel->topic.creator) - free(channel->topic.creator); - if (channel->purpose.value) - free(channel->purpose.value); - if (channel->purpose.creator) - free(channel->purpose.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); - - workspace->channels = new_channels; -} - -void slack_channel_free_all(struct t_slack_workspace *workspace) -{ - while (workspace->channels) - slack_channel_free(workspace, workspace->channels); -} - -void slack_channel_update_topic(struct t_slack_channel *channel, - 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); - else - weechat_buffer_set(channel->buffer, "title", ""); -} - -void slack_channel_update_purpose(struct t_slack_channel *channel, - const char* purpose, - const char* creator, - int last_set) -{ - if (channel->purpose.value) - free(channel->purpose.value); - if (channel->purpose.creator) - free(channel->purpose.creator); - channel->purpose.value = (purpose) ? strdup(purpose) : NULL; - channel->purpose.creator = (creator) ? strdup(creator) : NULL; - channel->purpose.last_set = last_set; -} - -struct t_slack_channel_member *slack_channel_add_member( - struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - const char *id) -{ - struct t_slack_channel_member *member; - struct t_slack_user *user; - - member = malloc(sizeof(struct t_slack_channel_member)); - member->id = strdup(id); - - 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; - - user = slack_user_search(workspace, id); - if (user) - slack_user_nicklist_add(workspace, channel, user); - - return member; -} diff --git a/slack-channel.h b/slack-channel.h deleted file mode 100644 index e5f507e..0000000 --- a/slack-channel.h +++ /dev/null @@ -1,147 +0,0 @@ -// 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/. - -#ifndef _SLACK_CHANNEL_H_ -#define _SLACK_CHANNEL_H_ - -#define SLACK_CHANNEL_MEMBERS_SPEAKING_LIMIT 128 - -#define SLACK_CHANNEL_NAME_MAX_LEN 22 - -enum t_slack_channel_type -{ - SLACK_CHANNEL_TYPE_CHANNEL, - SLACK_CHANNEL_TYPE_GROUP, - SLACK_CHANNEL_TYPE_MPIM, - SLACK_CHANNEL_TYPE_IM, -}; - -struct t_slack_channel_typing -{ - char *id; - char *name; - time_t ts; - - struct t_slack_channel_typing *prev_typing; - struct t_slack_channel_typing *next_typing; -}; - -struct t_slack_channel_member -{ - char *id; - - struct t_slack_channel_member *prev_member; - struct t_slack_channel_member *next_member; -}; - -struct t_slack_channel_topic -{ - char *value; - char *creator; - time_t last_set; -}; - -struct t_slack_channel_purpose -{ - char *value; - char *creator; - time_t last_set; -}; - -struct t_slack_channel -{ - enum t_slack_channel_type type; - char *id; - char *name; - time_t created; - - /* channel */ - int is_general; - char *name_normalized; - int is_shared; - int is_org_shared; - int is_member; - - /* group */ - struct t_slack_channel_topic topic; - struct t_slack_channel_purpose purpose; - int is_archived; - - /* mpim */ - char *creator; - double last_read; - int unread_count; - int unread_count_display; - - /* im */ - int is_user_deleted; - - struct t_hook *typing_hook_timer; - struct t_weelist *members_speaking[2]; - struct t_slack_channel_typing *typings; - struct t_slack_channel_typing *last_typing; - struct t_slack_channel_member *members; - struct t_slack_channel_member *last_member; - struct t_gui_buffer *buffer; - char *buffer_as_string; - - struct t_slack_channel *prev_channel; - struct t_slack_channel *next_channel; -}; - -struct t_slack_channel *slack_channel_search(struct t_slack_workspace *workspace, - const char *id); - -void slack_channel_add_nicklist_groups(struct t_slack_workspace *workspace, - struct t_slack_channel *channel); - -struct t_slack_channel *slack_channel_new(struct t_slack_workspace *workspace, - enum t_slack_channel_type type, - const char *id, const char *name); - -void slack_channel_member_speaking_add(struct t_slack_channel *channel, - const char *nick, int highlight); - -void slack_channel_member_speaking_rename(struct t_slack_channel *channel, - const char *old_nick, - const char *new_nick); - -void slack_channel_member_speaking_rename_if_present(struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - const char *nick); - -void slack_channel_typing_free(struct t_slack_channel *channel, - struct t_slack_channel_typing *typing); - -void slack_channel_typing_free_all(struct t_slack_channel *channel); - -int slack_channel_typing_cb(const void *pointer, - void *data, - int remaining_calls); - -struct t_slack_channel_typing *slack_channel_typing_search( - struct t_slack_channel *channel, - const char *id); - -void slack_channel_add_typing(struct t_slack_channel *channel, - struct t_slack_user *user); - -void slack_channel_free_all(struct t_slack_workspace *workspace); - -void slack_channel_update_topic(struct t_slack_channel *channel, - const char* title, - const char* creator, - int last_set); - -void slack_channel_update_purpose(struct t_slack_channel *channel, - const char* purpose, - const char* creator, - int last_set); - -struct t_slack_channel_member *slack_channel_add_member( - struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - const char *id); - -#endif /*SLACK_CHANNEL_H*/ diff --git a/slack-completion.c b/slack-completion.c deleted file mode 100644 index c8c6e80..0000000 --- a/slack-completion.c +++ /dev/null @@ -1,162 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-config.h" -#include "slack-emoji.h" -#include "slack-workspace.h" -#include "slack-channel.h" -#include "slack-user.h" -#include "slack-buffer.h" -#include "slack-completion.h" - -void slack_completion_channel_nicks_add_speakers(struct t_gui_completion *completion, - struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - int highlight) -{ - struct t_slack_user *user; - const char *member; - int list_size, i; - - if (channel->members_speaking[highlight]) - { - list_size = weechat_list_size(channel->members_speaking[highlight]); - for (i = 0; i < list_size; i++) - { - member = weechat_list_string ( - weechat_list_get(channel->members_speaking[highlight], i)); - if (member) - { - user = slack_user_search(workspace, member); - if (user) - weechat_hook_completion_list_add(completion, - user->profile.display_name, - 1, WEECHAT_LIST_POS_BEGINNING); - } - } - } -} - -int slack_completion_channel_nicks_cb(const void *pointer, void *data, - const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion) -{ - struct t_slack_workspace *ptr_workspace; - struct t_slack_channel *ptr_channel; - struct t_slack_channel_member *ptr_member; - struct t_slack_user *ptr_user; - - - (void) pointer; - (void) data; - (void) completion_item; - - ptr_workspace = NULL; - ptr_channel = NULL; - slack_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel); - - if (ptr_channel) - { - switch (ptr_channel->type) - { - case SLACK_CHANNEL_TYPE_CHANNEL: - case SLACK_CHANNEL_TYPE_GROUP: - case SLACK_CHANNEL_TYPE_MPIM: - case SLACK_CHANNEL_TYPE_IM: - for (ptr_member = ptr_channel->members; ptr_member; - ptr_member = ptr_member->next_member) - { - ptr_user = slack_user_search(ptr_workspace, ptr_member->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(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS) - { - slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 0); - } - /* add members whose make highlights on me recently on this channel */ - if (weechat_config_integer(slack_config_look_nick_completion_smart) == SLACK_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS) - { - slack_completion_channel_nicks_add_speakers(completion, ptr_workspace, ptr_channel, 1); - } - /* add self member at the end */ - weechat_hook_completion_list_add(completion, - ptr_workspace->nick, - 1, WEECHAT_LIST_POS_END); - break; - } - } - - return WEECHAT_RC_OK; -} - -int slack_completion_workspaces_cb(const void *pointer, void *data, - const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion) -{ - struct t_slack_workspace *ptr_workspace; - - - (void) pointer; - (void) data; - (void) completion_item; - (void) buffer; - - for (ptr_workspace = slack_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) - { - weechat_hook_completion_list_add(completion, ptr_workspace->domain, - 0, WEECHAT_LIST_POS_SORT); - } - - return WEECHAT_RC_OK; -} - -void slack_completion_init() -{ - struct t_config_option *option; - const char *default_template; - - - weechat_hook_completion ("nick", - N_("nicks of current Slack channel"), - &slack_completion_channel_nicks_cb, - NULL, NULL); - - weechat_hook_completion("slack_workspace", - N_("slack workspaces"), - &slack_completion_workspaces_cb, - NULL, NULL); - - weechat_hook_completion("slack_emoji", - N_("slack emoji"), - &slack_emoji_complete_by_name_cb, - NULL, NULL); - - option = weechat_config_get("weechat.completion.default_template"); - default_template = weechat_config_string(option); - if (!weechat_strcasestr(default_template, "%(slack_emoji)")) - { - size_t length = snprintf(NULL, 0, "%s|%s", - default_template, - "%(slack_emoji)") + 1; - char *new_template = malloc(length); - snprintf(new_template, length, "%s|%s", - default_template, - "%(slack_emoji)"); - weechat_config_option_set(option, new_template, 1); - free(new_template); - } -} diff --git a/slack-completion.h b/slack-completion.h deleted file mode 100644 index 5ae559f..0000000 --- a/slack-completion.h +++ /dev/null @@ -1,10 +0,0 @@ -// 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/. - -#ifndef _SLACK_COMPLETION_H_ -#define _SLACK_COMPLETION_H_ - -void slack_completion_init(); - -#endif /*SLACK_COMPLETION_H*/ diff --git a/slack-emoji.c b/slack-emoji.c deleted file mode 100644 index 3ec6802..0000000 --- a/slack-emoji.c +++ /dev/null @@ -1,289 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-channel.h" -#include "slack-buffer.h" -#include "slack-emoji.h" - -#include "slack-emoji.inc" - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -static int emoji_byname_cmp(const void *p1, const void *p2) -{ - return strcasecmp(((struct t_slack_emoji_by_name *)p1)->name, - ((struct t_slack_emoji_by_name *)p2)->name); -} - -static int emoji_bytext_cmp(const void *p1, const void *p2) -{ - return strcasecmp(((struct t_slack_emoji_by_text *)p1)->text, - ((struct t_slack_emoji_by_text *)p2)->text); -} - -static size_t modified_wagner_fischer(const char *src, const char *targ) -{ - size_t len = strlen(targ) + 1; - size_t above[len], below[len]; - for (size_t *k = above, c = 0; k < above + len; ++k, ++c) *k = c; - - const char *src_at = src, *targ_at; - for (size_t j = 1; j < strlen(src) + 1; ++j) - { - *below = j; - targ_at = targ; - for (size_t *d = above, *a = above + 1, *l = below, *c = below + 1; - c < below + len; ++d, ++a, ++l, ++c) - { - /* |-------------replace-----------| |isrt| |delt| */ - *c = MIN( *src_at == *targ_at ? *d : *d + 1, MIN( *a + 0, *l + 1 ) ); - ++targ_at; - } - for (size_t *a = above, *b = below; a < above + len; ++a, ++b) *a = *b; - ++src_at; - } - - return above[len-1]; -} - -static size_t longest_common_substring(const char *X, const char *Y) -{ - const size_t n = strlen(X); - const size_t m = strlen(Y); - size_t i, j, result = 0; - size_t **L; - - L = malloc(sizeof(size_t *) * (n + 1)); - L[0] = malloc(sizeof(size_t) * (m + 1) * (n + 1)); - - for (i = 0; i <= n; i++) - L[i] = (*L + (m + 1) * i); - - /* Following steps build L[n+1][m+1] in bottom up fashion. Note - that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */ - for (i = 0; i <= n; i++) - { - for (j = 0; j <= m; j++) - { - if (i == 0 || j == 0) - { - L[i][j] = 0; - } - else if (X[i-1] == Y[j-1]) - { - L[i][j] = L[i - 1][j - 1] + 1; - if (result < L[i][j]) - result = L[i][j]; - } - else - { - L[i][j] = 0; - } - } - } - - /* result now contains length of LCS for X[0..n-1] and Y[0..m-1] */ - free(L[0]); - free(L); - return result; -} - -int slack_emoji_complete_by_name_cb(const void *pointer, void *data, - const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion) -{ - struct t_slack_workspace_emoji *ptr_emoji; - struct t_slack_workspace *workspace; - struct t_slack_channel *channel; - - (void) pointer; - (void) data; - (void) completion_item; - - workspace = NULL; - slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); - - size_t i, emoji_count = sizeof(slack_emoji_by_name) - / sizeof(struct t_slack_emoji_by_name); - - if (workspace) - { - for (ptr_emoji = workspace->emoji; ptr_emoji; - ptr_emoji = ptr_emoji->next_emoji) - weechat_hook_completion_list_add(completion, - ptr_emoji->name, - 0, WEECHAT_LIST_POS_END); - - for (i = 0; i < emoji_count; i++) - weechat_hook_completion_list_add(completion, - slack_emoji_by_name[i].name, - 0, WEECHAT_LIST_POS_END); - } - - return WEECHAT_RC_OK; -} - -int slack_emoji_input_complete_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *command) -{ - struct t_slack_emoji_by_name *closest_emoji; - int input_pos, input_length, start, end; - char *new_string, *word, *new_pos; - const char *input_string; - - (void) pointer; - (void) data; - (void) command; - - input_string = weechat_buffer_get_string(buffer, "input"); - input_length = strlen(input_string); - input_pos = weechat_buffer_get_integer(buffer, "input_pos"); - for (start = input_pos; start > 0 && input_string[start] != ':'; start--) - if (input_string[start] == ' ') { break; } - for (end = input_pos; end < input_length && input_string[end] != ' '; end++) - if (input_string[end] == ':') { end++; break; } - - if (input_string[start] != ':') - return WEECHAT_RC_OK; - else - word = strndup(&input_string[start], end - start); - - size_t emoji_count = sizeof(slack_emoji_by_name) - / sizeof(struct t_slack_emoji_by_name); - closest_emoji = malloc(sizeof(slack_emoji_by_name)); - memcpy(closest_emoji, slack_emoji_by_name, - sizeof(slack_emoji_by_name)); - - int edit_dist_cmp(const void *p1, const void *p2) - { - const struct t_slack_emoji_by_name *e1 = p1; - const struct t_slack_emoji_by_name *e2 = p2; - size_t d1 = modified_wagner_fischer(e1->name, word); - size_t d2 = modified_wagner_fischer(e2->name, word); - if (d1 == d2) - { - size_t l1 = longest_common_substring(e1->name, word); - size_t l2 = longest_common_substring(e2->name, word); - return (l1 < l2) - (l1 > l2); - } - return (d1 > d2) - (d1 < d2); - }; - qsort(closest_emoji, emoji_count, - sizeof(struct t_slack_emoji_by_name), - edit_dist_cmp); - - size_t new_length = snprintf(NULL, 0, "%.*s%s%s", - start, input_string, - closest_emoji[0].name, - &input_string[end]) + 1; - new_string = malloc(new_length); - snprintf(new_string, new_length, "%.*s%s%s", - start, input_string, - closest_emoji[0].name, - &input_string[end]); - weechat_buffer_set(buffer, "input", new_string); - - size_t new_pos_len = snprintf(NULL, 0, "%lu", - (unsigned long)(start + - strlen(closest_emoji[0].name) - 1)); - new_pos = malloc(new_pos_len); - snprintf(new_pos, new_pos_len, "%lu", - (unsigned long)(start + - strlen(closest_emoji[0].name) - 1)); - weechat_buffer_set(buffer, "input_pos", new_pos); - - free(new_pos); - free(new_string); - free(closest_emoji); - free(word); - return WEECHAT_RC_OK_EAT; -} - -int slack_emoji_input_replace_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *command) -{ - (void) pointer; - (void) data; - (void) buffer; - (void) command; - - /* TBI */ - - return WEECHAT_RC_OK; -} - -const char *slack_emoji_get_unicode_by_name(const char *name) -{ - struct t_slack_emoji_by_name *result; - struct t_slack_emoji_by_name key; - key.name = name; - - size_t emoji_count = sizeof(slack_emoji_by_name) - / sizeof(struct t_slack_emoji_by_name); - result = (struct t_slack_emoji_by_name *)bsearch( - &key, slack_emoji_by_name, emoji_count, - sizeof(struct t_slack_emoji_by_name), - emoji_byname_cmp); - - return result->unicode; -} - -const char *slack_emoji_get_unicode_by_text(const char *text) -{ - struct t_slack_emoji_by_text *result; - struct t_slack_emoji_by_text key; - key.text = text; - - size_t emoji_count = sizeof(slack_emoji_by_text) - / sizeof(struct t_slack_emoji_by_text); - result = (struct t_slack_emoji_by_text *)bsearch( - &key, slack_emoji_by_text, emoji_count, - sizeof(struct t_slack_emoji_by_text), - emoji_bytext_cmp); - - return result->unicode; -} - -const char *slack_emoji_get_text_by_name(const char *name) -{ - struct t_slack_emoji_by_name *result; - struct t_slack_emoji_by_name key; - key.name = name; - - size_t emoji_count = sizeof(slack_emoji_by_name) - / sizeof(struct t_slack_emoji_by_name); - result = (struct t_slack_emoji_by_name *)bsearch( - &key, slack_emoji_by_name, emoji_count, - sizeof(struct t_slack_emoji_by_name), - emoji_byname_cmp); - - return result->text_to; -} - -const char *slack_emoji_get_name_by_text(const char *text) -{ - struct t_slack_emoji_by_text *result; - struct t_slack_emoji_by_text key; - key.text = text; - - size_t emoji_count = sizeof(slack_emoji_by_text) - / sizeof(struct t_slack_emoji_by_text); - result = (struct t_slack_emoji_by_text *)bsearch( - &key, slack_emoji_by_text, emoji_count, - sizeof(struct t_slack_emoji_by_text), - emoji_bytext_cmp); - - return result->name_to; -} diff --git a/slack-emoji.h b/slack-emoji.h deleted file mode 100644 index 9fc688d..0000000 --- a/slack-emoji.h +++ /dev/null @@ -1,29 +0,0 @@ -// 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/. - -#ifndef _SLACK_EMOJI_H_ -#define _SLACK_EMOJI_H_ - -int slack_emoji_complete_by_name_cb(const void *pointer, void *data, - const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion); - -int slack_emoji_input_complete_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *command); - -int slack_emoji_input_replace_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *command); - -const char *slack_emoji_get_unicode_by_name(const char *name); - -const char *slack_emoji_get_unicode_by_text(const char *text); - -const char *slack_emoji_get_text_by_name(const char *name); - -const char *slack_emoji_get_name_by_text(const char *text); - -#endif /*SLACK_EMOJI_H*/ diff --git a/slack-emoji.inc b/slack-emoji.inc deleted file mode 100644 index 23f0588..0000000 --- a/slack-emoji.inc +++ /dev/null @@ -1,1702 +0,0 @@ - -// 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 - -#define MAX_TEXTS 7 -#define MAX_NAMES 4 - -struct t_slack_emoji_by_name { - const char *name; - const char *unicode; - const char *text_to; - const char *text_from[MAX_TEXTS]; -}; - -struct t_slack_emoji_by_text { - const char *text; - const char *unicode; - const char *name_to; - const char *name_from[MAX_NAMES]; -}; - -static struct t_slack_emoji_by_name slack_emoji_by_name[] = -{ { ":+1:", "\u1f44D", NULL, {NULL} } -, { ":-1:", "\u1f44E", NULL, {NULL} } -, { ":100:", "\u1f4aF", NULL, {NULL} } -, { ":1234:", "\u1f522", NULL, {NULL} } -, { ":8ball:", "\u1f3b1", NULL, {NULL} } -, { ":a:", "\u1f170\ufe0f", NULL, {NULL} } -, { ":ab:", "\u1f18E", NULL, {NULL} } -, { ":abc:", "\u1f524", NULL, {NULL} } -, { ":abcd:", "\u1f521", NULL, {NULL} } -, { ":accept:", "\u1f251", NULL, {NULL} } -, { ":admission_tickets:", "\u1f39F\ufe0f", NULL, {NULL} } -, { ":adult:", "\u1f9d1", NULL, {NULL} } -, { ":aerial_tramway:", "\u1f6a1", NULL, {NULL} } -, { ":airplane:", "\u2708\ufe0f", NULL, {NULL} } -, { ":airplane_arriving:", "\u1f6eC", NULL, {NULL} } -, { ":airplane_departure:", "\u1f6eB", NULL, {NULL} } -, { ":alarm_clock:", "\u23f0", NULL, {NULL} } -, { ":alembic:", "\u2697\ufe0f", NULL, {NULL} } -, { ":alien:", "\u1f47D", NULL, {NULL} } -, { ":ambulance:", "\u1f691", NULL, {NULL} } -, { ":amphora:", "\u1f3fA", NULL, {NULL} } -, { ":anchor:", "\u2693", NULL, {NULL} } -, { ":angel:", "\u1f47C", NULL, {NULL} } -, { ":anger:", "\u1f4a2", NULL, {NULL} } -, { ":angry:", "\u1f620", NULL, {">:(", ">:-(", NULL} } -, { ":anguished:", "\u1f627", NULL, {"D:", NULL} } -, { ":ant:", "\u1f41C", NULL, {NULL} } -, { ":apple:", "\u1f34E", NULL, {NULL} } -, { ":aquarius:", "\u2652", NULL, {NULL} } -, { ":aries:", "\u2648", NULL, {NULL} } -, { ":arrow_backward:", "\u25c0\ufe0f", NULL, {NULL} } -, { ":arrow_double_down:", "\u23ec", NULL, {NULL} } -, { ":arrow_double_up:", "\u23eb", NULL, {NULL} } -, { ":arrow_down:", "\u2b07\ufe0f", NULL, {NULL} } -, { ":arrow_down_small:", "\u1f53D", NULL, {NULL} } -, { ":arrow_forward:", "\u25b6\ufe0f", NULL, {NULL} } -, { ":arrow_heading_down:", "\u2935\ufe0f", NULL, {NULL} } -, { ":arrow_heading_up:", "\u2934\ufe0f", NULL, {NULL} } -, { ":arrow_left:", "\u2b05\ufe0f", NULL, {NULL} } -, { ":arrow_lower_left:", "\u2199\ufe0f", NULL, {NULL} } -, { ":arrow_lower_right:", "\u2198\ufe0f", NULL, {NULL} } -, { ":arrow_right:", "\u27a1\ufe0f", NULL, {NULL} } -, { ":arrow_right_hook:", "\u21aa\ufe0f", NULL, {NULL} } -, { ":arrow_up:", "\u2b06\ufe0f", NULL, {NULL} } -, { ":arrow_up_down:", "\u2195\ufe0f", NULL, {NULL} } -, { ":arrow_up_small:", "\u1f53C", NULL, {NULL} } -, { ":arrow_upper_left:", "\u2196\ufe0f", NULL, {NULL} } -, { ":arrow_upper_right:", "\u2197\ufe0f", NULL, {NULL} } -, { ":arrows_clockwise:", "\u1f503", NULL, {NULL} } -, { ":arrows_counterclockwise:", "\u1f504", NULL, {NULL} } -, { ":art:", "\u1f3a8", NULL, {NULL} } -, { ":articulated_lorry:", "\u1f69B", NULL, {NULL} } -, { ":astonished:", "\u1f632", NULL, {NULL} } -, { ":athletic_shoe:", "\u1f45F", NULL, {NULL} } -, { ":atm:", "\u1f3e7", NULL, {NULL} } -, { ":atom_symbol:", "\u269b\ufe0f", NULL, {NULL} } -, { ":avocado:", "\u1f951", NULL, {NULL} } -, { ":b:", "\u1f171\ufe0f", NULL, {NULL} } -, { ":baby:", "\u1f476", NULL, {NULL} } -, { ":baby_bottle:", "\u1f37C", NULL, {NULL} } -, { ":baby_chick:", "\u1f424", NULL, {NULL} } -, { ":baby_symbol:", "\u1f6bC", NULL, {NULL} } -, { ":back:", "\u1f519", NULL, {NULL} } -, { ":bacon:", "\u1f953", NULL, {NULL} } -, { ":badminton_racquet_and_shuttlecock:", "\u1f3f8", NULL, {NULL} } -, { ":baggage_claim:", "\u1f6c4", NULL, {NULL} } -, { ":baguette_bread:", "\u1f956", NULL, {NULL} } -, { ":balloon:", "\u1f388", NULL, {NULL} } -, { ":ballot_box_with_ballot:", "\u1f5f3\ufe0f", NULL, {NULL} } -, { ":ballot_box_with_check:", "\u2611\ufe0f", NULL, {NULL} } -, { ":bamboo:", "\u1f38D", NULL, {NULL} } -, { ":banana:", "\u1f34C", NULL, {NULL} } -, { ":bangbang:", "\u203c\ufe0f", NULL, {NULL} } -, { ":bank:", "\u1f3e6", NULL, {NULL} } -, { ":bar_chart:", "\u1f4cA", NULL, {NULL} } -, { ":barber:", "\u1f488", NULL, {NULL} } -, { ":barely_sunny:", "\u1f325\ufe0f", NULL, {NULL} } -, { ":baseball:", "\u26be", NULL, {NULL} } -, { ":basketball:", "\u1f3c0", NULL, {NULL} } -, { ":bat:", "\u1f987", NULL, {NULL} } -, { ":bath:", "\u1f6c0", NULL, {NULL} } -, { ":bathtub:", "\u1f6c1", NULL, {NULL} } -, { ":battery:", "\u1f50B", NULL, {NULL} } -, { ":beach_with_umbrella:", "\u1f3d6\ufe0f", NULL, {NULL} } -, { ":bear:", "\u1f43B", NULL, {NULL} } -, { ":bearded_person:", "\u1f9d4", NULL, {NULL} } -, { ":bed:", "\u1f6cF\ufe0f", NULL, {NULL} } -, { ":bee:", "\u1f41D", NULL, {NULL} } -, { ":beer:", "\u1f37A", NULL, {NULL} } -, { ":beers:", "\u1f37B", NULL, {NULL} } -, { ":beetle:", "\u1f41E", NULL, {NULL} } -, { ":beginner:", "\u1f530", NULL, {NULL} } -, { ":bell:", "\u1f514", NULL, {NULL} } -, { ":bellhop_bell:", "\u1f6cE\ufe0f", NULL, {NULL} } -, { ":bento:", "\u1f371", NULL, {NULL} } -, { ":bicyclist:", "\u1f6b4", NULL, {NULL} } -, { ":bike:", "\u1f6b2", NULL, {NULL} } -, { ":bikini:", "\u1f459", NULL, {NULL} } -, { ":billed_cap:", "\u1f9e2", NULL, {NULL} } -, { ":biohazard_sign:", "\u2623\ufe0f", NULL, {NULL} } -, { ":bird:", "\u1f426", NULL, {NULL} } -, { ":birthday:", "\u1f382", NULL, {NULL} } -, { ":black_circle:", "\u26ab", NULL, {NULL} } -, { ":black_circle_for_record:", "\u23fa\ufe0f", NULL, {NULL} } -, { ":black_heart:", "\u1f5a4", NULL, {NULL} } -, { ":black_joker:", "\u1f0cF", NULL, {NULL} } -, { ":black_large_square:", "\u2b1b", NULL, {NULL} } -, { ":black_left_pointing_double_triangle_with_vertical_bar:", "\u23ee\ufe0f", NULL, {NULL} } -, { ":black_medium_small_square:", "\u25fe", NULL, {NULL} } -, { ":black_medium_square:", "\u25fc\ufe0f", NULL, {NULL} } -, { ":black_nib:", "\u2712\ufe0f", NULL, {NULL} } -, { ":black_right_pointing_double_triangle_with_vertical_bar:", "\u23ed\ufe0f", NULL, {NULL} } -, { ":black_right_pointing_triangle_with_double_vertical_bar:", "\u23ef\ufe0f", NULL, {NULL} } -, { ":black_small_square:", "\u25aa\ufe0f", NULL, {NULL} } -, { ":black_square_button:", "\u1f532", NULL, {NULL} } -, { ":black_square_for_stop:", "\u23f9\ufe0f", NULL, {NULL} } -, { ":blond-haired-man:", "\u1f471\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":blond-haired-woman:", "\u1f471\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":blossom:", "\u1f33C", NULL, {NULL} } -, { ":blowfish:", "\u1f421", NULL, {NULL} } -, { ":blue_book:", "\u1f4d8", NULL, {NULL} } -, { ":blue_car:", "\u1f699", NULL, {NULL} } -, { ":blue_heart:", "\u1f499", "<3", {NULL} } -, { ":blush:", "\u1f60A", ":)", {NULL} } -, { ":boar:", "\u1f417", NULL, {NULL} } -, { ":boat:", "\u26f5", NULL, {NULL} } -, { ":bomb:", "\u1f4a3", NULL, {NULL} } -, { ":book:", "\u1f4d6", NULL, {NULL} } -, { ":bookmark:", "\u1f516", NULL, {NULL} } -, { ":bookmark_tabs:", "\u1f4d1", NULL, {NULL} } -, { ":books:", "\u1f4dA", NULL, {NULL} } -, { ":boom:", "\u1f4a5", NULL, {NULL} } -, { ":boot:", "\u1f462", NULL, {NULL} } -, { ":bouquet:", "\u1f490", NULL, {NULL} } -, { ":bow:", "\u1f647", NULL, {NULL} } -, { ":bow_and_arrow:", "\u1f3f9", NULL, {NULL} } -, { ":bowl_with_spoon:", "\u1f963", NULL, {NULL} } -, { ":bowling:", "\u1f3b3", NULL, {NULL} } -, { ":boxing_glove:", "\u1f94A", NULL, {NULL} } -, { ":boy:", "\u1f466", NULL, {NULL} } -, { ":brain:", "\u1f9e0", NULL, {NULL} } -, { ":bread:", "\u1f35E", NULL, {NULL} } -, { ":breast-feeding:", "\u1f931", NULL, {NULL} } -, { ":bride_with_veil:", "\u1f470", NULL, {NULL} } -, { ":bridge_at_night:", "\u1f309", NULL, {NULL} } -, { ":briefcase:", "\u1f4bC", NULL, {NULL} } -, { ":broccoli:", "\u1f966", NULL, {NULL} } -, { ":broken_heart:", "\u1f494", "", ":->", NULL} } -, { ":leaves:", "\u1f343", NULL, {NULL} } -, { ":ledger:", "\u1f4d2", NULL, {NULL} } -, { ":left-facing_fist:", "\u1f91B", NULL, {NULL} } -, { ":left_luggage:", "\u1f6c5", NULL, {NULL} } -, { ":left_right_arrow:", "\u2194\ufe0f", NULL, {NULL} } -, { ":left_speech_bubble:", "\u1f5e8\ufe0f", NULL, {NULL} } -, { ":leftwards_arrow_with_hook:", "\u21a9\ufe0f", NULL, {NULL} } -, { ":lemon:", "\u1f34B", NULL, {NULL} } -, { ":leo:", "\u264c", NULL, {NULL} } -, { ":leopard:", "\u1f406", NULL, {NULL} } -, { ":level_slider:", "\u1f39A\ufe0f", NULL, {NULL} } -, { ":libra:", "\u264e", NULL, {NULL} } -, { ":light_rail:", "\u1f688", NULL, {NULL} } -, { ":lightning:", "\u1f329\ufe0f", NULL, {NULL} } -, { ":lightning_cloud:", "\u1f329\ufe0f", NULL, {NULL} } -, { ":link:", "\u1f517", NULL, {NULL} } -, { ":linked_paperclips:", "\u1f587\ufe0f", NULL, {NULL} } -, { ":lion_face:", "\u1f981", NULL, {NULL} } -, { ":lips:", "\u1f444", NULL, {NULL} } -, { ":lipstick:", "\u1f484", NULL, {NULL} } -, { ":lizard:", "\u1f98E", NULL, {NULL} } -, { ":lock:", "\u1f512", NULL, {NULL} } -, { ":lock_with_ink_pen:", "\u1f50F", NULL, {NULL} } -, { ":lollipop:", "\u1f36D", NULL, {NULL} } -, { ":loop:", "\u27bf", NULL, {NULL} } -, { ":loud_sound:", "\u1f50A", NULL, {NULL} } -, { ":loudspeaker:", "\u1f4e2", NULL, {NULL} } -, { ":love_hotel:", "\u1f3e9", NULL, {NULL} } -, { ":love_letter:", "\u1f48C", NULL, {NULL} } -, { ":low_brightness:", "\u1f505", NULL, {NULL} } -, { ":lower_left_ballpoint_pen:", "\u1f58A\ufe0f", NULL, {NULL} } -, { ":lower_left_crayon:", "\u1f58D\ufe0f", NULL, {NULL} } -, { ":lower_left_fountain_pen:", "\u1f58B\ufe0f", NULL, {NULL} } -, { ":lower_left_paintbrush:", "\u1f58C\ufe0f", NULL, {NULL} } -, { ":lying_face:", "\u1f925", NULL, {NULL} } -, { ":m:", "\u24c2\ufe0f", NULL, {NULL} } -, { ":mag:", "\u1f50D", NULL, {NULL} } -, { ":mag_right:", "\u1f50E", NULL, {NULL} } -, { ":mage:", "\u1f9d9", NULL, {NULL} } -, { ":mahjong:", "\u1f004", NULL, {NULL} } -, { ":mailbox:", "\u1f4eB", NULL, {NULL} } -, { ":mailbox_closed:", "\u1f4eA", NULL, {NULL} } -, { ":mailbox_with_mail:", "\u1f4eC", NULL, {NULL} } -, { ":mailbox_with_no_mail:", "\u1f4eD", NULL, {NULL} } -, { ":male-artist:", "\u1f468\u200d\u1f3a8", NULL, {NULL} } -, { ":male-astronaut:", "\u1f468\u200d\u1f680", NULL, {NULL} } -, { ":male-construction-worker:", "\u1f477\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male-cook:", "\u1f468\u200d\u1f373", NULL, {NULL} } -, { ":male-detective:", "\u1f575\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male-doctor:", "\u1f468\u200d\u2695\ufe0f", NULL, {NULL} } -, { ":male-factory-worker:", "\u1f468\u200d\u1f3eD", NULL, {NULL} } -, { ":male-farmer:", "\u1f468\u200d\u1f33E", NULL, {NULL} } -, { ":male-firefighter:", "\u1f468\u200d\u1f692", NULL, {NULL} } -, { ":male-guard:", "\u1f482\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male-judge:", "\u1f468\u200d\u2696\ufe0f", NULL, {NULL} } -, { ":male-mechanic:", "\u1f468\u200d\u1f527", NULL, {NULL} } -, { ":male-office-worker:", "\u1f468\u200d\u1f4bC", NULL, {NULL} } -, { ":male-pilot:", "\u1f468\u200d\u2708\ufe0f", NULL, {NULL} } -, { ":male-police-officer:", "\u1f46E\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male-scientist:", "\u1f468\u200d\u1f52C", NULL, {NULL} } -, { ":male-singer:", "\u1f468\u200d\u1f3a4", NULL, {NULL} } -, { ":male-student:", "\u1f468\u200d\u1f393", NULL, {NULL} } -, { ":male-teacher:", "\u1f468\u200d\u1f3eB", NULL, {NULL} } -, { ":male-technologist:", "\u1f468\u200d\u1f4bB", NULL, {NULL} } -, { ":male_elf:", "\u1f9dD\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male_fairy:", "\u1f9dA\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male_genie:", "\u1f9dE\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male_mage:", "\u1f9d9\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male_sign:", "\u2642\ufe0f", NULL, {NULL} } -, { ":male_vampire:", "\u1f9dB\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":male_zombie:", "\u1f9dF\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man:", "\u1f468", NULL, {NULL} } -, { ":man-biking:", "\u1f6b4\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-bouncing-ball:", "\u26f9\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-bowing:", "\u1f647\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-boy:", "\u1f468\u200d\u1f466", NULL, {NULL} } -, { ":man-boy-boy:", "\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { ":man-cartwheeling:", "\u1f938\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-facepalming:", "\u1f926\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-frowning:", "\u1f64D\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-gesturing-no:", "\u1f645\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-gesturing-ok:", "\u1f646\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-getting-haircut:", "\u1f487\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-getting-massage:", "\u1f486\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-girl:", "\u1f468\u200d\u1f467", NULL, {NULL} } -, { ":man-girl-boy:", "\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { ":man-girl-girl:", "\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { ":man-golfing:", "\u1f3cC\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-heart-man:", "\u1f468\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } -, { ":man-juggling:", "\u1f939\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-kiss-man:", "\u1f468\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } -, { ":man-lifting-weights:", "\u1f3cB\ufe0f\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-man-boy:", "\u1f468\u200d\u1f468\u200d\u1f466", NULL, {NULL} } -, { ":man-man-boy-boy:", "\u1f468\u200d\u1f468\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { ":man-man-girl:", "\u1f468\u200d\u1f468\u200d\u1f467", NULL, {NULL} } -, { ":man-man-girl-boy:", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { ":man-man-girl-girl:", "\u1f468\u200d\u1f468\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { ":man-mountain-biking:", "\u1f6b5\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-playing-handball:", "\u1f93E\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-playing-water-polo:", "\u1f93D\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-pouting:", "\u1f64E\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-raising-hand:", "\u1f64B\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-rowing-boat:", "\u1f6a3\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-running:", "\u1f3c3\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-shrugging:", "\u1f937\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-surfing:", "\u1f3c4\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-swimming:", "\u1f3cA\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-tipping-hand:", "\u1f481\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-walking:", "\u1f6b6\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-wearing-turban:", "\u1f473\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-with-bunny-ears-partying:", "\u1f46F\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man-woman-boy:", "\u1f468\u200d\u1f469\u200d\u1f466", NULL, {NULL} } -, { ":man-woman-boy:", "\u1f46A", NULL, {NULL} } -, { ":man-woman-boy-boy:", "\u1f468\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { ":man-woman-girl:", "\u1f468\u200d\u1f469\u200d\u1f467", NULL, {NULL} } -, { ":man-woman-girl-boy:", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { ":man-woman-girl-girl:", "\u1f468\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { ":man-wrestling:", "\u1f93C\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man_and_woman_holding_hands:", "\u1f46B", NULL, {NULL} } -, { ":man_climbing:", "\u1f9d7\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man_dancing:", "\u1f57A", NULL, {NULL} } -, { ":man_in_business_suit_levitating:", "\u1f574\ufe0f", NULL, {NULL} } -, { ":man_in_lotus_position:", "\u1f9d8\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man_in_steamy_room:", "\u1f9d6\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":man_in_tuxedo:", "\u1f935", NULL, {NULL} } -, { ":man_with_gua_pi_mao:", "\u1f472", NULL, {NULL} } -, { ":man_with_turban:", "\u1f473", NULL, {NULL} } -, { ":mans_shoe:", "\u1f45E", NULL, {NULL} } -, { ":mantelpiece_clock:", "\u1f570\ufe0f", NULL, {NULL} } -, { ":maple_leaf:", "\u1f341", NULL, {NULL} } -, { ":martial_arts_uniform:", "\u1f94B", NULL, {NULL} } -, { ":mask:", "\u1f637", NULL, {NULL} } -, { ":massage:", "\u1f486", NULL, {NULL} } -, { ":meat_on_bone:", "\u1f356", NULL, {NULL} } -, { ":medal:", "\u1f396\ufe0f", NULL, {NULL} } -, { ":medical_symbol:", "\u2695\ufe0f", NULL, {NULL} } -, { ":mega:", "\u1f4e3", NULL, {NULL} } -, { ":melon:", "\u1f348", NULL, {NULL} } -, { ":memo:", "\u1f4dD", NULL, {NULL} } -, { ":menorah_with_nine_branches:", "\u1f54E", NULL, {NULL} } -, { ":mens:", "\u1f6b9", NULL, {NULL} } -, { ":mermaid:", "\u1f9dC\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":merman:", "\u1f9dC\u200d\u2642\ufe0f", NULL, {NULL} } -, { ":merperson:", "\u1f9dC", NULL, {NULL} } -, { ":metro:", "\u1f687", NULL, {NULL} } -, { ":microphone:", "\u1f3a4", NULL, {NULL} } -, { ":microscope:", "\u1f52C", NULL, {NULL} } -, { ":middle_finger:", "\u1f595", NULL, {NULL} } -, { ":milky_way:", "\u1f30C", NULL, {NULL} } -, { ":minibus:", "\u1f690", NULL, {NULL} } -, { ":minidisc:", "\u1f4bD", NULL, {NULL} } -, { ":mobile_phone_off:", "\u1f4f4", NULL, {NULL} } -, { ":money_mouth_face:", "\u1f911", NULL, {NULL} } -, { ":money_with_wings:", "\u1f4b8", NULL, {NULL} } -, { ":moneybag:", "\u1f4b0", NULL, {NULL} } -, { ":monkey:", "\u1f412", NULL, {NULL} } -, { ":monkey_face:", "\u1f435", NULL, {":o)", NULL} } -, { ":monorail:", "\u1f69D", NULL, {NULL} } -, { ":moon:", "\u1f314", NULL, {NULL} } -, { ":mortar_board:", "\u1f393", NULL, {NULL} } -, { ":mosque:", "\u1f54C", NULL, {NULL} } -, { ":mostly_sunny:", "\u1f324\ufe0f", NULL, {NULL} } -, { ":mother_christmas:", "\u1f936", NULL, {NULL} } -, { ":motor_boat:", "\u1f6e5\ufe0f", NULL, {NULL} } -, { ":motor_scooter:", "\u1f6f5", NULL, {NULL} } -, { ":motorway:", "\u1f6e3\ufe0f", NULL, {NULL} } -, { ":mount_fuji:", "\u1f5fB", NULL, {NULL} } -, { ":mountain:", "\u26f0\ufe0f", NULL, {NULL} } -, { ":mountain_bicyclist:", "\u1f6b5", NULL, {NULL} } -, { ":mountain_cableway:", "\u1f6a0", NULL, {NULL} } -, { ":mountain_railway:", "\u1f69E", NULL, {NULL} } -, { ":mouse:", "\u1f42D", NULL, {NULL} } -, { ":mouse2:", "\u1f401", NULL, {NULL} } -, { ":movie_camera:", "\u1f3a5", NULL, {NULL} } -, { ":moyai:", "\u1f5fF", NULL, {NULL} } -, { ":mrs_claus:", "\u1f936", NULL, {NULL} } -, { ":muscle:", "\u1f4aA", NULL, {NULL} } -, { ":mushroom:", "\u1f344", NULL, {NULL} } -, { ":musical_keyboard:", "\u1f3b9", NULL, {NULL} } -, { ":musical_note:", "\u1f3b5", NULL, {NULL} } -, { ":musical_score:", "\u1f3bC", NULL, {NULL} } -, { ":mute:", "\u1f507", NULL, {NULL} } -, { ":nail_care:", "\u1f485", NULL, {NULL} } -, { ":name_badge:", "\u1f4dB", NULL, {NULL} } -, { ":national_park:", "\u1f3dE\ufe0f", NULL, {NULL} } -, { ":nauseated_face:", "\u1f922", NULL, {NULL} } -, { ":necktie:", "\u1f454", NULL, {NULL} } -, { ":negative_squared_cross_mark:", "\u274e", NULL, {NULL} } -, { ":nerd_face:", "\u1f913", NULL, {NULL} } -, { ":neutral_face:", "\u1f610", NULL, {":|", ":-|", NULL} } -, { ":new:", "\u1f195", NULL, {NULL} } -, { ":new_moon:", "\u1f311", NULL, {NULL} } -, { ":new_moon_with_face:", "\u1f31A", NULL, {NULL} } -, { ":newspaper:", "\u1f4f0", NULL, {NULL} } -, { ":ng:", "\u1f196", NULL, {NULL} } -, { ":night_with_stars:", "\u1f303", NULL, {NULL} } -, { ":nine:", "9\ufe0f\u20e3", NULL, {NULL} } -, { ":no_bell:", "\u1f515", NULL, {NULL} } -, { ":no_bicycles:", "\u1f6b3", NULL, {NULL} } -, { ":no_entry:", "\u26d4", NULL, {NULL} } -, { ":no_entry_sign:", "\u1f6aB", NULL, {NULL} } -, { ":no_good:", "\u1f645", NULL, {NULL} } -, { ":no_mobile_phones:", "\u1f4f5", NULL, {NULL} } -, { ":no_mouth:", "\u1f636", NULL, {NULL} } -, { ":no_pedestrians:", "\u1f6b7", NULL, {NULL} } -, { ":no_smoking:", "\u1f6aD", NULL, {NULL} } -, { ":non-potable_water:", "\u1f6b1", NULL, {NULL} } -, { ":nose:", "\u1f443", NULL, {NULL} } -, { ":notebook:", "\u1f4d3", NULL, {NULL} } -, { ":notebook_with_decorative_cover:", "\u1f4d4", NULL, {NULL} } -, { ":notes:", "\u1f3b6", NULL, {NULL} } -, { ":nut_and_bolt:", "\u1f529", NULL, {NULL} } -, { ":o:", "\u2b55", NULL, {NULL} } -, { ":o2:", "\u1f17E\ufe0f", NULL, {NULL} } -, { ":ocean:", "\u1f30A", NULL, {NULL} } -, { ":octagonal_sign:", "\u1f6d1", NULL, {NULL} } -, { ":octopus:", "\u1f419", NULL, {NULL} } -, { ":oden:", "\u1f362", NULL, {NULL} } -, { ":office:", "\u1f3e2", NULL, {NULL} } -, { ":oil_drum:", "\u1f6e2\ufe0f", NULL, {NULL} } -, { ":ok:", "\u1f197", NULL, {NULL} } -, { ":ok_hand:", "\u1f44C", NULL, {NULL} } -, { ":ok_woman:", "\u1f646", NULL, {NULL} } -, { ":old_key:", "\u1f5dD\ufe0f", NULL, {NULL} } -, { ":older_adult:", "\u1f9d3", NULL, {NULL} } -, { ":older_man:", "\u1f474", NULL, {NULL} } -, { ":older_woman:", "\u1f475", NULL, {NULL} } -, { ":om_symbol:", "\u1f549\ufe0f", NULL, {NULL} } -, { ":on:", "\u1f51B", NULL, {NULL} } -, { ":oncoming_automobile:", "\u1f698", NULL, {NULL} } -, { ":oncoming_bus:", "\u1f68D", NULL, {NULL} } -, { ":oncoming_police_car:", "\u1f694", NULL, {NULL} } -, { ":oncoming_taxi:", "\u1f696", NULL, {NULL} } -, { ":one:", "1\ufe0f\u20e3", NULL, {NULL} } -, { ":open_book:", "\u1f4d6", NULL, {NULL} } -, { ":open_file_folder:", "\u1f4c2", NULL, {NULL} } -, { ":open_hands:", "\u1f450", NULL, {NULL} } -, { ":open_mouth:", "\u1f62E", NULL, {":o", ":-o", ":O", ":-O", NULL} } -, { ":ophiuchus:", "\u26ce", NULL, {NULL} } -, { ":orange_book:", "\u1f4d9", NULL, {NULL} } -, { ":orange_heart:", "\u1f9e1", NULL, {NULL} } -, { ":orthodox_cross:", "\u2626\ufe0f", NULL, {NULL} } -, { ":outbox_tray:", "\u1f4e4", NULL, {NULL} } -, { ":owl:", "\u1f989", NULL, {NULL} } -, { ":ox:", "\u1f402", NULL, {NULL} } -, { ":package:", "\u1f4e6", NULL, {NULL} } -, { ":page_facing_up:", "\u1f4c4", NULL, {NULL} } -, { ":page_with_curl:", "\u1f4c3", NULL, {NULL} } -, { ":pager:", "\u1f4dF", NULL, {NULL} } -, { ":palm_tree:", "\u1f334", NULL, {NULL} } -, { ":palms_up_together:", "\u1f932", NULL, {NULL} } -, { ":pancakes:", "\u1f95E", NULL, {NULL} } -, { ":panda_face:", "\u1f43C", NULL, {NULL} } -, { ":paperclip:", "\u1f4cE", NULL, {NULL} } -, { ":parking:", "\u1f17F\ufe0f", NULL, {NULL} } -, { ":part_alternation_mark:", "\u303d\ufe0f", NULL, {NULL} } -, { ":partly_sunny:", "\u26c5", NULL, {NULL} } -, { ":partly_sunny_rain:", "\u1f326\ufe0f", NULL, {NULL} } -, { ":passenger_ship:", "\u1f6f3\ufe0f", NULL, {NULL} } -, { ":passport_control:", "\u1f6c2", NULL, {NULL} } -, { ":paw_prints:", "\u1f43E", NULL, {NULL} } -, { ":peace_symbol:", "\u262e\ufe0f", NULL, {NULL} } -, { ":peach:", "\u1f351", NULL, {NULL} } -, { ":peanuts:", "\u1f95C", NULL, {NULL} } -, { ":pear:", "\u1f350", NULL, {NULL} } -, { ":pencil:", "\u1f4dD", NULL, {NULL} } -, { ":pencil2:", "\u270f\ufe0f", NULL, {NULL} } -, { ":penguin:", "\u1f427", NULL, {NULL} } -, { ":pensive:", "\u1f614", NULL, {NULL} } -, { ":performing_arts:", "\u1f3aD", NULL, {NULL} } -, { ":persevere:", "\u1f623", NULL, {NULL} } -, { ":person_climbing:", "\u1f9d7", NULL, {NULL} } -, { ":person_doing_cartwheel:", "\u1f938", NULL, {NULL} } -, { ":person_frowning:", "\u1f64D", NULL, {NULL} } -, { ":person_in_lotus_position:", "\u1f9d8", NULL, {NULL} } -, { ":person_in_steamy_room:", "\u1f9d6", NULL, {NULL} } -, { ":person_with_ball:", "\u26f9\ufe0f", NULL, {NULL} } -, { ":person_with_blond_hair:", "\u1f471", NULL, {NULL} } -, { ":person_with_headscarf:", "\u1f9d5", NULL, {NULL} } -, { ":person_with_pouting_face:", "\u1f64E", NULL, {NULL} } -, { ":phone:", "\u260e\ufe0f", NULL, {NULL} } -, { ":pick:", "\u26cf\ufe0f", NULL, {NULL} } -, { ":pie:", "\u1f967", NULL, {NULL} } -, { ":pig:", "\u1f437", NULL, {NULL} } -, { ":pig2:", "\u1f416", NULL, {NULL} } -, { ":pig_nose:", "\u1f43D", NULL, {NULL} } -, { ":pill:", "\u1f48A", NULL, {NULL} } -, { ":pineapple:", "\u1f34D", NULL, {NULL} } -, { ":pisces:", "\u2653", NULL, {NULL} } -, { ":pizza:", "\u1f355", NULL, {NULL} } -, { ":place_of_worship:", "\u1f6d0", NULL, {NULL} } -, { ":point_down:", "\u1f447", NULL, {NULL} } -, { ":point_left:", "\u1f448", NULL, {NULL} } -, { ":point_right:", "\u1f449", NULL, {NULL} } -, { ":point_up:", "\u261d\ufe0f", NULL, {NULL} } -, { ":point_up_2:", "\u1f446", NULL, {NULL} } -, { ":police_car:", "\u1f693", NULL, {NULL} } -, { ":poodle:", "\u1f429", NULL, {NULL} } -, { ":poop:", "\u1f4a9", NULL, {NULL} } -, { ":popcorn:", "\u1f37F", NULL, {NULL} } -, { ":post_office:", "\u1f3e3", NULL, {NULL} } -, { ":postal_horn:", "\u1f4eF", NULL, {NULL} } -, { ":postbox:", "\u1f4eE", NULL, {NULL} } -, { ":potable_water:", "\u1f6b0", NULL, {NULL} } -, { ":potato:", "\u1f954", NULL, {NULL} } -, { ":pouch:", "\u1f45D", NULL, {NULL} } -, { ":poultry_leg:", "\u1f357", NULL, {NULL} } -, { ":pound:", "\u1f4b7", NULL, {NULL} } -, { ":pouting_cat:", "\u1f63E", NULL, {NULL} } -, { ":pray:", "\u1f64F", NULL, {NULL} } -, { ":prayer_beads:", "\u1f4fF", NULL, {NULL} } -, { ":pregnant_woman:", "\u1f930", NULL, {NULL} } -, { ":pretzel:", "\u1f968", NULL, {NULL} } -, { ":prince:", "\u1f934", NULL, {NULL} } -, { ":princess:", "\u1f478", NULL, {NULL} } -, { ":printer:", "\u1f5a8\ufe0f", NULL, {NULL} } -, { ":punch:", "\u1f44A", NULL, {NULL} } -, { ":purple_heart:", "\u1f49C", "<3", {NULL} } -, { ":purse:", "\u1f45B", NULL, {NULL} } -, { ":pushpin:", "\u1f4cC", NULL, {NULL} } -, { ":put_litter_in_its_place:", "\u1f6aE", NULL, {NULL} } -, { ":question:", "\u2753", NULL, {NULL} } -, { ":rabbit:", "\u1f430", NULL, {NULL} } -, { ":rabbit2:", "\u1f407", NULL, {NULL} } -, { ":racehorse:", "\u1f40E", NULL, {NULL} } -, { ":racing_car:", "\u1f3cE\ufe0f", NULL, {NULL} } -, { ":racing_motorcycle:", "\u1f3cD\ufe0f", NULL, {NULL} } -, { ":radio:", "\u1f4fB", NULL, {NULL} } -, { ":radio_button:", "\u1f518", NULL, {NULL} } -, { ":radioactive_sign:", "\u2622\ufe0f", NULL, {NULL} } -, { ":rage:", "\u1f621", NULL, {NULL} } -, { ":railway_car:", "\u1f683", NULL, {NULL} } -, { ":railway_track:", "\u1f6e4\ufe0f", NULL, {NULL} } -, { ":rain_cloud:", "\u1f327\ufe0f", NULL, {NULL} } -, { ":rainbow:", "\u1f308", NULL, {NULL} } -, { ":rainbow-flag:", "\u1f3f3\ufe0f\u200d\u1f308", NULL, {NULL} } -, { ":raised_back_of_hand:", "\u1f91A", NULL, {NULL} } -, { ":raised_hand:", "\u270b", NULL, {NULL} } -, { ":raised_hand_with_fingers_splayed:", "\u1f590\ufe0f", NULL, {NULL} } -, { ":raised_hands:", "\u1f64C", NULL, {NULL} } -, { ":raising_hand:", "\u1f64B", NULL, {NULL} } -, { ":ram:", "\u1f40F", NULL, {NULL} } -, { ":ramen:", "\u1f35C", NULL, {NULL} } -, { ":rat:", "\u1f400", NULL, {NULL} } -, { ":recycle:", "\u267b\ufe0f", NULL, {NULL} } -, { ":red_car:", "\u1f697", NULL, {NULL} } -, { ":red_circle:", "\u1f534", NULL, {NULL} } -, { ":registered:", "\u00ae\ufe0f", NULL, {NULL} } -, { ":relaxed:", "\u263a\ufe0f", NULL, {NULL} } -, { ":relieved:", "\u1f60C", NULL, {NULL} } -, { ":reminder_ribbon:", "\u1f397\ufe0f", NULL, {NULL} } -, { ":repeat:", "\u1f501", NULL, {NULL} } -, { ":repeat_one:", "\u1f502", NULL, {NULL} } -, { ":restroom:", "\u1f6bB", NULL, {NULL} } -, { ":reversed_hand_with_middle_finger_extended:", "\u1f595", NULL, {NULL} } -, { ":revolving_hearts:", "\u1f49E", NULL, {NULL} } -, { ":rewind:", "\u23ea", NULL, {NULL} } -, { ":rhinoceros:", "\u1f98F", NULL, {NULL} } -, { ":ribbon:", "\u1f380", NULL, {NULL} } -, { ":rice:", "\u1f35A", NULL, {NULL} } -, { ":rice_ball:", "\u1f359", NULL, {NULL} } -, { ":rice_cracker:", "\u1f358", NULL, {NULL} } -, { ":rice_scene:", "\u1f391", NULL, {NULL} } -, { ":right-facing_fist:", "\u1f91C", NULL, {NULL} } -, { ":right_anger_bubble:", "\u1f5eF\ufe0f", NULL, {NULL} } -, { ":ring:", "\u1f48D", NULL, {NULL} } -, { ":robot_face:", "\u1f916", NULL, {NULL} } -, { ":rocket:", "\u1f680", NULL, {NULL} } -, { ":rolled_up_newspaper:", "\u1f5dE\ufe0f", NULL, {NULL} } -, { ":roller_coaster:", "\u1f3a2", NULL, {NULL} } -, { ":rolling_on_the_floor_laughing:", "\u1f923", NULL, {NULL} } -, { ":rooster:", "\u1f413", NULL, {NULL} } -, { ":rose:", "\u1f339", NULL, {NULL} } -, { ":rosette:", "\u1f3f5\ufe0f", NULL, {NULL} } -, { ":rotating_light:", "\u1f6a8", NULL, {NULL} } -, { ":round_pushpin:", "\u1f4cD", NULL, {NULL} } -, { ":rowboat:", "\u1f6a3", NULL, {NULL} } -, { ":ru:", "\u1f1f7\u1f1fA", NULL, {NULL} } -, { ":rugby_football:", "\u1f3c9", NULL, {NULL} } -, { ":runner:", "\u1f3c3", NULL, {NULL} } -, { ":running:", "\u1f3c3", NULL, {NULL} } -, { ":running_shirt_with_sash:", "\u1f3bD", NULL, {NULL} } -, { ":sa:", "\u1f202\ufe0f", NULL, {NULL} } -, { ":sagittarius:", "\u2650", NULL, {NULL} } -, { ":sailboat:", "\u26f5", NULL, {NULL} } -, { ":sake:", "\u1f376", NULL, {NULL} } -, { ":sandal:", "\u1f461", NULL, {NULL} } -, { ":sandwich:", "\u1f96A", NULL, {NULL} } -, { ":santa:", "\u1f385", NULL, {NULL} } -, { ":satellite:", "\u1f6f0\ufe0f", NULL, {NULL} } -, { ":satellite_antenna:", "\u1f4e1", NULL, {NULL} } -, { ":satisfied:", "\u1f606", NULL, {":>", ":->", NULL} } -, { ":sauropod:", "\u1f995", NULL, {NULL} } -, { ":saxophone:", "\u1f3b7", NULL, {NULL} } -, { ":scales:", "\u2696\ufe0f", NULL, {NULL} } -, { ":scarf:", "\u1f9e3", NULL, {NULL} } -, { ":school:", "\u1f3eB", NULL, {NULL} } -, { ":school_satchel:", "\u1f392", NULL, {NULL} } -, { ":scissors:", "\u2702\ufe0f", NULL, {NULL} } -, { ":scooter:", "\u1f6f4", NULL, {NULL} } -, { ":scorpion:", "\u1f982", NULL, {NULL} } -, { ":scorpius:", "\u264f", NULL, {NULL} } -, { ":scream:", "\u1f631", NULL, {NULL} } -, { ":scream_cat:", "\u1f640", NULL, {NULL} } -, { ":scroll:", "\u1f4dC", NULL, {NULL} } -, { ":seat:", "\u1f4bA", NULL, {NULL} } -, { ":second_place_medal:", "\u1f948", NULL, {NULL} } -, { ":secret:", "\u3299\ufe0f", NULL, {NULL} } -, { ":see_no_evil:", "\u1f648", NULL, {NULL} } -, { ":seedling:", "\u1f331", NULL, {NULL} } -, { ":selfie:", "\u1f933", NULL, {NULL} } -, { ":serious_face_with_symbols_covering_mouth:", "\u1f92C", NULL, {NULL} } -, { ":seven:", "7\ufe0f\u20e3", NULL, {NULL} } -, { ":shallow_pan_of_food:", "\u1f958", NULL, {NULL} } -, { ":shamrock:", "\u2618\ufe0f", NULL, {NULL} } -, { ":shark:", "\u1f988", NULL, {NULL} } -, { ":shaved_ice:", "\u1f367", NULL, {NULL} } -, { ":sheep:", "\u1f411", NULL, {NULL} } -, { ":shell:", "\u1f41A", NULL, {NULL} } -, { ":shield:", "\u1f6e1\ufe0f", NULL, {NULL} } -, { ":shinto_shrine:", "\u26e9\ufe0f", NULL, {NULL} } -, { ":ship:", "\u1f6a2", NULL, {NULL} } -, { ":shirt:", "\u1f455", NULL, {NULL} } -, { ":shit:", "\u1f4a9", NULL, {NULL} } -, { ":shocked_face_with_exploding_head:", "\u1f92F", NULL, {NULL} } -, { ":shoe:", "\u1f45E", NULL, {NULL} } -, { ":shopping_bags:", "\u1f6cD\ufe0f", NULL, {NULL} } -, { ":shopping_trolley:", "\u1f6d2", NULL, {NULL} } -, { ":shower:", "\u1f6bF", NULL, {NULL} } -, { ":shrimp:", "\u1f990", NULL, {NULL} } -, { ":shrug:", "\u1f937", NULL, {NULL} } -, { ":shushing_face:", "\u1f92B", NULL, {NULL} } -, { ":sign_of_the_horns:", "\u1f918", NULL, {NULL} } -, { ":signal_strength:", "\u1f4f6", NULL, {NULL} } -, { ":six:", "6\ufe0f\u20e3", NULL, {NULL} } -, { ":six_pointed_star:", "\u1f52F", NULL, {NULL} } -, { ":ski:", "\u1f3bF", NULL, {NULL} } -, { ":skier:", "\u26f7\ufe0f", NULL, {NULL} } -, { ":skin-tone-2:", "\u1f3fB", NULL, {NULL} } -, { ":skin-tone-3:", "\u1f3fC", NULL, {NULL} } -, { ":skin-tone-4:", "\u1f3fD", NULL, {NULL} } -, { ":skin-tone-5:", "\u1f3fE", NULL, {NULL} } -, { ":skin-tone-6:", "\u1f3fF", NULL, {NULL} } -, { ":skull:", "\u1f480", NULL, {NULL} } -, { ":skull_and_crossbones:", "\u2620\ufe0f", NULL, {NULL} } -, { ":sled:", "\u1f6f7", NULL, {NULL} } -, { ":sleeping:", "\u1f634", NULL, {NULL} } -, { ":sleeping_accommodation:", "\u1f6cC", NULL, {NULL} } -, { ":sleepy:", "\u1f62A", NULL, {NULL} } -, { ":sleuth_or_spy:", "\u1f575\ufe0f", NULL, {NULL} } -, { ":slightly_frowning_face:", "\u1f641", NULL, {NULL} } -, { ":slightly_smiling_face:", "\u1f642", NULL, {":)", "(:", ":-)", NULL} } -, { ":slot_machine:", "\u1f3b0", NULL, {NULL} } -, { ":small_airplane:", "\u1f6e9\ufe0f", NULL, {NULL} } -, { ":small_blue_diamond:", "\u1f539", NULL, {NULL} } -, { ":small_orange_diamond:", "\u1f538", NULL, {NULL} } -, { ":small_red_triangle:", "\u1f53A", NULL, {NULL} } -, { ":small_red_triangle_down:", "\u1f53B", NULL, {NULL} } -, { ":smile:", "\u1f604", ":)", {"C:", "c:", ":D", ":-D", NULL} } -, { ":smile_cat:", "\u1f638", NULL, {NULL} } -, { ":smiley:", "\u1f603", ":)", {"=)", "=-)", NULL} } -, { ":smiley_cat:", "\u1f63A", NULL, {NULL} } -, { ":smiling_face_with_smiling_eyes_and_hand_covering_mouth:", "\u1f92D", NULL, {NULL} } -, { ":smiling_imp:", "\u1f608", NULL, {NULL} } -, { ":smirk:", "\u1f60F", NULL, {NULL} } -, { ":smirk_cat:", "\u1f63C", NULL, {NULL} } -, { ":smoking:", "\u1f6aC", NULL, {NULL} } -, { ":snail:", "\u1f40C", NULL, {NULL} } -, { ":snake:", "\u1f40D", NULL, {NULL} } -, { ":sneezing_face:", "\u1f927", NULL, {NULL} } -, { ":snow_capped_mountain:", "\u1f3d4\ufe0f", NULL, {NULL} } -, { ":snow_cloud:", "\u1f328\ufe0f", NULL, {NULL} } -, { ":snowboarder:", "\u1f3c2", NULL, {NULL} } -, { ":snowflake:", "\u2744\ufe0f", NULL, {NULL} } -, { ":snowman:", "\u2603\ufe0f", NULL, {NULL} } -, { ":snowman_without_snow:", "\u26c4", NULL, {NULL} } -, { ":sob:", "\u1f62D", ":'(", {NULL} } -, { ":soccer:", "\u26bd", NULL, {NULL} } -, { ":socks:", "\u1f9e6", NULL, {NULL} } -, { ":soon:", "\u1f51C", NULL, {NULL} } -, { ":sos:", "\u1f198", NULL, {NULL} } -, { ":sound:", "\u1f509", NULL, {NULL} } -, { ":space_invader:", "\u1f47E", NULL, {NULL} } -, { ":spades:", "\u2660\ufe0f", NULL, {NULL} } -, { ":spaghetti:", "\u1f35D", NULL, {NULL} } -, { ":sparkle:", "\u2747\ufe0f", NULL, {NULL} } -, { ":sparkler:", "\u1f387", NULL, {NULL} } -, { ":sparkles:", "\u2728", NULL, {NULL} } -, { ":sparkling_heart:", "\u1f496", NULL, {NULL} } -, { ":speak_no_evil:", "\u1f64A", NULL, {NULL} } -, { ":speaker:", "\u1f508", NULL, {NULL} } -, { ":speaking_head_in_silhouette:", "\u1f5e3\ufe0f", NULL, {NULL} } -, { ":speech_balloon:", "\u1f4aC", NULL, {NULL} } -, { ":speedboat:", "\u1f6a4", NULL, {NULL} } -, { ":spider:", "\u1f577\ufe0f", NULL, {NULL} } -, { ":spider_web:", "\u1f578\ufe0f", NULL, {NULL} } -, { ":spiral_calendar_pad:", "\u1f5d3\ufe0f", NULL, {NULL} } -, { ":spiral_note_pad:", "\u1f5d2\ufe0f", NULL, {NULL} } -, { ":spock-hand:", "\u1f596", NULL, {NULL} } -, { ":spoon:", "\u1f944", NULL, {NULL} } -, { ":sports_medal:", "\u1f3c5", NULL, {NULL} } -, { ":squid:", "\u1f991", NULL, {NULL} } -, { ":stadium:", "\u1f3dF\ufe0f", NULL, {NULL} } -, { ":staff_of_aesculapius:", "\u2695\ufe0f", NULL, {NULL} } -, { ":star:", "\u2b50", NULL, {NULL} } -, { ":star-struck:", "\u1f929", NULL, {NULL} } -, { ":star2:", "\u1f31F", NULL, {NULL} } -, { ":star_and_crescent:", "\u262a\ufe0f", NULL, {NULL} } -, { ":star_of_david:", "\u2721\ufe0f", NULL, {NULL} } -, { ":stars:", "\u1f320", NULL, {NULL} } -, { ":station:", "\u1f689", NULL, {NULL} } -, { ":statue_of_liberty:", "\u1f5fD", NULL, {NULL} } -, { ":steam_locomotive:", "\u1f682", NULL, {NULL} } -, { ":stew:", "\u1f372", NULL, {NULL} } -, { ":stopwatch:", "\u23f1\ufe0f", NULL, {NULL} } -, { ":straight_ruler:", "\u1f4cF", NULL, {NULL} } -, { ":strawberry:", "\u1f353", NULL, {NULL} } -, { ":stuck_out_tongue:", "\u1f61B", ":p", {":p", ":-p", ":P", ":-P", ":b", ":-b", NULL} } -, { ":stuck_out_tongue_closed_eyes:", "\u1f61D", NULL, {NULL} } -, { ":stuck_out_tongue_winking_eye:", "\u1f61C", ";p", {";p", ";-p", ";b", ";-b", ";P", ";-P", NULL} } -, { ":studio_microphone:", "\u1f399\ufe0f", NULL, {NULL} } -, { ":stuffed_flatbread:", "\u1f959", NULL, {NULL} } -, { ":sun_behind_cloud:", "\u1f325\ufe0f", NULL, {NULL} } -, { ":sun_behind_rain_cloud:", "\u1f326\ufe0f", NULL, {NULL} } -, { ":sun_small_cloud:", "\u1f324\ufe0f", NULL, {NULL} } -, { ":sun_with_face:", "\u1f31E", NULL, {NULL} } -, { ":sunflower:", "\u1f33B", NULL, {NULL} } -, { ":sunglasses:", "\u1f60E", NULL, {"8)", NULL} } -, { ":sunny:", "\u2600\ufe0f", NULL, {NULL} } -, { ":sunrise:", "\u1f305", NULL, {NULL} } -, { ":sunrise_over_mountains:", "\u1f304", NULL, {NULL} } -, { ":surfer:", "\u1f3c4", NULL, {NULL} } -, { ":sushi:", "\u1f363", NULL, {NULL} } -, { ":suspension_railway:", "\u1f69F", NULL, {NULL} } -, { ":sweat:", "\u1f613", NULL, {NULL} } -, { ":sweat_drops:", "\u1f4a6", NULL, {NULL} } -, { ":sweat_smile:", "\u1f605", NULL, {NULL} } -, { ":sweet_potato:", "\u1f360", NULL, {NULL} } -, { ":swimmer:", "\u1f3cA", NULL, {NULL} } -, { ":symbols:", "\u1f523", NULL, {NULL} } -, { ":synagogue:", "\u1f54D", NULL, {NULL} } -, { ":syringe:", "\u1f489", NULL, {NULL} } -, { ":t-rex:", "\u1f996", NULL, {NULL} } -, { ":table_tennis_paddle_and_ball:", "\u1f3d3", NULL, {NULL} } -, { ":taco:", "\u1f32E", NULL, {NULL} } -, { ":tada:", "\u1f389", NULL, {NULL} } -, { ":takeout_box:", "\u1f961", NULL, {NULL} } -, { ":tanabata_tree:", "\u1f38B", NULL, {NULL} } -, { ":tangerine:", "\u1f34A", NULL, {NULL} } -, { ":taurus:", "\u2649", NULL, {NULL} } -, { ":taxi:", "\u1f695", NULL, {NULL} } -, { ":tea:", "\u1f375", NULL, {NULL} } -, { ":telephone:", "\u260e\ufe0f", NULL, {NULL} } -, { ":telephone_receiver:", "\u1f4dE", NULL, {NULL} } -, { ":telescope:", "\u1f52D", NULL, {NULL} } -, { ":tennis:", "\u1f3bE", NULL, {NULL} } -, { ":tent:", "\u26fa", NULL, {NULL} } -, { ":the_horns:", "\u1f918", NULL, {NULL} } -, { ":thermometer:", "\u1f321\ufe0f", NULL, {NULL} } -, { ":thinking_face:", "\u1f914", NULL, {NULL} } -, { ":third_place_medal:", "\u1f949", NULL, {NULL} } -, { ":thought_balloon:", "\u1f4aD", NULL, {NULL} } -, { ":three:", "3\ufe0f\u20e3", NULL, {NULL} } -, { ":three_button_mouse:", "\u1f5b1\ufe0f", NULL, {NULL} } -, { ":thumbsdown:", "\u1f44E", NULL, {NULL} } -, { ":thumbsup:", "\u1f44D", NULL, {NULL} } -, { ":thunder_cloud_and_rain:", "\u26c8\ufe0f", NULL, {NULL} } -, { ":ticket:", "\u1f3aB", NULL, {NULL} } -, { ":tiger:", "\u1f42F", NULL, {NULL} } -, { ":tiger2:", "\u1f405", NULL, {NULL} } -, { ":timer_clock:", "\u23f2\ufe0f", NULL, {NULL} } -, { ":tired_face:", "\u1f62B", NULL, {NULL} } -, { ":tm:", "\u2122\ufe0f", NULL, {NULL} } -, { ":toilet:", "\u1f6bD", NULL, {NULL} } -, { ":tokyo_tower:", "\u1f5fC", NULL, {NULL} } -, { ":tomato:", "\u1f345", NULL, {NULL} } -, { ":tongue:", "\u1f445", NULL, {NULL} } -, { ":top:", "\u1f51D", NULL, {NULL} } -, { ":tophat:", "\u1f3a9", NULL, {NULL} } -, { ":tornado:", "\u1f32A\ufe0f", NULL, {NULL} } -, { ":tornado_cloud:", "\u1f32A\ufe0f", NULL, {NULL} } -, { ":trackball:", "\u1f5b2\ufe0f", NULL, {NULL} } -, { ":tractor:", "\u1f69C", NULL, {NULL} } -, { ":traffic_light:", "\u1f6a5", NULL, {NULL} } -, { ":train:", "\u1f68B", NULL, {NULL} } -, { ":train2:", "\u1f686", NULL, {NULL} } -, { ":tram:", "\u1f68A", NULL, {NULL} } -, { ":triangular_flag_on_post:", "\u1f6a9", NULL, {NULL} } -, { ":triangular_ruler:", "\u1f4d0", NULL, {NULL} } -, { ":trident:", "\u1f531", NULL, {NULL} } -, { ":triumph:", "\u1f624", NULL, {NULL} } -, { ":trolleybus:", "\u1f68E", NULL, {NULL} } -, { ":trophy:", "\u1f3c6", NULL, {NULL} } -, { ":tropical_drink:", "\u1f379", NULL, {NULL} } -, { ":tropical_fish:", "\u1f420", NULL, {NULL} } -, { ":truck:", "\u1f69A", NULL, {NULL} } -, { ":trumpet:", "\u1f3bA", NULL, {NULL} } -, { ":tshirt:", "\u1f455", NULL, {NULL} } -, { ":tulip:", "\u1f337", NULL, {NULL} } -, { ":tumbler_glass:", "\u1f943", NULL, {NULL} } -, { ":turkey:", "\u1f983", NULL, {NULL} } -, { ":turtle:", "\u1f422", NULL, {NULL} } -, { ":tv:", "\u1f4fA", NULL, {NULL} } -, { ":twisted_rightwards_arrows:", "\u1f500", NULL, {NULL} } -, { ":two:", "2\ufe0f\u20e3", NULL, {NULL} } -, { ":two_hearts:", "\u1f495", NULL, {NULL} } -, { ":two_men_holding_hands:", "\u1f46C", NULL, {NULL} } -, { ":two_women_holding_hands:", "\u1f46D", NULL, {NULL} } -, { ":u5272:", "\u1f239", NULL, {NULL} } -, { ":u5408:", "\u1f234", NULL, {NULL} } -, { ":u55b6:", "\u1f23A", NULL, {NULL} } -, { ":u6307:", "\u1f22F", NULL, {NULL} } -, { ":u6708:", "\u1f237\ufe0f", NULL, {NULL} } -, { ":u6709:", "\u1f236", NULL, {NULL} } -, { ":u6e80:", "\u1f235", NULL, {NULL} } -, { ":u7121:", "\u1f21A", NULL, {NULL} } -, { ":u7533:", "\u1f238", NULL, {NULL} } -, { ":u7981:", "\u1f232", NULL, {NULL} } -, { ":u7a7a:", "\u1f233", NULL, {NULL} } -, { ":uk:", "\u1f1eC\u1f1e7", NULL, {NULL} } -, { ":umbrella:", "\u2602\ufe0f", NULL, {NULL} } -, { ":umbrella_on_ground:", "\u26f1\ufe0f", NULL, {NULL} } -, { ":umbrella_with_rain_drops:", "\u2614", NULL, {NULL} } -, { ":unamused:", "\u1f612", ":(", {NULL} } -, { ":underage:", "\u1f51E", NULL, {NULL} } -, { ":unicorn_face:", "\u1f984", NULL, {NULL} } -, { ":unlock:", "\u1f513", NULL, {NULL} } -, { ":up:", "\u1f199", NULL, {NULL} } -, { ":upside_down_face:", "\u1f643", NULL, {NULL} } -, { ":us:", "\u1f1fA\u1f1f8", NULL, {NULL} } -, { ":v:", "\u270c\ufe0f", NULL, {NULL} } -, { ":vampire:", "\u1f9dB", NULL, {NULL} } -, { ":vertical_traffic_light:", "\u1f6a6", NULL, {NULL} } -, { ":vhs:", "\u1f4fC", NULL, {NULL} } -, { ":vibration_mode:", "\u1f4f3", NULL, {NULL} } -, { ":video_camera:", "\u1f4f9", NULL, {NULL} } -, { ":video_game:", "\u1f3aE", NULL, {NULL} } -, { ":violin:", "\u1f3bB", NULL, {NULL} } -, { ":virgo:", "\u264d", NULL, {NULL} } -, { ":volcano:", "\u1f30B", NULL, {NULL} } -, { ":volleyball:", "\u1f3d0", NULL, {NULL} } -, { ":vs:", "\u1f19A", NULL, {NULL} } -, { ":walking:", "\u1f6b6", NULL, {NULL} } -, { ":waning_crescent_moon:", "\u1f318", NULL, {NULL} } -, { ":waning_gibbous_moon:", "\u1f316", NULL, {NULL} } -, { ":warning:", "\u26a0\ufe0f", NULL, {NULL} } -, { ":wastebasket:", "\u1f5d1\ufe0f", NULL, {NULL} } -, { ":watch:", "\u231a", NULL, {NULL} } -, { ":water_buffalo:", "\u1f403", NULL, {NULL} } -, { ":water_polo:", "\u1f93D", NULL, {NULL} } -, { ":watermelon:", "\u1f349", NULL, {NULL} } -, { ":wave:", "\u1f44B", NULL, {NULL} } -, { ":waving_black_flag:", "\u1f3f4", NULL, {NULL} } -, { ":waving_white_flag:", "\u1f3f3\ufe0f", NULL, {NULL} } -, { ":wavy_dash:", "\u3030\ufe0f", NULL, {NULL} } -, { ":waxing_crescent_moon:", "\u1f312", NULL, {NULL} } -, { ":waxing_gibbous_moon:", "\u1f314", NULL, {NULL} } -, { ":wc:", "\u1f6bE", NULL, {NULL} } -, { ":weary:", "\u1f629", NULL, {NULL} } -, { ":wedding:", "\u1f492", NULL, {NULL} } -, { ":weight_lifter:", "\u1f3cB\ufe0f", NULL, {NULL} } -, { ":whale:", "\u1f433", NULL, {NULL} } -, { ":whale2:", "\u1f40B", NULL, {NULL} } -, { ":wheel_of_dharma:", "\u2638\ufe0f", NULL, {NULL} } -, { ":wheelchair:", "\u267f", NULL, {NULL} } -, { ":white_check_mark:", "\u2705", NULL, {NULL} } -, { ":white_circle:", "\u26aa", NULL, {NULL} } -, { ":white_flower:", "\u1f4aE", NULL, {NULL} } -, { ":white_frowning_face:", "\u2639\ufe0f", NULL, {NULL} } -, { ":white_large_square:", "\u2b1c", NULL, {NULL} } -, { ":white_medium_small_square:", "\u25fd", NULL, {NULL} } -, { ":white_medium_square:", "\u25fb\ufe0f", NULL, {NULL} } -, { ":white_small_square:", "\u25ab\ufe0f", NULL, {NULL} } -, { ":white_square_button:", "\u1f533", NULL, {NULL} } -, { ":wilted_flower:", "\u1f940", NULL, {NULL} } -, { ":wind_blowing_face:", "\u1f32C\ufe0f", NULL, {NULL} } -, { ":wind_chime:", "\u1f390", NULL, {NULL} } -, { ":wine_glass:", "\u1f377", NULL, {NULL} } -, { ":wink:", "\u1f609", ";)", {";)", ";-)", NULL} } -, { ":wolf:", "\u1f43A", NULL, {NULL} } -, { ":woman:", "\u1f469", NULL, {NULL} } -, { ":woman-biking:", "\u1f6b4\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-bouncing-ball:", "\u26f9\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-bowing:", "\u1f647\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-boy:", "\u1f469\u200d\u1f466", NULL, {NULL} } -, { ":woman-boy-boy:", "\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { ":woman-cartwheeling:", "\u1f938\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-facepalming:", "\u1f926\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-frowning:", "\u1f64D\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-gesturing-no:", "\u1f645\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-gesturing-ok:", "\u1f646\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-getting-haircut:", "\u1f487\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-getting-massage:", "\u1f486\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-girl:", "\u1f469\u200d\u1f467", NULL, {NULL} } -, { ":woman-girl-boy:", "\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { ":woman-girl-girl:", "\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { ":woman-golfing:", "\u1f3cC\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-heart-man:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f468", NULL, {NULL} } -, { ":woman-heart-woman:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f469", NULL, {NULL} } -, { ":woman-juggling:", "\u1f939\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-kiss-man:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f468", NULL, {NULL} } -, { ":woman-kiss-woman:", "\u1f469\u200d\u2764\ufe0f\u200d\u1f48B\u200d\u1f469", NULL, {NULL} } -, { ":woman-lifting-weights:", "\u1f3cB\ufe0f\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-mountain-biking:", "\u1f6b5\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-playing-handball:", "\u1f93E\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-playing-water-polo:", "\u1f93D\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-pouting:", "\u1f64E\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-raising-hand:", "\u1f64B\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-rowing-boat:", "\u1f6a3\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-running:", "\u1f3c3\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-shrugging:", "\u1f937\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-surfing:", "\u1f3c4\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-swimming:", "\u1f3cA\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-tipping-hand:", "\u1f481\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-walking:", "\u1f6b6\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-wearing-turban:", "\u1f473\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-with-bunny-ears-partying:", "\u1f46F\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman-woman-boy:", "\u1f469\u200d\u1f469\u200d\u1f466", NULL, {NULL} } -, { ":woman-woman-boy-boy:", "\u1f469\u200d\u1f469\u200d\u1f466\u200d\u1f466", NULL, {NULL} } -, { ":woman-woman-girl:", "\u1f469\u200d\u1f469\u200d\u1f467", NULL, {NULL} } -, { ":woman-woman-girl-boy:", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f466", NULL, {NULL} } -, { ":woman-woman-girl-girl:", "\u1f469\u200d\u1f469\u200d\u1f467\u200d\u1f467", NULL, {NULL} } -, { ":woman-wrestling:", "\u1f93C\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman_climbing:", "\u1f9d7\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman_in_lotus_position:", "\u1f9d8\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":woman_in_steamy_room:", "\u1f9d6\u200d\u2640\ufe0f", NULL, {NULL} } -, { ":womans_clothes:", "\u1f45A", NULL, {NULL} } -, { ":womans_hat:", "\u1f452", NULL, {NULL} } -, { ":womens:", "\u1f6bA", NULL, {NULL} } -, { ":world_map:", "\u1f5fA\ufe0f", NULL, {NULL} } -, { ":worried:", "\u1f61F", NULL, {NULL} } -, { ":wrench:", "\u1f527", NULL, {NULL} } -, { ":wrestlers:", "\u1f93C", NULL, {NULL} } -, { ":writing_hand:", "\u270d\ufe0f", NULL, {NULL} } -, { ":x:", "\u274c", NULL, {NULL} } -, { ":yellow_heart:", "\u1f49B", "<3", {NULL} } -, { ":yen:", "\u1f4b4", NULL, {NULL} } -, { ":yin_yang:", "\u262f\ufe0f", NULL, {NULL} } -, { ":yum:", "\u1f60B", NULL, {NULL} } -, { ":zany_face:", "\u1f92A", NULL, {NULL} } -, { ":zap:", "\u26a1", NULL, {NULL} } -, { ":zebra_face:", "\u1f993", NULL, {NULL} } -, { ":zero:", "0\ufe0f\u20e3", NULL, {NULL} } -, { ":zipper_mouth_face:", "\u1f910", NULL, {NULL} } -, { ":zombie:", "\u1f9dF", NULL, {NULL} } -, { ":zzz:", "\u1f4a4", NULL, {NULL} } -}; - -static struct t_slack_emoji_by_text slack_emoji_by_text[] = -{ { "(:", "\u1f642", ":slightly_smiling_face:", {":slightly_smiling_face:", NULL} } -, { "):", "\u1f61E", ":disappointed:", {":disappointed:", NULL} } -, { "8)", "\u1f60E", ":sunglasses:", {":sunglasses:", NULL} } -, { ":'(", "\u1f622", ":cry:", {":cry:", NULL} } -, { ":(", "\u1f61E", ":disappointed:", {":disappointed:", NULL} } -, { ":)", "\u1f642", ":slightly_smiling_face:", {":slightly_smiling_face:", NULL} } -, { ":*", "\u1f618", ":kissing_heart:", {":kissing_heart:", NULL} } -, { ":-(", "\u1f61E", ":disappointed:", {":disappointed:", NULL} } -, { ":-)", "\u1f642", ":slightly_smiling_face:", {":slightly_smiling_face:", NULL} } -, { ":-*", "\u1f618", ":kissing_heart:", {":kissing_heart:", NULL} } -, { ":-/", "\u1f615", ":confused:", {":confused:", NULL} } -, { ":->", "\u1f606", ":laughing:", {":laughing:", ":satisfied:", NULL} } -, { ":-D", "\u1f604", ":smile:", {":smile:", NULL} } -, { ":-O", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } -, { ":-P", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } -, { ":-\\", "\u1f615", ":confused:", {":confused:", NULL} } -, { ":-b", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } -, { ":-o", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } -, { ":-p", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } -, { ":-|", "\u1f610", ":neutral_face:", {":neutral_face:", NULL} } -, { ":/", "\u1f615", ":confused:", {":confused:", NULL} } -, { ":>", "\u1f606", ":laughing:", {":laughing:", ":satisfied:", NULL} } -, { ":D", "\u1f604", ":smile:", {":smile:", NULL} } -, { ":O", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } -, { ":P", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } -, { ":\\", "\u1f615", ":confused:", {":confused:", NULL} } -, { ":b", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } -, { ":o", "\u1f62E", ":open_mouth:", {":open_mouth:", NULL} } -, { ":o)", "\u1f435", ":monkey_face:", {":monkey_face:", NULL} } -, { ":p", "\u1f61B", ":stuck_out_tongue:", {":stuck_out_tongue:", NULL} } -, { ":|", "\u1f610", ":neutral_face:", {":neutral_face:", NULL} } -, { ";)", "\u1f609", ":wink:", {":wink:", NULL} } -, { ";-)", "\u1f609", ":wink:", {":wink:", NULL} } -, { ";-P", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } -, { ";-b", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } -, { ";-p", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } -, { ";P", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } -, { ";b", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } -, { ";p", "\u1f61C", ":stuck_out_tongue_winking_eye:", {":stuck_out_tongue_winking_eye:", NULL} } -, { ":(", "\u1f620", ":angry:", {":angry:", NULL} } -, { ">:-(", "\u1f620", ":angry:", {":angry:", NULL} } -, { "C:", "\u1f604", ":smile:", {":smile:", NULL} } -, { "D:", "\u1f627", ":anguished:", {":anguished:", NULL} } -, { "c:", "\u1f604", ":smile:", {":smile:", NULL} } -}; diff --git a/slack-input.c b/slack-input.c deleted file mode 100644 index 8643e8c..0000000 --- a/slack-input.c +++ /dev/null @@ -1,77 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-channel.h" -#include "slack-buffer.h" -#include "slack-request.h" -#include "slack-message.h" -#include "slack-input.h" -#include "request/slack-request-chat-postmessage.h" - -int slack_input_data(struct t_gui_buffer *buffer, const char *input_data) -{ - struct t_slack_workspace *workspace = NULL; - struct t_slack_channel *channel = NULL; - struct t_slack_request *request; - char *text; - - slack_buffer_get_workspace_and_channel(buffer, &workspace, &channel); - - if (!workspace) - return WEECHAT_RC_ERROR; - - if (channel) - { - if (!workspace->is_connected) - { - weechat_printf(buffer, - _("%s%s: you are not connected to server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return WEECHAT_RC_OK; - } - - text = malloc(SLACK_MESSAGE_MAX_LENGTH); - if (!text) - { - weechat_printf(buffer, - _("%s%s: error allocating string"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return WEECHAT_RC_ERROR; - } - lws_urlencode(text, input_data, SLACK_MESSAGE_MAX_LENGTH); - - request = slack_request_chat_postmessage(workspace, - weechat_config_string( - workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]), - channel->id, text); - if (request) - slack_workspace_register_request(workspace, request); - - free(text); - } - else - { - weechat_printf(buffer, - _("%s%s: this buffer is not a channel!"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - } - - return WEECHAT_RC_OK; -} - -int slack_input_data_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *input_data) -{ - (void) pointer; - (void) data; - - return slack_input_data(buffer, input_data); -} diff --git a/slack-input.h b/slack-input.h deleted file mode 100644 index fbc1d59..0000000 --- a/slack-input.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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/. - -#ifndef _SLACK_INPUT_H_ -#define _SLACK_INPUT_H_ - -int slack_input_data_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *input_data); - -#endif /*SLACK_INPUT_H*/ diff --git a/slack-message.c b/slack-message.c deleted file mode 100644 index b7b1e3a..0000000 --- a/slack-message.c +++ /dev/null @@ -1,249 +0,0 @@ -// 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 - -#include "../weechat-plugin.h" -#include "../slack.h" -#include "../slack-workspace.h" -#include "../slack-channel.h" -#include "../slack-user.h" -#include "../slack-message.h" - -static const char format_regex[] = "<([^>]*?)>"; -static const size_t max_groups = 2; - -char *slack_message_translate_code(struct t_slack_workspace *workspace, - const char *code) -{ - struct t_slack_channel *channel; - struct t_slack_user *user; - size_t resultlen; - char *identifier, *alttext, *result, *symbol, *prefix; - - identifier = strdup(code); - alttext = strchr(identifier, '|'); - if (alttext) - *alttext++ = '\0'; - - switch (identifier[0]) - { - case '#': /* channel */ - if (alttext) - { - prefix = "#"; - symbol = strdup(alttext); - } - else - { - channel = slack_channel_search(workspace, identifier+1); - if (channel) - { - prefix = "#"; - symbol = strdup(channel->name); - } - else - { - prefix = "Channel:"; - symbol = strdup(identifier+1); - } - } - break; - case '@': /* user */ - if (alttext) - { - prefix = "@"; - symbol = strdup(alttext); - } - else - { - user = slack_user_search(workspace, identifier+1); - if (user) - { - prefix = "@"; - symbol = strdup(user->profile.display_name); - } - else - { - prefix = "User:"; - symbol = strdup(identifier+1); - } - } - break; - case '!': /* special */ - if (alttext) - { - prefix = "@"; - symbol = strdup(alttext); - } - else - { - prefix = "@"; - symbol = strdup(identifier+1); - } - break; - default: /* url */ - prefix = ""; - symbol = strdup(code); - break; - } - - free(identifier); - resultlen = snprintf(NULL, 0, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")) + 1; - result = malloc(resultlen); - snprintf(result, resultlen, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")); - free(symbol); - - return result; -} - -void slack_message_htmldecode(char *dest, const char *src, size_t n) -{ - size_t i, j; - - for (i = 0, j = 0; i < n; i++, j++) - switch (src[i]) - { - case '\0': - dest[j] = '\0'; - return; - case '&': - if (src[i+1] == 'g' && - src[i+2] == 't' && - src[i+3] == ';') - { - dest[j] = '>'; - i += 3; - break; - } - else if (src[i+1] == 'l' && - src[i+2] == 't' && - src[i+3] == ';') - { - dest[j] = '<'; - i += 3; - break; - } - else if (src[i+1] == 'a' && - src[i+2] == 'm' && - src[i+3] == 'p' && - src[i+4] == ';') - { - dest[j] = '&'; - i += 4; - break; - } - /* fallthrough */ - default: - dest[j] = src[i]; - break; - } - dest[j-1] = '\0'; - return; -} - -char *slack_message_decode(struct t_slack_workspace *workspace, - const char *text) -{ - int rc; - regex_t reg; - regmatch_t groups[max_groups]; - char msgbuf[100]; - char *decoded_text; - const char *cursor; - size_t offset; - - if ((rc = regcomp(®, format_regex, REG_EXTENDED))) - { - regerror(rc, ®, msgbuf, sizeof(msgbuf)); - weechat_printf( - workspace->buffer, - _("%s%s: error compiling message formatting regex: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - msgbuf); - return strdup(text); - } - - decoded_text = malloc(SLACK_MESSAGE_MAX_LENGTH); - if (!decoded_text) - { - regfree(®); - weechat_printf( - workspace->buffer, - _("%s%s: error allocating space for message"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return strdup(text); - } - decoded_text[0] = '\0'; - - for (cursor = text; regexec(®, cursor, max_groups, groups, 0) == 0; cursor += offset) - { - offset = groups[0].rm_eo; - - char *copy = strdup(cursor); - if (!copy) - { - regfree(®); - free(decoded_text); - weechat_printf( - workspace->buffer, - _("%s%s: error allocating space for message"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return strdup(text); - } - copy[groups[1].rm_eo] = '\0'; - - char *match = strdup(copy + groups[1].rm_so); - if (!match) - { - free(copy); - regfree(®); - free(decoded_text); - weechat_printf( - workspace->buffer, - _("%s%s: error allocating space for message"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return strdup(text); - } - copy[groups[0].rm_so] = '\0'; - - char *prematch = strdup(copy); - if (!prematch) - { - free(match); - free(copy); - regfree(®); - free(decoded_text); - weechat_printf( - workspace->buffer, - _("%s%s: error allocating space for message"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return strdup(text); - } - free(copy); - - strncat(decoded_text, prematch, - SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); - free(prematch); - - char *replacement = slack_message_translate_code(workspace, match); - free(match); - - strncat(decoded_text, replacement, - SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); - free(replacement); - } - strncat(decoded_text, cursor, - SLACK_MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); - - slack_message_htmldecode(decoded_text, decoded_text, - SLACK_MESSAGE_MAX_LENGTH); - - regfree(®); - return decoded_text; -} diff --git a/slack-message.h b/slack-message.h deleted file mode 100644 index d223ba2..0000000 --- a/slack-message.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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/. - -#ifndef _SLACK_MESSAGE_H_ -#define _SLACK_MESSAGE_H_ - -#define SLACK_MESSAGE_MAX_LENGTH 40000 - -char *slack_message_decode(struct t_slack_workspace *workspace, - const char *text); - -#endif /*SLACK_MESSAGE_H*/ diff --git a/slack-oauth.c b/slack-oauth.c deleted file mode 100644 index be9f52d..0000000 --- a/slack-oauth.c +++ /dev/null @@ -1,245 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-oauth.h" - -static void (*weechat_callback)(char *token); - -static const char *const endpoint = "/api/oauth.access?" - "client_id=%s&client_secret=%s&code=%s"; -static char *uri; - -static int n = 0; -static struct lws *client_wsi = NULL; -static struct lws_context *context = NULL; - -static struct t_hook *slack_oauth_hook_timer = NULL; - -static inline int json_valid(json_object *object) -{ - if (!object) - { - weechat_printf( - NULL, - _("%s%s: error retrieving token: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return 0; - } - - return 1; -} - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - NULL, - _("%s%s: error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - in ? (char *)in : "(null)"); - client_wsi = NULL; - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - NULL, - _("%s%s: retrieving token... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - char *json_string = weechat_strndup(in, (int)len); - json_object *response, *ok, *error, *token; - - weechat_printf( - NULL, - _("%s%s: got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - token = json_object_object_get(response, "access_token"); - if (!json_valid(token)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - NULL, - _("%s%s: retrieved token: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - json_object_get_string(token)); - - weechat_callback(strdup(json_object_get_string(token))); - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - NULL, - _("%s%s: failed to retrieve token: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -int slack_oauth_timer_cb(const void *pointer, void *data, int remaining_calls) -{ - (void) pointer; - (void) data; - (void) remaining_calls; - - if (n >= 0 && client_wsi) - { - n = lws_service(context, 0); - } - else if (context) - { - lws_context_destroy(context); - context = NULL; - free(uri); - - if (slack_oauth_hook_timer) - weechat_unhook(slack_oauth_hook_timer); - } - - return WEECHAT_RC_OK; -} - -void slack_oauth_request_token(char *code, void (*callback)(char *token)) -{ - struct lws_context_creation_info info; - struct lws_client_connect_info i; - - if (client_wsi) - { - weechat_printf( - NULL, - _("%s%s: error: a registration is already in progress"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - - size_t urilen = snprintf(NULL, 0, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code) + 1; - uri = malloc(urilen); - snprintf(uri, urilen, endpoint, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, code); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - info.protocols = protocols; - - context = lws_create_context(&info); - if (!context) - { - weechat_printf( - NULL, - _("%s%s: error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - else - { - weechat_printf( - NULL, - _("%s%s: contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - } - - memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ - i.context = context; - i.ssl_connection = LCCSCF_USE_SSL; - i.port = 443; - i.address = "slack.com"; - i.path = uri; - i.host = i.address; - i.origin = i.address; - i.method = "GET"; - i.protocol = protocols[0].name; - i.pwsi = &client_wsi; - - lws_client_connect_via_info(&i); - - slack_oauth_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, - &slack_oauth_timer_cb, - NULL, NULL); - - weechat_callback = callback; -} diff --git a/slack-oauth.h b/slack-oauth.h deleted file mode 100644 index d7a6538..0000000 --- a/slack-oauth.h +++ /dev/null @@ -1,10 +0,0 @@ -// 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/. - -#ifndef _SLACK_OAUTH_H_ -#define _SLACK_OAUTH_H_ - -extern void slack_oauth_request_token(char *code, void (*callback)(char *token)); - -#endif /*SLACK_OAUTH_H*/ diff --git a/slack-request.c b/slack-request.c deleted file mode 100644 index 50c185e..0000000 --- a/slack-request.c +++ /dev/null @@ -1,27 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-request.h" - -struct t_slack_request *slack_request_alloc( - struct t_slack_workspace *workspace) -{ - struct t_slack_request *request; - - request = malloc(sizeof(struct t_slack_request)); - memset(request, 0, sizeof(struct t_slack_request)); - - request->workspace = workspace; - request->idx = workspace->idx++; - - return request; -} diff --git a/slack-request.h b/slack-request.h deleted file mode 100644 index 675d947..0000000 --- a/slack-request.h +++ /dev/null @@ -1,29 +0,0 @@ -// 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/. - -#ifndef _SLACK_REQUEST_H_ -#define _SLACK_REQUEST_H_ - -struct t_slack_request -{ - struct t_slack_workspace *workspace; - - int idx; - - const void *pointer; - void *data; - - char *uri; - struct lws *client_wsi; - struct lws_context *context; - struct t_json_chunk *json_chunks; - - struct t_slack_request *prev_request; - struct t_slack_request *next_request; -}; - -struct t_slack_request *slack_request_alloc( - struct t_slack_workspace *workspace); - -#endif /*SLACK_REQUEST_H*/ diff --git a/slack-teaminfo.c b/slack-teaminfo.c deleted file mode 100644 index 51ec2f7..0000000 --- a/slack-teaminfo.c +++ /dev/null @@ -1,348 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-teaminfo.h" - -static void (*weechat_callback)(struct t_slack_teaminfo *slack_teaminfo); - -static const char *const endpoint = "/api/team.info?" - "token=%s"; -static char *uri; - -static int n = 0; -static struct lws *client_wsi = NULL; -static struct lws_context *context = NULL; - -static struct t_hook *slack_teaminfo_hook_timer = NULL; - -struct t_json_chunk -{ - char *data; - struct t_json_chunk *next; -}; - -static struct t_json_chunk *slack_teaminfo_chunks = NULL; -static struct t_slack_teaminfo slack_teaminfo; - -static inline int json_valid(json_object *object) -{ - if (!object) - { - weechat_printf( - NULL, - _("%s%s: error retrieving workspace info: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return 0; - } - - return 1; -} - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - NULL, - _("%s%s: error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - in ? (char *)in : "(null)"); - client_wsi = NULL; - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - NULL, - _("%s%s: retrieving workspace details... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (slack_teaminfo_chunks) - { - for (last_chunk = slack_teaminfo_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - slack_teaminfo_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - json_object *response, *ok, *error, *team; - json_object *id, *name, *domain, *email_domain; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (slack_teaminfo_chunks) - { - chunk_count++; - for (chunk_ptr = slack_teaminfo_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = slack_teaminfo_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(slack_teaminfo_chunks->data); - free(slack_teaminfo_chunks); - slack_teaminfo_chunks = chunk_ptr; - } - - weechat_printf( - NULL, - _("%s%s: got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - team = json_object_object_get(response, "team"); - if (!json_valid(team)) - { - json_object_put(response); - free(json_string); - return 0; - } - - id = json_object_object_get(team, "id"); - if (!json_valid(id)) - { - json_object_put(response); - free(json_string); - return 0; - } - - name = json_object_object_get(team, "name"); - if (!json_valid(name)) - { - json_object_put(response); - free(json_string); - return 0; - } - - domain = json_object_object_get(team, "domain"); - if (!json_valid(domain)) - { - json_object_put(response); - free(json_string); - return 0; - } - - email_domain = json_object_object_get(team, "email_domain"); - if (!json_valid(email_domain)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - NULL, - _("%s%s: retrieved workspace details for %s@%s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - json_object_get_string(name), json_object_get_string(domain)); - - slack_teaminfo.id = json_object_get_string(id); - slack_teaminfo.name = json_object_get_string(name); - slack_teaminfo.domain = json_object_get_string(domain); - slack_teaminfo.email_domain = json_object_get_string(email_domain); - - weechat_callback(&slack_teaminfo); - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - NULL, - _("%s%s: failed to retrieve workspace details: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -int slack_teaminfo_timer_cb(const void *pointer, void *data, int remaining_calls) -{ - (void) pointer; - (void) data; - (void) remaining_calls; - - if (n >= 0 && client_wsi) - { - n = lws_service(context, 0); - } - else if (context) - { - lws_context_destroy(context); - context = NULL; - free(uri); - - if (slack_teaminfo_hook_timer) - weechat_unhook(slack_teaminfo_hook_timer); - } - - return WEECHAT_RC_OK; -} - -void slack_teaminfo_fetch(char *token, void (*callback)(struct t_slack_teaminfo *slack_teaminfo)) -{ - struct lws_context_creation_info info; - struct lws_client_connect_info i; - - if (client_wsi) - { - weechat_printf( - NULL, - _("%s%s: error: a registration is already in progress"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - - slack_teaminfo.token = strdup(token); - - size_t urilen = snprintf(NULL, 0, endpoint, token) + 1; - uri = malloc(urilen); - snprintf(uri, urilen, endpoint, token); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - info.protocols = protocols; - - context = lws_create_context(&info); - if (!context) - { - weechat_printf( - NULL, - _("%s%s: error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - else - { - weechat_printf( - NULL, - _("%s%s: contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - } - - memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ - i.context = context; - i.ssl_connection = LCCSCF_USE_SSL; - i.port = 443; - i.address = "slack.com"; - i.path = uri; - i.host = i.address; - i.origin = i.address; - i.method = "GET"; - i.protocol = protocols[0].name; - i.pwsi = &client_wsi; - - lws_client_connect_via_info(&i); - - slack_teaminfo_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, - &slack_teaminfo_timer_cb, - NULL, NULL); - - weechat_callback = callback; -} - -void free_teaminfo(struct t_slack_teaminfo *teaminfo) -{ - free(teaminfo->token); -} diff --git a/slack-teaminfo.h b/slack-teaminfo.h deleted file mode 100644 index 67bd5d2..0000000 --- a/slack-teaminfo.h +++ /dev/null @@ -1,20 +0,0 @@ -// 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/. - -#ifndef _SLACK_TEAMINFO_H_ -#define _SLACK_TEAMINFO_H_ - -struct t_slack_teaminfo -{ - const char *id; - const char *name; - const char *domain; - const char *email_domain; - char *token; -}; - -extern void slack_teaminfo_fetch(char *token, void (*callback)(struct t_slack_teaminfo *slack_teaminfo)); -extern void free_teaminfo(struct t_slack_teaminfo *teaminfo); - -#endif /*SLACK_TEAMINFO_H*/ diff --git a/slack-user.c b/slack-user.c deleted file mode 100644 index ff3fcd2..0000000 --- a/slack-user.c +++ /dev/null @@ -1,241 +0,0 @@ -// 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 "weechat-plugin.h" -#include "slack.h" -#include "slack-workspace.h" -#include "slack-user.h" -#include "slack-channel.h" - -const char *slack_user_get_colour(struct t_slack_user *user) -{ - return weechat_info_get("nick_color", user->profile.display_name); -} - -const char *slack_user_get_colour_for_nicklist(struct t_slack_user *user) -{ - return weechat_info_get("nick_color_name", user->profile.display_name); -} - -const char *slack_user_as_prefix(struct t_slack_workspace *workspace, - struct t_slack_user *user, - const char *name) -{ - static char result[256]; - - (void) workspace; - - snprintf(result, sizeof(result), "%s%s\t", - slack_user_get_colour(user), - name ? name : user->profile.display_name); - - return result; -} - -struct t_slack_user *slack_user_bot_search(struct t_slack_workspace *workspace, - const char *bot_id) -{ - struct t_slack_user *ptr_user; - - if (!workspace || !bot_id) - return NULL; - - for (ptr_user = workspace->users; ptr_user; - ptr_user = ptr_user->next_user) - { - if (ptr_user->profile.bot_id && - weechat_strcasecmp(ptr_user->profile.bot_id, bot_id) == 0) - return ptr_user; - } - - return NULL; -} - -struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, - const char *id) -{ - struct t_slack_user *ptr_user; - - if (!workspace || !id) - return NULL; - - for (ptr_user = workspace->users; ptr_user; - ptr_user = ptr_user->next_user) - { - if (weechat_strcasecmp(ptr_user->id, id) == 0) - return ptr_user; - } - - return NULL; -} - -void slack_user_nicklist_add(struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - struct t_slack_user *user) -{ - struct t_gui_nick_group *ptr_group; - struct t_gui_buffer *ptr_buffer; - - ptr_buffer = channel ? channel->buffer : workspace->buffer; - - ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, - user->is_away ? - "+" : "..."); - weechat_nicklist_add_nick(ptr_buffer, ptr_group, - user->profile.display_name, - user->is_away ? - "weechat.color.nicklist_away" : - slack_user_get_colour_for_nicklist(user), - user->is_away ? "+" : "", - "bar_fg", - 1); -} - -struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, - const char *id, const char *display_name) -{ - struct t_slack_user *new_user, *ptr_user; - - if (!workspace || !id || !display_name) - { - return NULL; - } - - if (!display_name[0] && strcmp("USLACKBOT", id) == 0) - return NULL; - - if (!workspace->users) - slack_channel_add_nicklist_groups(workspace, NULL); - - ptr_user = slack_user_search(workspace, id); - if (ptr_user) - { - slack_user_nicklist_add(workspace, NULL, ptr_user); - return ptr_user; - } - - if ((new_user = malloc(sizeof(*new_user))) == NULL) - { - return NULL; - } - - new_user->prev_user = workspace->last_user; - new_user->next_user = NULL; - if (workspace->last_user) - (workspace->last_user)->next_user = new_user; - else - workspace->users = new_user; - workspace->last_user = new_user; - - new_user->id = strdup(id); - new_user->name = NULL; - new_user->team_id = NULL; - new_user->real_name = NULL; - new_user->colour = NULL; - new_user->deleted = 0; - - new_user->tz = NULL; - new_user->tz_label = NULL; - new_user->tz_offset = 0; - new_user->locale = NULL; - - new_user->profile.avatar_hash = NULL; - new_user->profile.status_text = NULL; - new_user->profile.status_emoji = NULL; - new_user->profile.real_name = NULL; - new_user->profile.display_name = display_name[0] ? - strdup(display_name) : - strdup("slackbot"); - new_user->profile.real_name_normalized = NULL; - new_user->profile.email = NULL; - new_user->profile.team = NULL; - new_user->profile.bot_id = NULL; - new_user->updated = 0; - new_user->is_away = 0; - - new_user->is_admin = 0; - new_user->is_owner = 0; - new_user->is_primary_owner = 0; - new_user->is_restricted = 0; - new_user->is_ultra_restricted = 0; - new_user->is_bot = 0; - new_user->is_stranger = 0; - new_user->is_app_user = 0; - new_user->has_2fa = 0; - - slack_user_nicklist_add(workspace, NULL, new_user); - - return new_user; -} - -void slack_user_free(struct t_slack_workspace *workspace, - struct t_slack_user *user) -{ - struct t_slack_user *new_users; - - if (!workspace || !user) - return; - - /* remove user from users list */ - if (workspace->last_user == user) - workspace->last_user = user->prev_user; - if (user->prev_user) - { - (user->prev_user)->next_user = user->next_user; - new_users = workspace->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->team_id) - free(user->team_id); - if (user->real_name) - free(user->real_name); - if (user->colour) - free(user->colour); - if (user->tz) - free(user->tz); - if (user->tz_label) - free(user->tz_label); - if (user->locale) - free(user->locale); - if (user->profile.avatar_hash) - free(user->profile.avatar_hash); - if (user->profile.status_text) - free(user->profile.status_text); - if (user->profile.status_emoji) - free(user->profile.status_emoji); - if (user->profile.real_name) - free(user->profile.real_name); - if (user->profile.display_name) - free(user->profile.display_name); - if (user->profile.real_name_normalized) - free(user->profile.real_name_normalized); - if (user->profile.email) - free(user->profile.email); - if (user->profile.team) - free(user->profile.team); - - free(user); - - workspace->users = new_users; -} - -void slack_user_free_all(struct t_slack_workspace *workspace) -{ - while (workspace->users) - slack_user_free(workspace, workspace->users); -} diff --git a/slack-user.h b/slack-user.h deleted file mode 100644 index cc97ec4..0000000 --- a/slack-user.h +++ /dev/null @@ -1,74 +0,0 @@ -// 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/. - -#ifndef _SLACK_USER_H_ -#define _SLACK_USER_H_ - -struct t_slack_user_profile -{ - char *avatar_hash; - char *status_text; - char *status_emoji; - char *real_name; - char *display_name; - char *real_name_normalized; - char *email; - char *team; - char *bot_id; -}; - -struct t_slack_user -{ - char *id; - char *name; - char *team_id; - char *real_name; - char *colour; - - int deleted; - char *tz; - char *tz_label; - int tz_offset; - char *locale; - - struct t_slack_user_profile profile; - int updated; - int is_away; - - int is_admin; - int is_owner; - int is_primary_owner; - int is_restricted; - int is_ultra_restricted; - int is_bot; - int is_stranger; - int is_app_user; - int has_2fa; - - struct t_slack_user *prev_user; - struct t_slack_user *next_user; -}; - -const char *slack_user_get_colour(struct t_slack_user *user); - -const char *slack_user_as_prefix(struct t_slack_workspace *workspace, - struct t_slack_user *user, - const char *name); - -struct t_slack_user *slack_user_bot_search(struct t_slack_workspace *workspace, - const char *bot_id); - -struct t_slack_user *slack_user_search(struct t_slack_workspace *workspace, - const char *id); - -struct t_slack_user *slack_user_new(struct t_slack_workspace *workspace, - const char *id, const char *display_name); - -void slack_user_free_all(struct t_slack_workspace *workspace); - -void slack_user_nicklist_add(struct t_slack_workspace *workspace, - struct t_slack_channel *channel, - struct t_slack_user *user); - -#endif /*SLACK_USER_H*/ diff --git a/slack-workspace.c b/slack-workspace.c deleted file mode 100644 index 358cb24..0000000 --- a/slack-workspace.c +++ /dev/null @@ -1,972 +0,0 @@ -// 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 -#include - -#include "weechat-plugin.h" -#include "slack.h" -#include "slack-config.h" -#include "slack-input.h" -#include "slack-workspace.h" -#include "slack-api.h" -#include "slack-request.h" -#include "slack-user.h" -#include "slack-channel.h" -#include "slack-buffer.h" - -struct t_slack_workspace *slack_workspaces = NULL; -struct t_slack_workspace *last_slack_workspace = NULL; - -char *slack_workspace_options[SLACK_WORKSPACE_NUM_OPTIONS][2] = -{ { "token", "" }, -}; - -static const char *const endpoint = "/api/rtm.connect?" - "token=%s&batch_presence_aware=true&presence_sub=false&"; - -static inline int json_valid(json_object *object, struct t_slack_workspace *workspace) -{ - if (!object) - { - weechat_printf( - workspace->buffer, - _("%s%s: error requesting websocket: unexpected response from server"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return 0; - } - - return 1; -} - -static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct t_slack_workspace *workspace = (struct t_slack_workspace *)user; - int status; - - switch (reason) - { - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - weechat_printf( - workspace->buffer, - _("%s%s: error connecting to slack: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - in ? (char *)in : "(null)"); - workspace->client_wsi = NULL; - break; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - status = lws_http_client_http_response(wsi); - weechat_printf( - workspace->buffer, - _("%s%s: requesting a websocket... (%d)"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - status); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - { - struct t_json_chunk *new_chunk, *last_chunk; - - new_chunk = malloc(sizeof(*new_chunk)); - new_chunk->data = malloc((1024 * sizeof(char)) + 1); - new_chunk->data[0] = '\0'; - new_chunk->next = NULL; - - strncat(new_chunk->data, in, (int)len); - - if (workspace->json_chunks) - { - for (last_chunk = workspace->json_chunks; last_chunk->next; - last_chunk = last_chunk->next); - last_chunk->next = new_chunk; - } - else - { - workspace->json_chunks = new_chunk; - } - } - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - { - int chunk_count, i; - char *json_string; - json_object *response, *ok, *error, *self, *team, *url; - json_object *id, *name, *domain; - struct t_json_chunk *chunk_ptr; - - chunk_count = 0; - if (workspace->json_chunks) - { - chunk_count++; - for (chunk_ptr = workspace->json_chunks; chunk_ptr->next; - chunk_ptr = chunk_ptr->next) - { - chunk_count++; - } - } - - json_string = malloc((1024 * sizeof(char) * chunk_count) + 1); - json_string[0] = '\0'; - - chunk_ptr = workspace->json_chunks; - for (i = 0; i < chunk_count; i++) - { - strncat(json_string, chunk_ptr->data, 1024); - chunk_ptr = chunk_ptr->next; - - free(workspace->json_chunks->data); - free(workspace->json_chunks); - workspace->json_chunks = chunk_ptr; - } - - weechat_printf( - workspace->buffer, - _("%s%s: got response: %s"), - weechat_prefix("network"), SLACK_PLUGIN_NAME, - json_string); - - response = json_tokener_parse(json_string); - ok = json_object_object_get(response, "ok"); - if (!json_valid(ok, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - if(json_object_get_boolean(ok)) - { - self = json_object_object_get(response, "self"); - if (!json_valid(self, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - else - { - id = json_object_object_get(self, "id"); - if (!json_valid(id, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - workspace->user = strdup(json_object_get_string(id)); - - name = json_object_object_get(self, "name"); - if (!json_valid(name, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - workspace->nick = strdup(json_object_get_string(name)); - } - - team = json_object_object_get(response, "team"); - if (!json_valid(team, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - else - { - domain = json_object_object_get(team, "domain"); - if (!json_valid(domain, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - id = json_object_object_get(team, "id"); - if (!json_valid(id, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - workspace->id = strdup(json_object_get_string(id)); - - name = json_object_object_get(team, "name"); - if (!json_valid(name, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - workspace->name = strdup(json_object_get_string(name)); - } - - url = json_object_object_get(response, "url"); - if (!json_valid(url, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - workspace->ws_url = strdup(json_object_get_string(url)); - } - else - { - error = json_object_object_get(response, "error"); - if (!json_valid(error, workspace)) - { - json_object_put(response); - free(json_string); - return 0; - } - - weechat_printf( - workspace->buffer, - _("%s%s: failed to request websocket: %s"), - weechat_prefix("error"), SLACK_PLUGIN_NAME, - json_object_get_string(error)); - } - - json_object_put(response); - free(json_string); - } - /* fallthrough */ - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - workspace->client_wsi = NULL; - /* Does not doing this cause a leak? - lws_cancel_service(lws_get_context(wsi));*/ /* abort poll wait */ - break; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); -} - -static const struct lws_protocols protocols[] = { - { - "http", - callback_http, - 0, - 0, - }, - { NULL, NULL, 0, 0 } -}; - -struct t_slack_workspace *slack_workspace_search(const char *workspace_domain) -{ - struct t_slack_workspace *ptr_workspace; - - if (!workspace_domain) - return NULL; - - for (ptr_workspace = slack_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) - { - if (strcmp(ptr_workspace->domain, workspace_domain) == 0) - return ptr_workspace; - } - - /* workspace not found */ - return NULL; -} - -struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_domain) -{ - struct t_slack_workspace *ptr_workspace; - - if (!workspace_domain) - return NULL; - - for (ptr_workspace = slack_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) - { - if (weechat_strcasecmp (ptr_workspace->domain, workspace_domain) == 0) - return ptr_workspace; - } - - /* workspace not found */ - return NULL; -} - -int slack_workspace_search_option(const char *option_name) -{ - int i; - - if (!option_name) - return -1; - - for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) - { - if (weechat_strcasecmp(slack_workspace_options[i][0], option_name) == 0) - return i; - } - - /* workspace option not found */ - return -1; -} - -struct t_slack_workspace *slack_workspace_alloc(const char *domain) -{ - struct t_slack_workspace *new_workspace; - int i, length; - char *option_name; - - if (slack_workspace_casesearch(domain)) - return NULL; - - /* alloc memory for new workspace */ - new_workspace = malloc(sizeof(*new_workspace)); - if (!new_workspace) - { - weechat_printf(NULL, - _("%s%s: error when allocating new workspace"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return NULL; - } - - /* add new workspace to queue */ - new_workspace->prev_workspace = last_slack_workspace; - new_workspace->next_workspace = NULL; - if (last_slack_workspace) - last_slack_workspace->next_workspace = new_workspace; - else - slack_workspaces = new_workspace; - last_slack_workspace = new_workspace; - - /* set properties */ - new_workspace->id = NULL; - new_workspace->name = NULL; - - /* set name */ - new_workspace->domain = strdup(domain); - - /* internal vars */ - new_workspace->reloading_from_config = 0; - new_workspace->reloaded_from_config = 0; - - new_workspace->is_connected = 0; - new_workspace->disconnected = 0; - - new_workspace->idx = 0; - new_workspace->uri = NULL; - new_workspace->ws_url = NULL; - new_workspace->client_wsi = NULL; - new_workspace->context = NULL; - new_workspace->json_chunks = NULL; - new_workspace->requests = NULL; - new_workspace->last_request = NULL; - - new_workspace->user = NULL; - new_workspace->nick = NULL; - - new_workspace->buffer = NULL; - new_workspace->buffer_as_string = NULL; - new_workspace->users = NULL; - new_workspace->last_user = NULL; - new_workspace->channels = NULL; - new_workspace->last_channel = NULL; - new_workspace->emoji = NULL; - new_workspace->last_emoji = NULL; - - /* create options with null value */ - for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) - { - length = strlen(new_workspace->domain) + 1 + - strlen(slack_workspace_options[i][0]) + - 512 + /* inherited option name(slack.workspace_default.xxx) */ - 1; - option_name = malloc(length); - if (option_name) - { - snprintf(option_name, length, "%s.%s << slack.workspace_default.%s", - new_workspace->domain, - slack_workspace_options[i][0], - slack_workspace_options[i][0]); - new_workspace->options[i] = slack_config_workspace_new_option( - slack_config_file, - slack_config_section_workspace, - i, - option_name, - NULL, - NULL, - 1, - &slack_config_workspace_check_value_cb, - slack_workspace_options[i][0], - NULL, - &slack_config_workspace_change_cb, - slack_workspace_options[i][0], - NULL); - slack_config_workspace_change_cb(slack_workspace_options[i][0], NULL, - new_workspace->options[i]); - free(option_name); - } - } - - return new_workspace; -} - -void slack_workspace_free_data(struct t_slack_workspace *workspace) -{ - int i; - - if (!workspace) - return; - - /* free linked lists */ - /* - for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) - { - slack_workspace_outqueue_free_all(workspace, i); - } - slack_redirect_free_all(workspace); - slack_notify_free_all(workspace); - */ - slack_channel_free_all(workspace); - slack_user_free_all(workspace); - - /* free hashtables */ - /* - weechat_hashtable_free(workspace->join_manual); - weechat_hashtable_free(workspace->join_channel_key); - weechat_hashtable_free(workspace->join_noswitch); - */ - - /* free workspace data */ - for (i = 0; i < SLACK_WORKSPACE_NUM_OPTIONS; i++) - { - if (workspace->options[i]) - weechat_config_option_free(workspace->options[i]); - } - if (workspace->id) - free(workspace->id); - if (workspace->name) - free(workspace->name); - if (workspace->domain) - free(workspace->domain); - - if (workspace->uri) - free(workspace->uri); - if (workspace->ws_url) - free(workspace->ws_url); - if (workspace->context) - lws_context_destroy(workspace->context); - while (workspace->json_chunks) - { - struct t_json_chunk *chunk_ptr = workspace->json_chunks->next; - - free(workspace->json_chunks->data); - free(workspace->json_chunks); - workspace->json_chunks = chunk_ptr; - } - while (workspace->requests) - { - struct t_slack_request *request_ptr = workspace->requests->next_request; - - workspace->requests->client_wsi = NULL; - if (workspace->requests->context) - { - lws_context_destroy(workspace->requests->context); - workspace->requests->context = NULL; - if (workspace->requests->uri) - { - free(workspace->requests->uri); - workspace->requests->uri = NULL; - } - } - free(workspace->requests); - workspace->requests = request_ptr; - } - - if (workspace->user) - free(workspace->user); - if (workspace->nick) - free(workspace->nick); - - if (workspace->buffer_as_string) - free(workspace->buffer_as_string); - - slack_channel_free_all(workspace); - slack_user_free_all(workspace); -} - -void slack_workspace_free(struct t_slack_workspace *workspace) -{ - struct t_slack_workspace *new_slack_workspaces; - - if (!workspace) - return; - - /* - * close workspace buffer (and all channels/privates) - * (only if we are not in a /upgrade, because during upgrade we want to - * keep connections and closing workspace buffer would disconnect from workspace) - */ - if (workspace->buffer) - weechat_buffer_close(workspace->buffer); - - /* remove workspace from queue */ - if (last_slack_workspace == workspace) - last_slack_workspace = workspace->prev_workspace; - if (workspace->prev_workspace) - { - (workspace->prev_workspace)->next_workspace = workspace->next_workspace; - new_slack_workspaces = slack_workspaces; - } - else - new_slack_workspaces = workspace->next_workspace; - - if (workspace->next_workspace) - (workspace->next_workspace)->prev_workspace = workspace->prev_workspace; - - slack_workspace_free_data(workspace); - free(workspace); - slack_workspaces = new_slack_workspaces; -} - -void slack_workspace_free_all() -{ - /* for each workspace in memory, remove it */ - while (slack_workspaces) - { - slack_workspace_free(slack_workspaces); - } -} - -void slack_workspace_disconnect(struct t_slack_workspace *workspace, - int reconnect) -{ - (void) reconnect; - - struct t_slack_channel *ptr_channel; - (void) ptr_channel; - - if (workspace->is_connected) - { - /* - * remove all nicks and write disconnection message on each - * channel/private buffer - */ - slack_user_free_all(workspace); - weechat_nicklist_remove_all(workspace->buffer); - for (ptr_channel = workspace->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) - { - weechat_nicklist_remove_all(ptr_channel->buffer); - weechat_printf( - ptr_channel->buffer, - _("%s%s: disconnected from workspace"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - } - /* remove away status on workspace buffer */ - //weechat_buffer_set(workspace->buffer, "localvar_del_away", ""); - } - - slack_workspace_close_connection(workspace); - - if (workspace->buffer) - { - weechat_printf( - workspace->buffer, - _("%s%s: disconnected from workspace"), - weechat_prefix ("network"), SLACK_PLUGIN_NAME); - } - - /* - workspace->current_retry = 0; - - if (switch_address) - slack_workspace_switch_address(workspace, 0); - else - slack_workspace_set_index_current_address(workspace, 0); - - if (workspace->nick_modes) - { - free (workspace->nick_modes); - workspace->nick_modes = NULL; - weechat_bar_item_update ("input_prompt"); - weechat_bar_item_update ("slack_nick_modes"); - } - workspace->cap_away_notify = 0; - workspace->cap_account_notify = 0; - workspace->cap_extended_join = 0; - workspace->is_away = 0; - workspace->away_time = 0; - workspace->lag = 0; - workspace->lag_displayed = -1; - workspace->lag_check_time.tv_sec = 0; - workspace->lag_check_time.tv_usec = 0; - workspace->lag_next_check = time (NULL) + - weechat_config_integer (slack_config_network_lag_check); - workspace->lag_last_refresh = 0; - slack_workspace_set_lag (workspace); - workspace->monitor = 0; - workspace->monitor_time = 0; - - if (reconnect - && IRC_SERVER_OPTION_BOOLEAN(workspace, IRC_SERVER_OPTION_AUTORECONNECT)) - slack_workspace_reconnect_schedule(workspace); - else - { - workspace->reconnect_delay = 0; - workspace->reconnect_start = 0; - } - */ - - /* discard current nick if no reconnection asked */ - /* - if (!reconnect && workspace->nick) - slack_workspace_set_nick(workspace, NULL); - - slack_workspace_set_buffer_title(workspace); - - workspace->disconnected = 1; - */ - - /* send signal "slack_workspace_disconnected" with workspace name */ - /* - (void) weechat_hook_signal_send("slack_workspace_disconnected", - WEECHAT_HOOK_SIGNAL_STRING, workspace->name); - */ -} - -void slack_workspace_disconnect_all() -{ - struct t_slack_workspace *ptr_workspace; - - for (ptr_workspace = slack_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) - { - slack_workspace_disconnect(ptr_workspace, 0); - } -} - -struct t_gui_buffer *slack_workspace_create_buffer(struct t_slack_workspace *workspace) -{ - char buffer_name[256], charset_modifier[256]; - - snprintf(buffer_name, sizeof(buffer_name), - "workspace.%s", workspace->domain); - workspace->buffer = weechat_buffer_new(buffer_name, - &slack_input_data_cb, NULL, NULL, - &slack_buffer_close_cb, NULL, NULL); - if (!workspace->buffer) - return NULL; - - if (!weechat_buffer_get_integer(workspace->buffer, "short_name_is_set")) - weechat_buffer_set(workspace->buffer, "short_name", workspace->domain); - weechat_buffer_set(workspace->buffer, "localvar_set_type", "server"); - weechat_buffer_set(workspace->buffer, "localvar_set_server", workspace->domain); - weechat_buffer_set(workspace->buffer, "localvar_set_channel", workspace->domain); - snprintf(charset_modifier, sizeof (charset_modifier), - "workspace.%s", workspace->domain); - weechat_buffer_set(workspace->buffer, "localvar_set_charset_modifier", - charset_modifier); - weechat_buffer_set(workspace->buffer, "title", - (workspace->name) ? workspace->name : ""); - - weechat_buffer_set(workspace->buffer, "nicklist", "1"); - weechat_buffer_set(workspace->buffer, "nicklist_display_groups", "0"); - weechat_buffer_set_pointer(workspace->buffer, "nicklist_callback", - &slack_buffer_nickcmp_cb); - weechat_buffer_set_pointer(workspace->buffer, "nicklist_callback_pointer", - workspace); - - return workspace->buffer; -} - -void slack_workspace_close_connection(struct t_slack_workspace *workspace) -{ - struct t_slack_request *ptr_request; - - workspace->is_connected = 0; - workspace->client_wsi = NULL; - workspace->context = NULL; - - for (ptr_request = workspace->requests; ptr_request; - ptr_request = ptr_request->next_request) - { - if (ptr_request->context) - { - struct t_slack_request *new_requests; - - lws_context_destroy(ptr_request->context); - ptr_request->context = NULL; - if (ptr_request->uri) - { - free(ptr_request->uri); - ptr_request->uri = NULL; - } - - /* remove request from requests list */ - if (workspace->last_request == ptr_request) - workspace->last_request = ptr_request->prev_request; - if (ptr_request->prev_request) - { - (ptr_request->prev_request)->next_request = ptr_request->next_request; - new_requests = workspace->requests; - } - else - new_requests = ptr_request->next_request; - - if (ptr_request->next_request) - (ptr_request->next_request)->prev_request = ptr_request->prev_request; - - workspace->requests = new_requests; - } - } -} - -void slack_workspace_websocket_create(struct t_slack_workspace *workspace) -{ - struct lws_context_creation_info info; - struct lws_client_connect_info i; - const char *token; - - if (workspace->client_wsi) - { - weechat_printf( - workspace->buffer, - _("%s%s: error: a websocket already exists"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - - token = weechat_config_string(workspace->options[SLACK_WORKSPACE_OPTION_TOKEN]); - - size_t urilen = snprintf(NULL, 0, endpoint, token) + 1; - workspace->uri = malloc(urilen); - snprintf(workspace->uri, urilen, endpoint, token); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ - info.protocols = protocols; - - workspace->context = lws_create_context(&info); - if (!workspace->context) - { - weechat_printf( - workspace->buffer, - _("%s%s: error connecting to slack: lws init failed"), - weechat_prefix("error"), SLACK_PLUGIN_NAME); - return; - } - else - { - weechat_printf( - workspace->buffer, - _("%s%s: contacting slack.com:443"), - weechat_prefix("network"), SLACK_PLUGIN_NAME); - } - - memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ - i.context = workspace->context; - i.ssl_connection = LCCSCF_USE_SSL; - i.port = 443; - i.address = "slack.com"; - i.path = workspace->uri; - i.host = i.address; - i.origin = i.address; - i.method = "GET"; - i.protocol = protocols[0].name; - i.pwsi = &workspace->client_wsi; - i.userdata = workspace; - - lws_client_connect_via_info(&i); - - workspace->is_connected = 1; -} - -int slack_workspace_connect(struct t_slack_workspace *workspace) -{ - workspace->disconnected = 0; - - if (!workspace->buffer) - { - if (!slack_workspace_create_buffer(workspace)) - return 0; - weechat_buffer_set(workspace->buffer, "display", "auto"); - } - - slack_workspace_close_connection(workspace); - - slack_workspace_websocket_create(workspace); - - return 1; -} - -int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls) -{ - struct t_slack_workspace *ptr_workspace; - struct t_slack_request *ptr_request; - - - (void) pointer; - (void) data; - (void) remaining_calls; - - for (ptr_workspace = slack_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) - { - if (!ptr_workspace->is_connected) - continue; - - for (ptr_request = ptr_workspace->requests; ptr_request; - ptr_request = ptr_request->next_request) - { - if (ptr_request->client_wsi) - { - lws_service(ptr_request->context, 0); - } - else if (ptr_request->context) - { - struct t_slack_request *new_requests; - - lws_context_destroy(ptr_request->context); - ptr_request->context = NULL; - if (ptr_request->uri) - { - free(ptr_request->uri); - ptr_request->uri = NULL; - } - ptr_request->pointer = NULL; - if (ptr_request->data) - { - free(ptr_request->data); - ptr_request->data = NULL; - } - - /* remove request from requests list */ - if (ptr_workspace->last_request == ptr_request) - ptr_workspace->last_request = ptr_request->prev_request; - if (ptr_request->prev_request) - { - (ptr_request->prev_request)->next_request = ptr_request->next_request; - new_requests = ptr_workspace->requests; - } - else - new_requests = ptr_request->next_request; - - if (ptr_request->next_request) - (ptr_request->next_request)->prev_request = ptr_request->prev_request; - - ptr_workspace->requests = new_requests; - } - } - - if (ptr_workspace->client_wsi) - { - lws_service(ptr_workspace->context, 0); - } - else if (ptr_workspace->context) - { - lws_context_destroy(ptr_workspace->context); - ptr_workspace->context = NULL; - if (ptr_workspace->uri) - { - free(ptr_workspace->uri); - ptr_workspace->uri = NULL; - } - if (ptr_workspace->ws_url) - { - slack_api_connect(ptr_workspace); - free(ptr_workspace->ws_url); - ptr_workspace->ws_url = NULL; - } - } - } - - return WEECHAT_RC_OK; -} - -void slack_workspace_register_request(struct t_slack_workspace *workspace, - struct t_slack_request *request) -{ - request->prev_request = workspace->last_request; - request->next_request = NULL; - if (workspace->last_request) - (workspace->last_request)->next_request = request; - else - workspace->requests = request; - workspace->last_request = request; -} - -struct t_slack_workspace_emoji *slack_workspace_emoji_search( - struct t_slack_workspace *workspace, - const char *name) -{ - struct t_slack_workspace_emoji *ptr_emoji; - - if (!workspace || !name) - return NULL; - - for (ptr_emoji = workspace->emoji; ptr_emoji; - ptr_emoji = ptr_emoji->next_emoji) - { - if (weechat_strcasecmp(ptr_emoji->name, name) == 0) - return ptr_emoji; - } - - return NULL; -} - -struct t_slack_workspace_emoji *slack_workspace_add_emoji( - struct t_slack_workspace *workspace, - const char *name, const char *url) -{ - struct t_slack_workspace_emoji *ptr_emoji, *new_emoji; - char shortname[SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN + 1]; - - (void) url; - - if (!workspace || !name || !name[0]) - return NULL; - - snprintf(shortname, SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN + 1, - ":%s:", name); - - ptr_emoji = slack_workspace_emoji_search(workspace, shortname); - if (ptr_emoji) - { - return ptr_emoji; - } - - if ((new_emoji = malloc(sizeof(*new_emoji))) == NULL) - return NULL; - - new_emoji->name = strdup(shortname); - new_emoji->url = strdup(url); - - new_emoji->prev_emoji = workspace->last_emoji; - new_emoji->next_emoji = NULL; - if (workspace->last_emoji) - (workspace->last_emoji)->next_emoji = new_emoji; - else - workspace->emoji = new_emoji; - workspace->last_emoji = new_emoji; - - return new_emoji; -} diff --git a/slack-workspace.h b/slack-workspace.h deleted file mode 100644 index 030b4ff..0000000 --- a/slack-workspace.h +++ /dev/null @@ -1,95 +0,0 @@ -// 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/. - -#ifndef _SLACK_WORKSPACE_H_ -#define _SLACK_WORKSPACE_H_ - -#define SLACK_WORKSPACE_EMOJI_SHORTNAME_MAX_LEN 1 + 100 + 1 - -extern struct t_slack_workspace *slack_workspaces; -extern struct t_slack_workspace *last_slack_workspace; - -struct t_slack_workspace_emoji -{ - char *name; - char *url; - - struct t_slack_workspace_emoji *prev_emoji; - struct t_slack_workspace_emoji *next_emoji; -}; - -enum t_slack_workspace_option -{ - SLACK_WORKSPACE_OPTION_TOKEN, - SLACK_WORKSPACE_NUM_OPTIONS, -}; - -struct t_json_chunk -{ - char *data; - struct t_json_chunk *next; -}; - -struct t_slack_workspace -{ - char *id; - char *name; - char *domain; - struct t_config_option *options[SLACK_WORKSPACE_NUM_OPTIONS]; - - int reloading_from_config; - int reloaded_from_config; - - int is_connected; - int disconnected; - - int idx; - char *uri; - char *ws_url; - struct lws *client_wsi; - struct lws_context *context; - struct t_json_chunk *json_chunks; - struct t_slack_request *requests; - struct t_slack_request *last_request; - - char *user; - char *nick; - - struct t_gui_buffer *buffer; - char *buffer_as_string; - struct t_slack_user *users; - struct t_slack_user *last_user; - struct t_slack_channel *channels; - struct t_slack_channel *last_channel; - struct t_slack_workspace_emoji *emoji; - struct t_slack_workspace_emoji *last_emoji; - struct t_slack_workspace *prev_workspace; - struct t_slack_workspace *next_workspace; -}; - -extern char *slack_workspace_options[][2]; - -struct t_slack_workspace *slack_workspace_search(const char *workspace_domain); -struct t_slack_workspace *slack_workspace_casesearch (const char *workspace_domain); -int slack_workspace_search_option(const char *option_name); -struct t_slack_workspace *slack_workspace_alloc(const char *domain); -void slack_workspace_free_data(struct t_slack_workspace *workspace); -void slack_workspace_free(struct t_slack_workspace *workspace); -void slack_workspace_free_all(); -void slack_workspace_disconnect(struct t_slack_workspace *workspace, - int reconnect); -void slack_workspace_disconnect_all(); -void slack_workspace_close_connection(struct t_slack_workspace *workspace); -int slack_workspace_connect(struct t_slack_workspace *workspace); -int slack_workspace_timer_cb(const void *pointer, void *data, int remaining_calls); -void slack_workspace_register_request(struct t_slack_workspace *workspace, - struct t_slack_request *request); -struct t_slack_workspace_emoji *slack_workspace_emoji_search( - struct t_slack_workspace *workspace, - const char *name); -struct t_slack_workspace_emoji *slack_workspace_add_emoji( - struct t_slack_workspace *workspace, - const char *name, const char *url); - -#endif /*SLACK_WORKSPACE_H*/ From b6b6ed6246dd24971ce64d18f25ada8ac657f9be Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 28 Jun 2021 02:18:05 +0100 Subject: [PATCH 075/118] drop json-c --- .gitmodules | 3 --- Makefile | 45 +++------------------------------------------ connection.c | 3 +-- connection.h | 2 +- json-c | 1 - plugin.c | 1 - 6 files changed, 5 insertions(+), 50 deletions(-) delete mode 160000 json-c diff --git a/.gitmodules b/.gitmodules index fc93d6e..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "json-c"] - path = json-c - url = https://github.com/json-c/json-c diff --git a/Makefile b/Makefile index 704f6b1..3ef02a1 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ifdef DEBUG endif RM=rm -f FIND=find -INCLUDES=-Ilibstrophe -Ijson-c +INCLUDES=-Ilibstrophe CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers $(INCLUDES) LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) LDLIBS=-lstrophe -lpthread @@ -18,36 +18,7 @@ SRCS=plugin.c \ config.c \ connection.c \ -DEPS=json-c/libjson-c.a -OLDSRCS=slack.c \ - slack-api.c \ - slack-buffer.c \ - slack-channel.c \ - slack-config.c \ - slack-command.c \ - slack-completion.c \ - slack-emoji.c \ - slack-input.c \ - slack-message.c \ - slack-oauth.c \ - slack-request.c \ - slack-teaminfo.c \ - slack-user.c \ - slack-workspace.c \ - api/slack-api-hello.c \ - api/slack-api-error.c \ - api/slack-api-message.c \ - api/slack-api-user-typing.c \ - api/message/slack-api-message-bot-message.c \ - api/message/slack-api-message-slackbot-response.c \ - api/message/slack-api-message-me-message.c \ - api/message/slack-api-message-unimplemented.c \ - request/slack-request-chat-memessage.c \ - request/slack-request-chat-postmessage.c \ - request/slack-request-channels-list.c \ - request/slack-request-conversations-members.c \ - request/slack-request-emoji-list.c \ - request/slack-request-users-list.c +DEPS= OBJS=$(subst .c,.o,$(SRCS)) all: $(DEPS) weechat-xmpp @@ -57,15 +28,9 @@ weechat-xmpp: $(OBJS) which patchelf >/dev/null && \ patchelf --set-rpath $(LIBRARY_PATH):$(shell patchelf --print-rpath xmpp.so) xmpp.so || true -json-c/libjson-c.a: - cd json-c && env CFLAGS= LDFLAGS= \ - cmake -DCMAKE_C_FLAGS=-fPIC . - $(MAKE) -C json-c json-c-static -json-c: json-c/libjson-c.a - depend: .depend -.depend: json-c/libjson-c.a $(SRCS) +.depend: $(SRCS) $(RM) ./.depend $(CC) $(CFLAGS) -MM $^>>./.depend @@ -74,10 +39,6 @@ tidy: clean: $(RM) $(OBJS) - $(MAKE) -C json-c clean || true - git submodule foreach --recursive git clean -xfd || true - git submodule foreach --recursive git reset --hard || true - git submodule update --init --recursive || true distclean: clean $(RM) *~ .depend diff --git a/connection.c b/connection.c index 6ac95a2..77ed274 100644 --- a/connection.c +++ b/connection.c @@ -2,7 +2,6 @@ // 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 @@ -260,7 +259,7 @@ int xmpp_connection_check_events(const void *pointer, void *data, int remaining_ } int xmpp_connection_route_message(xmpp_conn_t *workspace, - const char *type, json_object *message) + const char *type, void *message) { //struct stringcase key; //key.string = type; diff --git a/connection.h b/connection.h index d2f3448..9507803 100644 --- a/connection.h +++ b/connection.h @@ -16,6 +16,6 @@ void xmpp_connection_connect(const char* jid, const char* password); int xmpp_connection_check_events(const void *pointer, void *data, int remaining_calls); int xmpp_connection_route_message(xmpp_conn_t *connection, - const char *type, json_object *message); + const char *type, void *message); #endif /*WEECHAT_XMPP_CONNECTION_H*/ diff --git a/json-c b/json-c deleted file mode 160000 index 75bf657..0000000 --- a/json-c +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 75bf657cc285c1b726492ed6af3645ea95fe17ac diff --git a/plugin.c b/plugin.c index 1381694..582a524 100644 --- a/plugin.c +++ b/plugin.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "plugin.h" From 2b42e8cd2ab4873146dfd8181542a662055719d1 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 30 Jun 2021 07:26:06 +0100 Subject: [PATCH 076/118] buffers! hooray. --- .envrc | 8 +- Makefile | 34 ++- account.c | 495 +++++++++++++++++++++++++++++++++++++++ account.h | 64 +++++ buffer.c | 165 +++++++++++++ buffer.h | 27 +++ channel.c | 643 +++++++++++++++++++++++++++++++++++++++++++++++++++ channel.h | 147 ++++++++++++ command.c | 438 +++++++++++++++++------------------ command.h | 2 +- config.c | 388 ++++++++++++++++--------------- config.h | 88 ++++--- connection.c | 162 ++++--------- connection.h | 17 +- input.c | 64 +++++ input.h | 12 + message.c | 249 ++++++++++++++++++++ message.h | 13 ++ plugin.c | 63 +++-- user.c | 242 +++++++++++++++++++ user.h | 75 ++++++ 21 files changed, 2762 insertions(+), 634 deletions(-) create mode 100644 account.c create mode 100644 account.h create mode 100644 buffer.c create mode 100644 buffer.h create mode 100644 channel.c create mode 100644 channel.h create mode 100644 input.c create mode 100644 input.h create mode 100644 message.c create mode 100644 message.h create mode 100644 user.c create mode 100644 user.h diff --git a/.envrc b/.envrc index ec1a23e..989115f 100644 --- a/.envrc +++ b/.envrc @@ -18,12 +18,6 @@ export_function() use_guix() { - # Set GitHub token. - export GUIX_GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - - # Unset 'GUIX_PACKAGE_PATH'. - export GUIX_PACKAGE_PATH="" - # Recreate a garbage collector root. gcroots="$HOME/.config/guix/gcroots" mkdir -p "$gcroots" @@ -51,4 +45,4 @@ use_guix() export CC=gcc } -use guix +use guix --with-debug-info=weechat --with-debug-info=libstrophe diff --git a/Makefile b/Makefile index 3ef02a1..657cd60 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ ifdef DEBUG - DBGCFLAGS=-fsanitize=address -fsanitize=leak -fsanitize=undefined - DBGLDFLAGS=-static-libasan -static-liblsan -static-libubsan + DBGCFLAGS=-fsanitize=address -fsanitize=undefined -fsanitize=leak + DBGLDFLAGS=-lasan -lubsan -llsan endif RM=rm -f FIND=find INCLUDES=-Ilibstrophe CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers $(INCLUDES) -LDFLAGS+=-shared -g $(DBGCFLAGS) $(DBGLDFLAGS) +LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) LDLIBS=-lstrophe -lpthread PREFIX ?= /usr/local @@ -14,19 +14,35 @@ LIBDIR ?= $(PREFIX)/lib INSTALL ?= /usr/bin/install SRCS=plugin.c \ - command.c \ - config.c \ - connection.c \ + account.c \ + buffer.c \ + channel.c \ + command.c \ + config.c \ + connection.c \ + input.c \ + message.c \ + user.c \ DEPS= OBJS=$(subst .c,.o,$(SRCS)) -all: $(DEPS) weechat-xmpp +all: weechat-xmpp +weechat-xmpp: $(DEPS) xmpp.so -weechat-xmpp: $(OBJS) +xmpp.so: $(OBJS) $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(LDLIBS) which patchelf >/dev/null && \ - patchelf --set-rpath $(LIBRARY_PATH):$(shell patchelf --print-rpath xmpp.so) xmpp.so || true + patchelf --set-rpath $(LIBRARY_PATH):$(shell realpath $(shell dirname $(shell gcc --print-libgcc-file-name))/../../../) xmpp.so && \ + patchelf --shrink-rpath xmpp.so || true + +test: xmpp.so + env LD_PRELOAD=$(DEBUG) \ + weechat -a -P buflist -r '/plugin load ./xmpp.so' + +debug: xmpp.so + gdb -ex "handle SIGPIPE nostop noprint pass" --args \ + weechat -a -r '/plugin load ./xmpp.so' depend: .depend diff --git a/account.c b/account.c new file mode 100644 index 0000000..e70c2cc --- /dev/null +++ b/account.c @@ -0,0 +1,495 @@ +// 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 +#include + +#include "plugin.h" +#include "config.h" +#include "input.h" +#include "account.h" +#include "connection.h" +//#include "xmpp-api.h" +//#include "xmpp-request.h" +#include "user.h" +#include "channel.h" +#include "buffer.h" + +struct t_account *accounts = NULL; +struct t_account *last_account = NULL; + +char *account_options[ACCOUNT_NUM_OPTIONS][2] = +{ { "jid", "" }, + { "password", "" }, + { "tls", "normal" }, + { "nickname", "" }, +}; + +struct t_account *account__search(const char *name) +{ + struct t_account *ptr_account; + + if (!name) + return NULL; + + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + if (strcmp(ptr_account->name, name) == 0) + return ptr_account; + } + + /* account not found */ + return NULL; +} + +struct t_account *account__casesearch (const char *name) +{ + struct t_account *ptr_account; + + if (!name) + return NULL; + + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + if (weechat_strcasecmp (ptr_account->name, name) == 0) + return ptr_account; + } + + /* 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; +} + +void 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; + + static const char *log_level_name[4] = {"debug", "info", "warn", "error"}; + + time_t date = time(NULL); + const char *timestamp = weechat_util_get_time_string(&date); + + weechat_printf( + account ? account->buffer : NULL, + _("%s%s (%s): %s"), + weechat_prefix("error"), area, + log_level_name[level], msg); +} + +struct t_account *account__alloc(const char *name) +{ + struct t_account *new_account; + int i, length; + char *option_name; + + if (account__casesearch(name)) + return NULL; + + /* alloc memory for new account */ + new_account = malloc(sizeof(*new_account)); + if (!new_account) + { + weechat_printf(NULL, + _("%s%s: error when allocating new account"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return NULL; + } + + /* add new account to queue */ + new_account->prev_account = last_account; + new_account->next_account = NULL; + if (last_account) + last_account->next_account = new_account; + else + accounts = new_account; + last_account = new_account; + + /* set name */ + new_account->name = strdup(name); + + /* set properties */ + new_account->jid = NULL; + new_account->password = NULL; + new_account->tls = 1; + + /* internal vars */ + new_account->reloading_from_config = 0; + + new_account->is_connected = 0; + new_account->disconnected = 0; + + new_account->logger.handler = &log_emit_weechat; + new_account->logger.userdata = new_account; + new_account->context = xmpp_ctx_new(NULL, &new_account->logger); + new_account->connection = NULL; + + new_account->nickname = NULL; + + new_account->buffer = NULL; + new_account->buffer_as_string = NULL; + new_account->users = NULL; + new_account->last_user = NULL; + new_account->channels = NULL; + new_account->last_channel = NULL; + + /* create options with null value */ + for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) + { + new_account->options[i] = NULL; + + length = strlen(new_account->name) + 1 + + strlen(account_options[i][0]) + + 512 + /* inherited option name(xmpp.account_default.xxx) */ + 1; + option_name = malloc(length); + if (option_name) + { + snprintf(option_name, length, "%s.%s << xmpp.account_default.%s", + new_account->name, + account_options[i][0], + account_options[i][0]); + new_account->options[i] = config__account_new_option( + config_file, + config_section_account, + i, + option_name, + account_options[i][1], + account_options[i][1], + 0, + &config__account_check_value_cb, + account_options[i][0], + NULL, + &config__account_change_cb, + account_options[i][0], + NULL); + config__account_change_cb(account_options[i][0], NULL, + new_account->options[i]); + free(option_name); + } + } + + return new_account; +} + +void account__free_data(struct t_account *account) +{ + int i; + + if (!account) + return; + + /* free linked lists */ + /* + for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) + { + account__outqueue_free_all(account, i); + } + xmpp_redirect_free_all(account); + xmpp_notify_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); + + /* free account data */ + //for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) + //{ + // if (account->options[i]) + // weechat_config_option_free(account->options[i]); + //} + + if (account->name) + free(account->name); + if (account->jid) + free(account->jid); + if (account->password) + free(account->password); + + if (account->nickname) + free(account->nickname); + + if (account->buffer_as_string) + free(account->buffer_as_string); + + channel__free_all(account); + user__free_all(account); +} + +void account__free(struct t_account *account) +{ + struct t_account *new_accounts; + + if (!account) + return; + + /* + * 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); + + /* remove account from queue */ + if (last_account == account) + last_account = account->prev_account; + if (account->prev_account) + { + (account->prev_account)->next_account = account->next_account; + new_accounts = accounts; + } + else + new_accounts = account->next_account; + + if (account->next_account) + (account->next_account)->prev_account = account->prev_account; + + account__free_data(account); + free(account); + accounts = new_accounts; +} + +void account__free_all() +{ + /* for each account in memory, remove it */ + while (accounts) + { + account__free(accounts); + } +} + +void account__disconnect(struct t_account *account, int reconnect) +{ + (void) reconnect; + + struct t_channel *ptr_channel; + (void) ptr_channel; + + if (account->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) + { + weechat_nicklist_remove_all(ptr_channel->buffer); + weechat_printf( + ptr_channel->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", ""); + } + + account__close_connection(account); + + if (account->buffer) + { + weechat_printf( + account->buffer, + _("%s%s: disconnected from account"), + weechat_prefix ("network"), WEECHAT_XMPP_PLUGIN_NAME); + } + + /* + account->current_retry = 0; + + if (switch_address) + account__switch_address(account, 0); + else + account__set_index_current_address(account, 0); + + if (account->nick_modes) + { + free (account->nick_modes); + account->nick_modes = NULL; + weechat_bar_item_update ("input_prompt"); + weechat_bar_item_update ("xmpp_nick_modes"); + } + account->cap_away_notify = 0; + account->cap_account_notify = 0; + account->cap_extended_join = 0; + account->is_away = 0; + account->away_time = 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) + + weechat_config_integer (xmpp_config_network_lag_check); + account->lag_last_refresh = 0; + account__set_lag (account); + account->monitor = 0; + account->monitor_time = 0; + + if (reconnect + && IRC_SERVER_OPTION_BOOLEAN(account, IRC_SERVER_OPTION_AUTORECONNECT)) + account__reconnect_schedule(account); + else + { + account->reconnect_delay = 0; + account->reconnect_start = 0; + } + */ + + /* discard current nick if no reconnection asked */ + /* + if (!reconnect && account->nick) + account__set_nick(account, NULL); + + account__set_buffer_title(account); + + account->disconnected = 1; + */ + + /* send signal "account_disconnected" with account name */ + /* + (void) weechat_hook_signal_send("account_disconnected", + WEECHAT_HOOK_SIGNAL_STRING, account->name); + */ +} + +void account__disconnect_all() +{ + struct t_account *ptr_account; + + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + account__disconnect(ptr_account, 0); + } +} + +struct t_gui_buffer *account__create_buffer(struct t_account *account) +{ + 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) + return NULL; + + 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_server", account->name); + weechat_buffer_set(account->buffer, "localvar_set_channel", 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", + &buffer__nickcmp_cb); + weechat_buffer_set_pointer(account->buffer, "nicklist_callback_pointer", + account); + + return account->buffer; +} + +void account__close_connection(struct t_account *account) +{ + if (account->connection) + { + if (xmpp_conn_is_connected(account->connection)) + xmpp_disconnect(account->connection); + } + + account->is_connected = 0; +} + +int account__connect(struct t_account *account) +{ + account->disconnected = 0; + + if (!account->buffer) + { + if (!account__create_buffer(account)) + return 0; + weechat_buffer_set(account->buffer, "display", "auto"); + } + + account__close_connection(account); + + account->jid = !account->options[ACCOUNT_OPTION_JID] ? NULL : + weechat_config_string(account->options[ACCOUNT_OPTION_JID]); + account->password = !account->options[ACCOUNT_OPTION_PASSWORD] ? NULL : + weechat_config_string(account->options[ACCOUNT_OPTION_PASSWORD]); + account->tls = !account->options[ACCOUNT_OPTION_TLS] ? NULL : + weechat_config_integer(account->options[ACCOUNT_OPTION_TLS]); + account->nickname = !account->options[ACCOUNT_OPTION_NICKNAME] ? NULL : + weechat_config_string(account->options[ACCOUNT_OPTION_NICKNAME]); + + account->is_connected = + connection__connect(account->context, &account->connection, + &account->logger, account->jid, + account->password, account->tls); + + return account->is_connected; +} + +int account__timer_cb(const void *pointer, void *data, int remaining_calls) +{ + (void) pointer; + (void) data; + (void) remaining_calls; + + struct t_account *ptr_account; + + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + if (ptr_account->is_connected + && (xmpp_conn_is_connecting(ptr_account->connection) + || xmpp_conn_is_connected(ptr_account->connection))) + connection__process(ptr_account->context, ptr_account->connection, 10); + } +} diff --git a/account.h b/account.h new file mode 100644 index 0000000..c963bde --- /dev/null +++ b/account.h @@ -0,0 +1,64 @@ +// 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/. + +#ifndef _ACCOUNT_H_ +#define _ACCOUNT_H_ + +extern struct t_account *accounts; +extern struct t_account *last_account; + +enum t_account_option +{ + ACCOUNT_OPTION_JID, + ACCOUNT_OPTION_PASSWORD, + ACCOUNT_OPTION_TLS, + ACCOUNT_OPTION_NICKNAME, + ACCOUNT_NUM_OPTIONS, +}; + +struct t_account +{ + const char *name; + const char *jid; + const char *password; + int tls; + struct t_config_option *options[ACCOUNT_NUM_OPTIONS]; + + int reloading_from_config; + + int is_connected; + int disconnected; + + xmpp_log_t logger; + struct xmpp_ctx_t *context; + struct xmpp_conn_t *connection; + + char *nickname; + + struct t_gui_buffer *buffer; + char *buffer_as_string; + 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 *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); + +#endif /*ACCOUNT_H*/ diff --git a/buffer.c b/buffer.c new file mode 100644 index 0000000..48232b3 --- /dev/null +++ b/buffer.c @@ -0,0 +1,165 @@ +// 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 "plugin.h" +#include "account.h" +#include "channel.h" +#include "buffer.h" + +void buffer__get_account_and_channel(struct t_gui_buffer *buffer, + struct t_account **account, + struct t_channel **channel) +{ + struct t_account *ptr_account; + struct t_channel *ptr_channel; + + if (!buffer) + return; + + /* look for a account or channel using this buffer */ + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + if (ptr_account->buffer == buffer) + { + if (account) + *account = ptr_account; + return; + } + + for (ptr_channel = ptr_account->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + if (ptr_channel->buffer == buffer) + { + if (account) + *account = ptr_account; + if (channel) + *channel = ptr_channel; + return; + } + } + } + + /* no account or channel found */ +} + +char *buffer__typing_bar_cb(const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info) +{ + struct t_channel_typing *ptr_typing; + struct t_account *account; + struct t_channel *channel; + char notification[256]; + unsigned typecount; + + (void) pointer; + (void) data; + (void) item; + (void) window; + (void) extra_info; + + account = NULL; + channel = NULL; + + buffer__get_account_and_channel(buffer, &account, &channel); + + if (!channel) + return strdup(""); + + typecount = 0; + + for (ptr_typing = channel->typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + switch (++typecount) + { + case 1: + strcpy(notification, ptr_typing->name); + break; + case 2: + strcat(notification, ", "); + strcat(notification, ptr_typing->name); + break; + case 3: + default: + strcpy(notification, "Several people"); + break; + } + } + + if (typecount) + { + strcat(notification, NG_(" is typing...", + " are typing...", + typecount)); + return strdup(notification); + } + else + { + return strdup(""); + } +} + +int buffer__nickcmp_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *nick1, + const char *nick2) +{ + struct t_account *account; + + (void) data; + + if (pointer) + account = (struct t_account *)pointer; + else + buffer__get_account_and_channel(buffer, &account, NULL); + + if (account) + { + return weechat_strcasecmp(nick1, nick2); + } + else + { + return weechat_strcasecmp(nick1, nick2); + } +} + +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; + + buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin"); + if (buffer_plugin == weechat_plugin) + buffer__get_account_and_channel(buffer, + &ptr_account, &ptr_channel); + + (void) pointer; + (void) data; + (void) buffer; + + if (ptr_account) + { + if (!ptr_account->disconnected) + { + //command_quit_account(ptr_account, NULL); + account__disconnect(ptr_account, 0); + } + + ptr_account->buffer = NULL; + } + + return WEECHAT_RC_OK; +} diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..b126d9d --- /dev/null +++ b/buffer.h @@ -0,0 +1,27 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_BUFFER_H_ +#define _WEECHAT_XMPP_BUFFER_H_ + +void buffer__get_account_and_channel(struct t_gui_buffer *buffer, + struct t_account **account, + struct t_channel **channel); + +char *buffer__typing_bar_cb(const void *pointer, + void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info); + +int buffer__nickcmp_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *nick1, + const char *nick2); + +int buffer__close_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer); + +#endif /*WEECHAT_XMPP_BUFFER_H*/ diff --git a/channel.c b/channel.c new file mode 100644 index 0000000..a2dd60c --- /dev/null +++ b/channel.c @@ -0,0 +1,643 @@ +// 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 +#include + +#include "plugin.h" +#include "account.h" +#include "user.h" +#include "channel.h" +#include "input.h" +#include "buffer.h" + +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; + } + + return NULL; +} + +struct t_gui_buffer *channel__search_buffer(struct t_account *account, + enum t_channel_type type, + const char *name) +{ + struct t_hdata *hdata_buffer; + struct t_gui_buffer *ptr_buffer; + const char *ptr_type, *ptr_account_name, *ptr_channel_name; + + hdata_buffer = weechat_hdata_get("buffer"); + ptr_buffer = weechat_hdata_get_list(hdata_buffer, "gui_buffers"); + + while (ptr_buffer) + { + if (weechat_buffer_get_pointer(ptr_buffer, "plugin") == weechat_plugin) + { + ptr_type = weechat_buffer_get_string(ptr_buffer, "localvar_type"); + ptr_account_name = weechat_buffer_get_string(ptr_buffer, + "localvar_server"); + ptr_channel_name = weechat_buffer_get_string(ptr_buffer, + "localvar_channel"); + if (ptr_type && ptr_type[0] + && ptr_account_name && ptr_account_name[0] + && ptr_channel_name && ptr_channel_name[0] + && ( (( (type == CHANNEL_TYPE_CHANNEL) + || (type == CHANNEL_TYPE_GROUP)) + && (strcmp(ptr_type, "channel") == 0)) + || (( (type == CHANNEL_TYPE_MPIM) + || (type == CHANNEL_TYPE_IM)) + && (strcmp(ptr_type, "private") == 0))) + && (strcmp(ptr_account_name, account->name) == 0) + && (weechat_strcasecmp(ptr_channel_name, name) == 0)) + { + return ptr_buffer; + } + } + ptr_buffer = weechat_hdata_move(hdata_buffer, ptr_buffer, 1); + } + + 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 *ptr_buffer; + int buffer_created; + const char *short_name, *localvar_channel; + char buffer_name[256]; + + buffer_created = 0; + + snprintf(buffer_name, sizeof(buffer_name), + "%s.%s", account->name, name); + + ptr_buffer = channel__search_buffer(account, type, name); + if (ptr_buffer) + { + weechat_nicklist_remove_all(ptr_buffer); + } + else + { + ptr_buffer = weechat_buffer_new(buffer_name, + &input__data_cb, NULL, NULL, + &buffer__close_cb, NULL, NULL); + if (!ptr_buffer) + return NULL; + + buffer_created = 1; + } + + if (buffer_created) + { + if (!weechat_buffer_get_integer(ptr_buffer, "short_name_is_set")) + weechat_buffer_set(ptr_buffer, "short_name", name); + } + else + { + short_name = weechat_buffer_get_string (ptr_buffer, "short_name"); + localvar_channel = weechat_buffer_get_string (ptr_buffer, + "localvar_channel"); + + if (!short_name || + (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) + { + weechat_buffer_set (ptr_buffer, "short_name", name); + } + } + + weechat_buffer_set(ptr_buffer, "name", buffer_name); + weechat_buffer_set(ptr_buffer, "localvar_set_type", + (type == CHANNEL_TYPE_IM || + type == CHANNEL_TYPE_MPIM) ? "private" : "channel"); + weechat_buffer_set(ptr_buffer, "localvar_set_nick", account->nickname); + weechat_buffer_set(ptr_buffer, "localvar_set_server", account->name); + weechat_buffer_set(ptr_buffer, "localvar_set_channel", name); + + if (buffer_created) + { + (void) weechat_hook_signal_send ("logger_backlog", + WEECHAT_HOOK_SIGNAL_POINTER, + ptr_buffer); + weechat_buffer_set(ptr_buffer, "input_get_unknown_commands", "1"); + if (type != CHANNEL_TYPE_IM) + { + weechat_buffer_set(ptr_buffer, "nicklist", "1"); + weechat_buffer_set(ptr_buffer, "nicklist_display_groups", "0"); + weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback", + &buffer__nickcmp_cb); + weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback_pointer", + account); + } + + weechat_buffer_set(ptr_buffer, "highlight_words_add", + account->nickname); + weechat_buffer_set(ptr_buffer, "highlight_tags_restrict", + "message"); + } + + return ptr_buffer; +} + +void channel__add_nicklist_groups(struct t_account *account, + struct t_channel *channel) +{ + struct t_gui_buffer *ptr_buffer; + char str_group[32]; + + if (channel && channel->type == CHANNEL_TYPE_MPIM) + return; + if (channel && channel->type == CHANNEL_TYPE_IM) + 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.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", + 999, "..."); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "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) +{ + struct t_channel *new_channel, *ptr_channel; + struct t_gui_buffer *ptr_buffer; + struct t_hook *typing_timer; + char buffer_name[CHANNEL_NAME_MAX_LEN + 2]; + + if (!account || !id || !name || !name[0]) + return NULL; + + ptr_channel = channel__search(account, id); + if (ptr_channel) + { + return ptr_channel; + } + + buffer_name[0] = '#'; + strncpy(&buffer_name[1], name, CHANNEL_NAME_MAX_LEN + 1); + + ptr_buffer = channel__create_buffer(account, type, buffer_name); + if (!ptr_buffer) + return NULL; + + if ((new_channel = malloc(sizeof(*new_channel))) == NULL) + return NULL; + + typing_timer = weechat_hook_timer(1 * 1000, 0, 0, + &channel__typing_cb, + new_channel, NULL); + + new_channel->type = type; + new_channel->id = strdup(id); + new_channel->name = strdup(name); + new_channel->created = 0; + + new_channel->is_general = 0; + new_channel->name_normalized = NULL; + new_channel->is_shared = 0; + new_channel->is_org_shared = 0; + new_channel->is_member = 0; + + new_channel->topic.value = NULL; + new_channel->topic.creator = NULL; + new_channel->topic.last_set = 0; + new_channel->purpose.value = NULL; + new_channel->purpose.creator = NULL; + new_channel->purpose.last_set = 0; + new_channel->is_archived = 0; + + new_channel->creator = NULL; + new_channel->last_read = 0.0; + new_channel->unread_count = 0; + new_channel->unread_count_display = 0; + + new_channel->is_user_deleted = 0; + + new_channel->typing_hook_timer = typing_timer; + new_channel->members_speaking[0] = NULL; + new_channel->members_speaking[1] = 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; + + return new_channel; +} + +void channel__member_speaking_add_to_list(struct t_channel *channel, + 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(); + + /* remove item if it was already in list */ + ptr_item = weechat_list_casesearch(channel->members_speaking[highlight], nick); + if (ptr_item) + weechat_list_remove(channel->members_speaking[highlight], ptr_item); + + /* add nick in list */ + weechat_list_add(channel->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]); + 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)); + } + } +} + +void channel__member_speaking_add(struct t_channel *channel, + 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); + + channel__member_speaking_add_to_list(channel, nick, 0); +} + +void channel__member_speaking_rename(struct t_channel *channel, + 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]) + { + ptr_item = weechat_list_search(channel->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) +{ + struct t_weelist_item *ptr_item; + int i, j, list_size; + + (void) account; + + for (i = 0; i < 2; i++) + { + if (channel->members_speaking[i]) + { + list_size = weechat_list_size(channel->members_speaking[i]); + for (j = 0; j < list_size; j++) + { + ptr_item = weechat_list_get (channel->members_speaking[i], j); + if (ptr_item && (strcasecmp(weechat_list_string(ptr_item), nick) == 0)) + weechat_list_set(ptr_item, nick); + } + } + } +} + +void channel__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_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; + const char *localvar; + unsigned typecount; + time_t now; + + (void) data; + (void) remaining_calls; + + if (!pointer) + return WEECHAT_RC_ERROR; + + channel = (struct t_channel *)pointer; + + now = time(NULL); + + typecount = 0; + + for (ptr_typing = channel->typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + next_typing = ptr_typing->next_typing; + + while (ptr_typing && now - ptr_typing->ts > 5) + { + channel__typing_free(channel, ptr_typing); + ptr_typing = next_typing; + if (ptr_typing) + next_typing = ptr_typing->next_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", + 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) +{ + struct t_channel_typing *ptr_typing; + + if (!channel || !id) + return NULL; + + for (ptr_typing = channel->typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + if (weechat_strcasecmp(ptr_typing->id, id) == 0) + return ptr_typing; + } + + return NULL; +} + +void channel__add_typing(struct t_channel *channel, + struct t_user *user) +{ + struct t_channel_typing *new_typing; + + new_typing = channel__typing_search(channel, user->id); + if (!new_typing) + { + new_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; + } + new_typing->ts = time(NULL); + + channel__typing_cb(channel, NULL, 0); +} + +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); + + 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); + + /* free linked lists */ + channel__typing_free_all(channel); + channel__member_free_all(channel); + + /* free channel data */ + if (channel->id) + free(channel->id); + if (channel->name) + free(channel->name); + if (channel->name_normalized) + free(channel->name_normalized); + if (channel->topic.value) + free(channel->topic.value); + if (channel->topic.creator) + free(channel->topic.creator); + if (channel->purpose.value) + free(channel->purpose.value); + if (channel->purpose.creator) + free(channel->purpose.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) +{ + while (account->channels) + channel__free(account, account->channels); +} + +void channel__update_topic(struct t_channel *channel, + 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); + else + weechat_buffer_set(channel->buffer, "title", ""); +} + +void channel__update_purpose(struct t_channel *channel, + const char* purpose, + const char* creator, + int last_set) +{ + if (channel->purpose.value) + free(channel->purpose.value); + if (channel->purpose.creator) + free(channel->purpose.creator); + channel->purpose.value = (purpose) ? strdup(purpose) : NULL; + channel->purpose.creator = (creator) ? strdup(creator) : NULL; + channel->purpose.last_set = last_set; +} + +struct t_channel_member *channel__add_member( + struct t_account *account, + struct t_channel *channel, + const char *id) +{ + struct t_channel_member *member; + struct t_user *user; + + member = malloc(sizeof(struct t_channel_member)); + member->id = strdup(id); + + 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; + + user = user__search(account, id); + if (user) + user__nicklist_add(account, channel, user); + + return member; +} diff --git a/channel.h b/channel.h new file mode 100644 index 0000000..5b79c79 --- /dev/null +++ b/channel.h @@ -0,0 +1,147 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_CHANNEL_H_ +#define _WEECHAT_XMPP_CHANNEL_H_ + +#define CHANNEL_MEMBERS_SPEAKING_LIMIT 128 + +#define CHANNEL_NAME_MAX_LEN 22 + +enum t_channel_type +{ + CHANNEL_TYPE_CHANNEL, + CHANNEL_TYPE_GROUP, + CHANNEL_TYPE_MPIM, + CHANNEL_TYPE_IM, +}; + +struct t_channel_typing +{ + char *id; + char *name; + time_t ts; + + struct t_channel_typing *prev_typing; + struct t_channel_typing *next_typing; +}; + +struct t_channel_member +{ + char *id; + + 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_purpose +{ + char *value; + char *creator; + time_t last_set; +}; + +struct t_channel +{ + enum t_channel_type type; + char *id; + char *name; + time_t created; + + /* channel */ + int is_general; + char *name_normalized; + int is_shared; + int is_org_shared; + int is_member; + + /* group */ + struct t_channel_topic topic; + struct t_channel_purpose purpose; + int is_archived; + + /* mpim */ + char *creator; + double last_read; + int unread_count; + int unread_count_display; + + /* im */ + int is_user_deleted; + + struct t_hook *typing_hook_timer; + struct t_weelist *members_speaking[2]; + 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; +}; + +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); + +void channel__add_typing(struct t_channel *channel, + struct t_user *user); + +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_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); + +#endif /*WEECHAT_XMPP_CHANNEL_H*/ diff --git a/command.c b/command.c index ff62b1a..fe39db0 100644 --- a/command.c +++ b/command.c @@ -8,39 +8,35 @@ #include #include "plugin.h" -//#include "xmpp-oauth.h" -//#include "xmpp-teaminfo.h" -//#include "xmpp-workspace.h" -//#include "xmpp-channel.h" -//#include "xmpp-buffer.h" -//#include "xmpp-message.h" +//#include "oauth.h" +//#include "teaminfo.h" +#include "account.h" +#include "channel.h" +#include "buffer.h" +#include "message.h" #include "command.h" -//#include "request/xmpp-request-chat-memessage.h" -/* -void xmpp_command_display_workspace(xmpp_conn_t *workspace) +void command__display_account(struct t_account *account) { int num_channels, num_pv; - if (workspace->is_connected) + if (account->is_connected) { - num_channels = 0;//xmpp_workspace_get_channel_count(workspace); - num_pv = 0;//xmpp_workspace_get_pv_count(workspace); + 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.xmpp.com %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv", - (workspace->is_connected) ? "*" : " ", + " %s %s%s%s %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv", + (account->is_connected) ? "*" : " ", weechat_color("chat_server"), - workspace->domain, + account->name, weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - (workspace->name) ? - workspace->name : "???", + (account->jid) ? account->jid : "???", weechat_color("chat_delimiters"), weechat_color("reset"), - (workspace->is_connected) ? - _("connected") : _("not connected"), + (account->is_connected) ? _("connected") : _("not connected"), weechat_color("chat_delimiters"), weechat_color("reset"), num_channels, @@ -51,177 +47,166 @@ void xmpp_command_display_workspace(xmpp_conn_t *workspace) { weechat_printf( NULL, - " %s%s%s.xmpp.com %s(%s%s%s)%s", + " %s%s%s %s(%s%s%s)%s", weechat_color("chat_server"), - workspace->domain, + account->name, weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - (workspace->name) ? - workspace->name : "???", + (account->jid) ? account->jid : "???", weechat_color("chat_delimiters"), weechat_color("reset")); } } -void xmpp_command_workspace_list(int argc, char **argv) +void command__account_list(int argc, char **argv) { - int i, one_workspace_found; - xmpp_conn_t *ptr_workspace2; - char *workspace_name = NULL; + int i, one_account_found; + struct t_account *ptr_account2; + char *account_name = NULL; for (i = 2; i < argc; i++) { - if (!workspace_name) - workspace_name = argv[i]; + if (!account_name) + account_name = argv[i]; } - if (!workspace_name) + if (!account_name) { - if (xmpp_workspaces) + if (accounts) { weechat_printf(NULL, ""); - weechat_printf(NULL, _("All workspaces:")); - for (ptr_workspace2 = xmpp_workspaces; ptr_workspace2; - ptr_workspace2 = ptr_workspace2->next_workspace) + weechat_printf(NULL, _("All accounts:")); + for (ptr_account2 = accounts; ptr_account2; + ptr_account2 = ptr_account2->next_account) { - xmpp_command_display_workspace(ptr_workspace2); + command__display_account(ptr_account2); } } else - weechat_printf(NULL, _("No workspace")); + weechat_printf(NULL, _("No account")); } else { - one_workspace_found = 0; - for (ptr_workspace2 = xmpp_workspaces; ptr_workspace2; - ptr_workspace2 = ptr_workspace2->next_workspace) + one_account_found = 0; + for (ptr_account2 = accounts; ptr_account2; + ptr_account2 = ptr_account2->next_account) { - if (weechat_strcasestr(ptr_workspace2->name, workspace_name)) + if (weechat_strcasestr(ptr_account2->name, account_name)) { - if (!one_workspace_found) + if (!one_account_found) { weechat_printf(NULL, ""); weechat_printf(NULL, _("Servers with \"%s\":"), - workspace_name); + account_name); } - one_workspace_found = 1; - xmpp_command_display_workspace(ptr_workspace2); + one_account_found = 1; + command__display_account(ptr_account2); } } - if (!one_workspace_found) + if (!one_account_found) weechat_printf(NULL, - _("No workspace found with \"%s\""), - workspace_name); + _("No account found with \"%s\""), + account_name); } } -void xmpp_command_add_workspace(struct t_xmpp_teaminfo *xmpp_teaminfo) +void command__add_account(const char *name, const char *jid, const char *password) { - xmpp_conn_t *workspace; + struct t_account *account; - workspace = xmpp_workspace_casesearch(xmpp_teaminfo->domain); - if (workspace) + account = account__casesearch(name); + if (account) { weechat_printf( NULL, - _("%s%s: workspace \"%s\" already exists, can't add it!"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, - xmpp_teaminfo->domain); + _("%s%s: account \"%s\" already exists, can't add it!"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + name); return; } - workspace = xmpp_workspace_alloc(xmpp_teaminfo->domain); - if (!workspace) + account = account__alloc(name); + if (!account) { weechat_printf( NULL, - _("%s%s: unable to add workspace"), - weechat_prefix("error"), XMPP_PLUGIN_NAME); + _("%s%s: unable to add account"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); return; } - workspace->id = strdup(xmpp_teaminfo->id); - workspace->name = strdup(xmpp_teaminfo->name); - weechat_config_option_set(workspace->options[XMPP_WORKSPACE_OPTION_TOKEN], - xmpp_teaminfo->token, 1); + account->name = strdup(name); + if (jid) + account->jid = strdup(jid); + if (password) + account->password = strdup(password); + weechat_config_option_set(account->options[ACCOUNT_OPTION_JID], + account->jid, 1); + weechat_config_option_set(account->options[ACCOUNT_OPTION_PASSWORD], + account->password, 1); + weechat_config_option_set(account->options[ACCOUNT_OPTION_NICKNAME], + account->jid ? xmpp_jid_node(account->context, + account->jid) + : NULL, 1); weechat_printf ( NULL, - _("%s: workspace %s%s%s.xmpp.com %s(%s%s%s)%s added"), - XMPP_PLUGIN_NAME, + _("%s: account %s%s%s %s(%s%s%s)%s added"), + WEECHAT_XMPP_PLUGIN_NAME, weechat_color("chat_server"), - workspace->domain, + account->name, weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - workspace->name, + account->jid ? account->jid : "???", weechat_color("chat_delimiters"), weechat_color("reset")); - - free_teaminfo(xmpp_teaminfo); -} - -void xmpp_command_fetch_workspace(char *token) -{ - xmpp_teaminfo_fetch(token, &xmpp_command_add_workspace); - - free(token); } -void xmpp_command_workspace_register(int argc, char **argv) +void command__account_add(int argc, char **argv) { - char *code; + char *name, *jid = NULL, *password = NULL; - if (argc > 2) - { - code = argv[2]; - - if (strncmp("xoxp", code, 4) == 0) - { - xmpp_command_fetch_workspace(strdup(code)); - } - else - { - xmpp_oauth_request_token(code, &xmpp_command_fetch_workspace); - } - } - else + switch (argc) { - weechat_printf(NULL, - _("\n#### Retrieving a Xmpp token via OAUTH ####\n" - "1) Paste this into a browser: https://xmpp.com/oauth/authorize?client_id=%s&scope=client\n" - "2) Select the team you wish to access from weechat in your browser.\n" - "3) Click \"Authorize\" in the browser **IMPORTANT: the redirect will fail, this is expected**\n" - "4) Copy the \"code\" portion of the URL to your clipboard\n" - "5) Return to weechat and run `/xmpp register [code]`\n"), - XMPP_CLIENT_ID); + case 5: + password = argv[4]; + case 4: + jid = argv[3]; + case 3: + name = argv[2]; + command__add_account(name, jid, password); + break; + default: + weechat_printf(NULL, _("account add: wrong number of arguments")); + break; } } -int xmpp_command_connect_workspace(xmpp_conn_t *workspace) +int command__connect_account(struct t_account *account) { - if (!workspace) + if (!account) return 0; - if (workspace->is_connected) + if (account->is_connected) { weechat_printf( NULL, - _("%s%s: already connected to workspace \"%s\"!"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, - workspace->domain); + _("%s%s: already connected to account \"%s\"!"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + account->name); } - xmpp_workspace_connect(workspace); + account__connect(account); return 1; } -int xmpp_command_workspace_connect(int argc, char **argv) +int command__account_connect(int argc, char **argv) { int i, nb_connect, connect_ok; - xmpp_conn_t *ptr_workspace; + struct t_account *ptr_account; (void) argc; (void) argv; @@ -232,10 +217,10 @@ int xmpp_command_workspace_connect(int argc, char **argv) for (i = 2; i < argc; i++) { nb_connect++; - ptr_workspace = xmpp_workspace_search(argv[i]); - if (ptr_workspace) + ptr_account = account__search(argv[i]); + if (ptr_account) { - if (!xmpp_command_connect_workspace(ptr_workspace)) + if (!command__connect_account(ptr_account)) { connect_ok = 0; } @@ -244,9 +229,9 @@ int xmpp_command_workspace_connect(int argc, char **argv) { weechat_printf( NULL, - _("%s%s: workspace not found \"%s\" " - "(register first with: /xmpp register)"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, + _("%s%s: account not found \"%s\" " + "(add one first with: /account add)"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, argv[i]); } } @@ -254,10 +239,10 @@ int xmpp_command_workspace_connect(int argc, char **argv) return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; } -void xmpp_command_workspace_delete(int argc, char **argv) +void command__account_delete(int argc, char **argv) { - xmpp_conn_t *workspace; - char *workspace_domain; + struct t_account *account; + char *account_name; if (argc < 3) { @@ -270,88 +255,87 @@ void xmpp_command_workspace_delete(int argc, char **argv) return; } - workspace = xmpp_workspace_search(argv[2]); - if (!workspace) + account = account__search(argv[2]); + if (!account) { weechat_printf( NULL, - _("%s%s: workspace \"%s\" not found for \"%s\" command"), - weechat_prefix("error"), XMPP_PLUGIN_NAME, + _("%s%s: account \"%s\" not found for \"%s\" command"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, argv[2], "xmpp delete"); return; } - if (workspace->is_connected) + if (account->is_connected) { weechat_printf( NULL, - _("%s%s: you cannot delete workspace \"%s\" because you" + _("%s%s: you cannot delete account \"%s\" because you" "are connected. Try \"/xmpp disconnect %s\" first."), - weechat_prefix("error"), XMPP_PLUGIN_NAME, + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, argv[2], argv[2]); return; } - workspace_domain = strdup(workspace->domain); - xmpp_workspace_free(workspace); + account_name = strdup(account->name); + account__free(account); weechat_printf ( NULL, - _("%s: workspace %s%s%s has been deleted"), - XMPP_PLUGIN_NAME, + _("%s: account %s%s%s has been deleted"), + WEECHAT_XMPP_PLUGIN_NAME, weechat_color("chat_server"), - (workspace_domain) ? workspace_domain : "???", + (account_name) ? account_name : "???", weechat_color("reset")); - if (workspace_domain) - free(workspace_domain); + if (account_name) + free(account_name); } -*/ -int xmpp_command_xmpp(const void *pointer, void *data, - struct t_gui_buffer *buffer, int argc, - char **argv, char **argv_eol) +int command__account(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) { (void) pointer; (void) data; (void) buffer; - //if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) - //{ - // xmpp_command_workspace_list(argc, argv); - // return WEECHAT_RC_OK; - //} - - //if (argc > 1) - //{ - // if (weechat_strcasecmp(argv[1], "register") == 0) - // { - // xmpp_command_workspace_register(argc, argv); - // return WEECHAT_RC_OK; - // } - - // if (weechat_strcasecmp(argv[1], "connect") == 0) - // { - // xmpp_command_workspace_connect(argc, argv); - // return WEECHAT_RC_OK; - // } - - // if (weechat_strcasecmp(argv[1], "delete") == 0) - // { - // xmpp_command_workspace_delete(argc, argv); - // return WEECHAT_RC_OK; - // } - - // WEECHAT_COMMAND_ERROR; - //} + if (argc <= 1 || weechat_strcasecmp(argv[1], "list") == 0) + { + command__account_list(argc, argv); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + if (weechat_strcasecmp(argv[1], "add") == 0) + { + command__account_add(argc, argv); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp(argv[1], "connect") == 0) + { + command__account_connect(argc, argv); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp(argv[1], "delete") == 0) + { + command__account_delete(argc, argv); + return WEECHAT_RC_OK; + } + + WEECHAT_COMMAND_ERROR; + } return WEECHAT_RC_OK; } -int xmpp_command_me(const void *pointer, void *data, - struct t_gui_buffer *buffer, int argc, - char **argv, char **argv_eol) +int command__me(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) { - xmpp_conn_t *ptr_workspace = NULL; - //struct t_xmpp_channel *ptr_channel = NULL; + struct t_account *ptr_account = NULL; + struct t_xmpp_channel *ptr_channel = NULL; //struct t_xmpp_request *request; char *text; @@ -360,76 +344,72 @@ int xmpp_command_me(const void *pointer, void *data, (void) buffer; (void) argv; - //xmpp_buffer_get_workspace_and_channel(buffer, &ptr_workspace, &ptr_channel); - - //if (!ptr_workspace) - // return WEECHAT_RC_ERROR; - - //if (!ptr_channel) - //{ - // weechat_printf ( - // ptr_workspace->buffer, - // _("%s%s: \"%s\" command can not be executed on a workspace buffer"), - // weechat_prefix("error"), XMPP_PLUGIN_NAME, "me"); - // return WEECHAT_RC_OK; - //} - - //if (!ptr_workspace->is_connected) - //{ - // weechat_printf(buffer, - // _("%s%s: you are not connected to server"), - // weechat_prefix("error"), XMPP_PLUGIN_NAME); - // return WEECHAT_RC_OK; - //} - - //if (argc > 1) - //{ - // text = malloc(XMPP_MESSAGE_MAX_LENGTH); - // if (!text) - // { - // weechat_printf(buffer, - // _("%s%s: error allocating string"), - // weechat_prefix("error"), XMPP_PLUGIN_NAME); - // return WEECHAT_RC_ERROR; - // } - // lws_urlencode(text, argv_eol[1], XMPP_MESSAGE_MAX_LENGTH); - - // request = xmpp_request_chat_memessage(ptr_workspace, - // weechat_config_string( - // ptr_workspace->options[XMPP_WORKSPACE_OPTION_TOKEN]), - // ptr_channel->id, text); - // if (request) - // xmpp_workspace_register_request(ptr_workspace, request); - - // free(text); - //} + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_channel) + { + weechat_printf ( + ptr_account->buffer, + _("%s%s: \"%s\" command can not be executed on a account buffer"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "me"); + return WEECHAT_RC_OK; + } + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + text = argv_eol[1]; + + //request = xmpp_request_chat_memessage(ptr_account, + // weechat_config_string( + // ptr_account->options[XMPP_ACCOUNT_OPTION_TOKEN]), + // ptr_channel->id, text); + //if (request) + // xmpp_account_register_request(ptr_account, request); + } return WEECHAT_RC_OK; } -void xmpp_command_init() +void command__init() { - weechat_hook_command( - "xmpp", - N_("xmpp control"), + struct t_hook *hook; + + hook = weechat_hook_command( + "account", + N_("handle xmpp accounts"), N_("list" - " || register [token]" - " || connect " - " || delete "), - N_(" list: list workspaces\n" - "register: add a xmpp workspace\n" - " connect: connect to a xmpp workspace\n" - " delete: delete a xmpp workspace\n"), + " || add " + " || connect " + " || delete "), + N_(" list: list accounts\n" + " add: add a xmpp account\n" + "connect: connect to a xmpp account\n" + " delete: delete a xmpp account\n"), "list" - " || register %(xmpp_token)" - " || connect %(xmpp_workspace)" - " || delete %(xmpp_workspace)", - &xmpp_command_xmpp, NULL, NULL); - - weechat_hook_command( + " || add %(xmpp_account)" + " || connect %(xmpp_account)" + " || delete %(xmpp_account)", + &command__account, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /account"); + + hook = weechat_hook_command( "me", N_("send a xmpp action to the current channel"), N_(""), N_("message: message to send"), - NULL, &xmpp_command_me, NULL, NULL); + NULL, &command__me, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /me"); } diff --git a/command.h b/command.h index 1e79a41..f8af048 100644 --- a/command.h +++ b/command.h @@ -5,6 +5,6 @@ #ifndef _WEECHAT_XMPP_COMMAND_H_ #define _WEECHAT_XMPP_COMMAND_H_ -extern void xmpp_command_init(); +void command__init(); #endif /*WEECHAT_XMPP_COMMAND_H*/ diff --git a/config.c b/config.c index cc5789b..dcc1c2c 100644 --- a/config.c +++ b/config.c @@ -8,41 +8,40 @@ #include #include "plugin.h" +#include "account.h" #include "config.h" -struct t_config_file *xmpp_config_file; +struct t_config_file *config_file; -//struct t_config_section *xmpp_config_section_workspace_default; -//struct t_config_section *xmpp_config_section_workspace; +struct t_config_section *config_section_account_default; +struct t_config_section *config_section_account; -struct t_config_option *xmpp_config_server_jid; -struct t_config_option *xmpp_config_server_password; -struct t_config_option *xmpp_config_look_nick_completion_smart; +struct t_config_option *config_look_nick_completion_smart; -/* -struct t_config_option *xmpp_config_workspace_default[XMPP_WORKSPACE_NUM_OPTIONS]; +struct t_config_option *config_account_default[ACCOUNT_NUM_OPTIONS]; -int xmpp_config_workspace_check_value_cb(const void *pointer, void *data, - struct t_config_option *option, - const char *value) +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; + + return 1; } -void xmpp_config_workspace_change_cb(const void *pointer, void *data, - struct t_config_option *option) +void config__account_change_cb(const void *pointer, void *data, + struct t_config_option *option) { (void) pointer; (void) data; (void) option; } -void xmpp_config_workspace_default_change_cb(const void *pointer, void *data, - struct t_config_option *option) +void config__account_default_change_cb(const void *pointer, void *data, + struct t_config_option *option) { (void) pointer; (void) data; @@ -50,36 +49,84 @@ void xmpp_config_workspace_default_change_cb(const void *pointer, void *data, } struct t_config_option * -xmpp_config_workspace_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) +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; + struct t_config_option *new_option; new_option = NULL; switch (index_option) { - case XMPP_WORKSPACE_OPTION_TOKEN: + 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 api token"), + N_("XMPP Server JID"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -91,46 +138,46 @@ xmpp_config_workspace_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; - case XMPP_WORKSPACE_NUM_OPTIONS: + case ACCOUNT_NUM_OPTIONS: break; } return new_option; } -void xmpp_config_workspace_create_default_options(struct t_config_section *section) +void config__account_create_default_options(struct t_config_section *section) { int i; - for (i = 0; i < XMPP_WORKSPACE_NUM_OPTIONS; i++) - { - xmpp_config_workspace_default[i] = xmpp_config_workspace_new_option( - xmpp_config_file, - section, - i, - xmpp_workspace_options[i][0], - xmpp_workspace_options[i][1], - xmpp_workspace_options[i][1], - 0, - &xmpp_config_workspace_check_value_cb, - xmpp_workspace_options[i][0], - NULL, - &xmpp_config_workspace_default_change_cb, - xmpp_workspace_options[i][0], - NULL); - } + for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) + { + config_account_default[i] = config__account_new_option( + config_file, + section, + i, + account_options[i][0], + account_options[i][1], + account_options[i][1], + 0, + &config__account_check_value_cb, + account_options[i][0], + NULL, + &config__account_default_change_cb, + account_options[i][0], + NULL); + } } -int xmpp_config_workspace_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) +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_xmpp_workspace *ptr_workspace; + struct t_account *ptr_account; int index_option, rc, i; - char *pos_option, *workspace_domain; + char *pos_option, *account_name; (void) pointer; (void) data; @@ -144,42 +191,42 @@ int xmpp_config_workspace_read_cb (const void *pointer, void *data, pos_option = strrchr(option_name, '.'); if (pos_option) { - workspace_domain = weechat_strndup(option_name, - pos_option - option_name); + account_name = weechat_strndup(option_name, + pos_option - option_name); pos_option++; - if (workspace_domain) + if (account_name) { - index_option = xmpp_workspace_search_option(pos_option); + index_option = account__search_option(pos_option); if (index_option >= 0) { - ptr_workspace = xmpp_workspace_search(workspace_domain); - if (!ptr_workspace) - ptr_workspace = xmpp_workspace_alloc(workspace_domain); - if (ptr_workspace) + ptr_account = account__search(account_name); + if (!ptr_account) + ptr_account = account__alloc(account_name); + if (ptr_account) { - if (ptr_workspace->reloading_from_config - && !ptr_workspace->reloaded_from_config) + if (!ptr_account->reloading_from_config++) { - for (i = 0; i < XMPP_WORKSPACE_NUM_OPTIONS; i++) + for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) { weechat_config_option_set( - ptr_workspace->options[i], NULL, 1); + ptr_account->options[i], NULL, 1); } - ptr_workspace->reloaded_from_config = 1; } + ptr_account->reloading_from_config %= + ACCOUNT_NUM_OPTIONS; rc = weechat_config_option_set( - ptr_workspace->options[index_option], value, 1); + ptr_account->options[index_option], value, 1); } else { weechat_printf( NULL, - _("%s%s: error adding workspace \"%s\""), - weechat_prefix("error"), XMPP_PLUGIN_NAME, - workspace_domain); + _("%s%s: error adding account \"%s\""), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + account_name); } } - free(workspace_domain); + free(account_name); } } } @@ -188,18 +235,18 @@ int xmpp_config_workspace_read_cb (const void *pointer, void *data, { weechat_printf( NULL, - _("%s%s: error creating workspace option \"%s\""), - weechat_prefix("error"), XMPP_PLUGIN_NAME, option_name); + _("%s%s: error creating account option \"%s\""), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, option_name); } return rc; } -int xmpp_config_workspace_write_cb (const void *pointer, void *data, - struct t_config_file *config_file, - const char *section_name) +int config__account_write_cb (const void *pointer, void *data, + struct t_config_file *config_file, + const char *section_name) { - struct t_xmpp_workspace *ptr_workspace; + struct t_account *ptr_account; int i; (void) pointer; @@ -208,88 +255,61 @@ int xmpp_config_workspace_write_cb (const void *pointer, void *data, if (!weechat_config_write_line(config_file, section_name, NULL)) return WEECHAT_CONFIG_WRITE_ERROR; - for (ptr_workspace = xmpp_workspaces; ptr_workspace; - ptr_workspace = ptr_workspace->next_workspace) + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) { - for (i = 0; i < XMPP_WORKSPACE_NUM_OPTIONS; i++) + for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) { if (!weechat_config_write_option(config_file, - ptr_workspace->options[i])) + ptr_account->options[i])) return WEECHAT_CONFIG_WRITE_ERROR; } } return WEECHAT_CONFIG_WRITE_OK; } -*/ -int xmpp_config_reload (const void *pointer, void *data, - struct t_config_file *config_file) +int config__reload (const void *pointer, void *data, + struct t_config_file *config_file) { (void) pointer; (void) data; - //weechat_config_section_free_options(xmpp_config_section_workspace_default); - //weechat_config_section_free_options(xmpp_config_section_workspace); - //xmpp_workspace_free_all(); + weechat_config_section_free_options(config_section_account_default); + weechat_config_section_free_options(config_section_account); + account__free_all(); return weechat_config_reload(config_file); } -int xmpp_config_init() +int config__init() { - struct t_config_section *ptr_section_server; - struct t_config_section *ptr_section_look; + struct t_config_section *ptr_section; - xmpp_config_file = weechat_config_new(WEECHAT_XMPP_CONFIG_NAME, - &xmpp_config_reload, NULL, NULL); + config_file = weechat_config_new(WEECHAT_XMPP_CONFIG_NAME, + &config__reload, NULL, NULL); - if(!xmpp_config_file) + if(!config_file) return 0; - ptr_section_server = weechat_config_new_section( - xmpp_config_file, "server", - 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - - ptr_section_look = weechat_config_new_section( - xmpp_config_file, "look", - 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - - if (!ptr_section_server - || !ptr_section_server - || !ptr_section_look) + 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(xmpp_config_file); - xmpp_config_file = NULL; + weechat_config_free(config_file); + config_file = NULL; return 0; } - xmpp_config_server_jid = weechat_config_new_option ( - xmpp_config_file, ptr_section_server, - "jid", "string", - N_("XMPP Server JID"), - NULL, 0, 0, "", "", 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - xmpp_config_server_password = weechat_config_new_option ( - xmpp_config_file, ptr_section_server, - "password", "string", - N_("XMPP Server Password"), - NULL, 0, 0, "", "", 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - xmpp_config_look_nick_completion_smart = weechat_config_new_option ( - xmpp_config_file, ptr_section_look, + 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), " @@ -297,61 +317,61 @@ int xmpp_config_init() "off|speakers|speakers_highlights", 0, 0, "speakers", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - //ptr_section = weechat_config_new_section( - // xmpp_config_file, "workspace_default", - // 0, 0, - // NULL, NULL, NULL, - // NULL, NULL, NULL, - // NULL, NULL, NULL, - // NULL, NULL, NULL, - // NULL, NULL, NULL); - - //if (!ptr_section) - //{ - // weechat_config_free(xmpp_config_file); - // xmpp_config_file = NULL; - // return 0; - //} - - //xmpp_config_section_workspace_default = ptr_section; - - //xmpp_config_workspace_create_default_options(ptr_section); - - // ptr_section = weechat_config_new_section( - // xmpp_config_file, "workspace", - // 0, 0, - // &xmpp_config_workspace_read_cb, NULL, NULL, - // &xmpp_config_workspace_write_cb, NULL, NULL, - // NULL, NULL, NULL, - // NULL, NULL, NULL, - // NULL, NULL, NULL); - - //if (!ptr_section) - //{ - // weechat_config_free(xmpp_config_file); - // xmpp_config_file = NULL; - // return 0; - //} - - //xmpp_config_section_workspace = ptr_section; + ptr_section = weechat_config_new_section( + config_file, "account_default", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + + if (!ptr_section) + { + weechat_config_free(config_file); + config_file = NULL; + return 0; + } + + config_section_account_default = ptr_section; + + config__account_create_default_options(ptr_section); + + ptr_section = weechat_config_new_section( + config_file, "account", + 0, 0, + &config__account_read_cb, NULL, NULL, + &config__account_write_cb, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + + if (!ptr_section) + { + weechat_config_free(config_file); + config_file = NULL; + return 0; + } + + config_section_account = ptr_section; return 1; } -int xmpp_config_read() +int config__read() { - int rc; + int rc; - rc = weechat_config_read(xmpp_config_file); + rc = weechat_config_read(config_file); return rc; } -int xmpp_config_write() +int config__write() { - return weechat_config_write(xmpp_config_file); + return weechat_config_write(config_file); } -void xmpp_config_free() +void config__free() { } diff --git a/config.h b/config.h index c291cc4..8b2214d 100644 --- a/config.h +++ b/config.h @@ -7,53 +7,51 @@ #define WEECHAT_XMPP_CONFIG_NAME "xmpp" -enum t_xmpp_config_nick_completion +enum t_config_nick_completion { - XMPP_CONFIG_NICK_COMPLETION_SMART_OFF = 0, - XMPP_CONFIG_NICK_COMPLETION_SMART_SPEAKERS, - XMPP_CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, + CONFIG_NICK_COMPLETION_SMART_OFF = 0, + CONFIG_NICK_COMPLETION_SMART_SPEAKERS, + CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, }; -extern struct t_config_file *xmpp_config_file; - -//extern struct t_config_section *xmpp_config_section_workspace_default; -//extern struct t_config_section *xmpp_config_section_workspace; - -extern struct t_config_option *xmpp_config_server_jid; -extern struct t_config_option *xmpp_config_server_password; -extern struct t_config_option *xmpp_config_look_nick_completion_smart; - -//extern struct t_config_option *xmpp_config_workspace_default[]; - -//int xmpp_config_workspace_check_value_cb(const void *pointer, void *data, -// struct t_config_option *option, -// const char *value); - -//void xmpp_config_workspace_change_cb(const void *pointer, void *data, -// struct t_config_option *option); - -//struct t_config_option *xmpp_config_workspace_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 xmpp_config_init(); -extern int xmpp_config_read(); -extern int xmpp_config_write(); -extern void xmpp_config_free(); +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(); #endif /*WEECHAT_XMPP_CONFIG_H*/ diff --git a/connection.c b/connection.c index 77ed274..0f0b93e 100644 --- a/connection.c +++ b/connection.c @@ -15,42 +15,13 @@ //#include "api/xmpp-api-message.h" //#include "api/xmpp-api-user-typing.h" -xmpp_conn_t *xmpp_connection; +xmpp_conn_t *connection; -void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg) -{ - (void) userdata; - - static const char *log_level_name[4] = {"debug", "info", "warn", "error"}; - - time_t date = time(NULL); - const char *timestamp = weechat_util_get_time_string(&date); - - weechat_printf( - NULL, - _("%s%s/%s (%s): %s"), - weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, area, - log_level_name[level], msg); -} - -xmpp_log_t xmpp_logger = { - &xmpp_log_emit_weechat, - NULL -}; - -void xmpp_connection_init() +void connection__init() { xmpp_initialize(); } -int xmpp_connection_autoconnect(const void *pointer, void *data, int remaining_calls) -{ - xmpp_connection_connect(weechat_config_string(xmpp_config_server_jid), - weechat_config_string(xmpp_config_server_password)); - - return WEECHAT_RC_OK; -} - int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { xmpp_stanza_t *reply, *query, *name, *version, *text; @@ -142,9 +113,9 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) return 1; } -void xmpp_connection_on_connected(xmpp_conn_t *conn, xmpp_conn_event_t status, - int error, xmpp_stream_error_t *stream_error, - void *userdata) +void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, + int error, xmpp_stream_error_t *stream_error, + void *userdata) { xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; @@ -168,97 +139,60 @@ void xmpp_connection_on_connected(xmpp_conn_t *conn, xmpp_conn_event_t status, } } -void xmpp_connection_connect(const char* jid, const char* password) +int connection__connect(xmpp_ctx_t *context, xmpp_conn_t **connection, + xmpp_log_t *logger, const char* jid, + const char* password, int tls) { - xmpp_ctx_t *xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger); - - xmpp_connection = xmpp_conn_new(xmpp_context); - xmpp_conn_set_jid(xmpp_connection, jid); - xmpp_conn_set_pass(xmpp_connection, password); - auto flags = xmpp_conn_get_flags(xmpp_connection); - //flags |= XMPP_CONN_FLAG_TRUST_TLS; - xmpp_conn_set_flags(xmpp_connection, flags); - xmpp_connect_client(xmpp_connection, NULL, 0, xmpp_connection_on_connected, xmpp_context); - //struct lws_context_creation_info ctxinfo; - //struct lws_client_connect_info ccinfo; - //const char *url_protocol, *url_path; - //char path[512]; - - //memset(&ctxinfo, 0, sizeof(ctxinfo)); - //memset(&ccinfo, 0, sizeof(ccinfo)); - - //ccinfo.port = 443; - - //if (lws_parse_uri(workspace->ws_url, - // &url_protocol, &ccinfo.address, - // &ccinfo.port, &url_path)) - //{ - // weechat_printf( - // workspace->buffer, - // _("%s%s: error connecting to xmpp: bad websocket uri"), - // weechat_prefix("error"), XMPP_PLUGIN_NAME); - // return; - //} - - //path[0] = '/'; - //strncpy(path + 1, url_path, sizeof(path) - 2); - //path[sizeof(path) - 1] = '\0'; - - //ccinfo.path = path; - - //ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - //ctxinfo.port = CONTEXT_PORT_NO_LISTEN; - //ctxinfo.protocols = protocols; - //ctxinfo.uid = -1; - //ctxinfo.gid = -1; + *connection = xmpp_conn_new(context); + xmpp_conn_set_jid(*connection, jid); + xmpp_conn_set_pass(*connection, password); - //workspace->context = lws_create_context(&ctxinfo); - //if (!workspace->context) - //{ - // weechat_printf( - // workspace->buffer, - // _("%s%s: error connecting to xmpp: lws init failed"), - // weechat_prefix("error"), XMPP_PLUGIN_NAME); - // return; - //} - //else - //{ - // weechat_printf( - // workspace->buffer, - // _("%s%s: connecting to %s://%s:%d%s"), - // weechat_prefix("network"), XMPP_PLUGIN_NAME, - // url_protocol, ccinfo.address, ccinfo.port, path); - //} + auto flags = xmpp_conn_get_flags(*connection); + switch (tls) + { + case 0: + flags |= XMPP_CONN_FLAG_DISABLE_TLS; + break; + case 1: + break; + case 2: + flags |= XMPP_CONN_FLAG_TRUST_TLS; + break; + default: + break; + } + xmpp_conn_set_flags(*connection, flags); - //ccinfo.context = workspace->context; - //ccinfo.ssl_connection = LCCSCF_USE_SSL; - //ccinfo.host = ccinfo.address; - //ccinfo.origin = ccinfo.address; - //ccinfo.ietf_version_or_minus_one = -1; - //ccinfo.protocol = protocols[0].name; - //ccinfo.pwsi = &workspace->client_wsi; - //ccinfo.userdata = workspace; + if (xmpp_connect_client(*connection, NULL, 0, &connection__handler, context) + != XMPP_EOK) + { + weechat_printf( + NULL, + _("%s%s: error connecting to %s"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + jid); + return 0; + } - //lws_client_connect_via_info(&ccinfo); + weechat_printf( + NULL, + _("%s%s: c'necting to %s"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + jid); + return 1; } -int xmpp_connection_check_events(const void *pointer, void *data, int remaining_calls) +void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, + const unsigned long timeout) { - (void) pointer; - (void) data; - (void) remaining_calls; - - if (xmpp_connection) + if (connection) { - xmpp_ctx_t *xmpp_context = xmpp_conn_get_context(xmpp_connection); - - xmpp_run_once(xmpp_context, 10); + xmpp_run_once(context ? context : xmpp_conn_get_context(connection), + timeout); } - - return WEECHAT_RC_OK; } -int xmpp_connection_route_message(xmpp_conn_t *workspace, +int connection__route_message(xmpp_conn_t *workspace, const char *type, void *message) { //struct stringcase key; diff --git a/connection.h b/connection.h index 9507803..1b049ea 100644 --- a/connection.h +++ b/connection.h @@ -5,17 +5,16 @@ #ifndef _WEECHAT_XMPP_CONNECTION_H_ #define _WEECHAT_XMPP_CONNECTION_H_ -extern xmpp_conn_t *xmpp_connection; +void connection__init(); -void xmpp_connection_init(); +int connection__connect(xmpp_ctx_t *context, xmpp_conn_t **connection, + xmpp_log_t *logger, const char* jid, + const char* password, int tls); -int xmpp_connection_autoconnect(const void *pointer, void *data, int remaining_calls); +void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, + const unsigned long timeout); -void xmpp_connection_connect(const char* jid, const char* password); - -int xmpp_connection_check_events(const void *pointer, void *data, int remaining_calls); - -int xmpp_connection_route_message(xmpp_conn_t *connection, - const char *type, void *message); +int connection__route_message(xmpp_conn_t *connection, + const char *type, void *message); #endif /*WEECHAT_XMPP_CONNECTION_H*/ diff --git a/input.c b/input.c new file mode 100644 index 0000000..6aebd91 --- /dev/null +++ b/input.c @@ -0,0 +1,64 @@ +// 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 "plugin.h" +#include "account.h" +#include "channel.h" +#include "buffer.h" +//#include "request.h" +#include "message.h" +#include "input.h" + +int input__data(struct t_gui_buffer *buffer, const char *text) +{ + struct t_account *account = NULL; + struct t_channel *channel = NULL; + struct t_request *request; + + buffer__get_account_and_channel(buffer, &account, &channel); + + if (!account) + return WEECHAT_RC_ERROR; + + if (channel) + { + if (!account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + //TODO: SEND + //request = request_chat_postmessage(account, + // weechat_config_string( + // account->options[ACCOUNT_OPTION_TOKEN]), + // channel->id, text); + //if (request) + // account__register_request(account, request); + } + else + { + weechat_printf(buffer, + _("%s%s: this buffer is not a channel!"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + } + + return WEECHAT_RC_OK; +} + +int input__data_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *text) +{ + (void) pointer; + (void) data; + + return input__data(buffer, text); +} diff --git a/input.h b/input.h new file mode 100644 index 0000000..c218506 --- /dev/null +++ b/input.h @@ -0,0 +1,12 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_INPUT_H_ +#define _WEECHAT_XMPP_INPUT_H_ + +int input__data_cb(const void *pointer, void *data, + struct t_gui_buffer *buffer, + const char *input_data); + +#endif /*WEECHAT_XMPP_INPUT_H*/ diff --git a/message.c b/message.c new file mode 100644 index 0000000..0314d44 --- /dev/null +++ b/message.c @@ -0,0 +1,249 @@ +// 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 +#include + +#include "plugin.h" +#include "account.h" +#include "channel.h" +#include "user.h" +#include "message.h" + +static const char format_regex[] = "<([^>]*?)>"; +static const size_t max_groups = 2; + +char *message__translate_code(struct t_account *account, + const char *code) +{ + struct t_channel *channel; + struct t_user *user; + size_t resultlen; + char *identifier, *alttext, *result, *symbol, *prefix; + + identifier = strdup(code); + alttext = strchr(identifier, '|'); + if (alttext) + *alttext++ = '\0'; + + switch (identifier[0]) + { + case '#': /* channel */ + if (alttext) + { + prefix = "#"; + symbol = strdup(alttext); + } + else + { + channel = channel__search(account, identifier+1); + if (channel) + { + prefix = "#"; + symbol = strdup(channel->name); + } + else + { + prefix = "Channel:"; + symbol = strdup(identifier+1); + } + } + break; + case '@': /* user */ + if (alttext) + { + prefix = "@"; + symbol = strdup(alttext); + } + else + { + user = user__search(account, identifier+1); + if (user) + { + prefix = "@"; + symbol = strdup(user->profile.display_name); + } + else + { + prefix = "User:"; + symbol = strdup(identifier+1); + } + } + break; + case '!': /* special */ + if (alttext) + { + prefix = "@"; + symbol = strdup(alttext); + } + else + { + prefix = "@"; + symbol = strdup(identifier+1); + } + break; + default: /* url */ + prefix = ""; + symbol = strdup(code); + break; + } + + free(identifier); + resultlen = snprintf(NULL, 0, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")) + 1; + result = malloc(resultlen); + snprintf(result, resultlen, "%s%s%s%s", weechat_color("chat_nick"), prefix, symbol, weechat_color("reset")); + free(symbol); + + return result; +} + +void message__htmldecode(char *dest, const char *src, size_t n) +{ + size_t i, j; + + for (i = 0, j = 0; i < n; i++, j++) + switch (src[i]) + { + case '\0': + dest[j] = '\0'; + return; + case '&': + if (src[i+1] == 'g' && + src[i+2] == 't' && + src[i+3] == ';') + { + dest[j] = '>'; + i += 3; + break; + } + else if (src[i+1] == 'l' && + src[i+2] == 't' && + src[i+3] == ';') + { + dest[j] = '<'; + i += 3; + break; + } + else if (src[i+1] == 'a' && + src[i+2] == 'm' && + src[i+3] == 'p' && + src[i+4] == ';') + { + dest[j] = '&'; + i += 4; + break; + } + /* fallthrough */ + default: + dest[j] = src[i]; + break; + } + dest[j-1] = '\0'; + return; +} + +char *message__decode(struct t_account *account, + const char *text) +{ + int rc; + regex_t reg; + regmatch_t groups[max_groups]; + char msgbuf[100]; + char *decoded_text; + const char *cursor; + size_t offset; + + if ((rc = regcomp(®, format_regex, REG_EXTENDED))) + { + regerror(rc, ®, msgbuf, sizeof(msgbuf)); + weechat_printf( + account->buffer, + _("%s%s: error compiling message formatting regex: %s"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + msgbuf); + return strdup(text); + } + + decoded_text = malloc(MESSAGE_MAX_LENGTH); + if (!decoded_text) + { + regfree(®); + weechat_printf( + account->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return strdup(text); + } + decoded_text[0] = '\0'; + + for (cursor = text; regexec(®, cursor, max_groups, groups, 0) == 0; cursor += offset) + { + offset = groups[0].rm_eo; + + char *copy = strdup(cursor); + if (!copy) + { + regfree(®); + free(decoded_text); + weechat_printf( + account->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return strdup(text); + } + copy[groups[1].rm_eo] = '\0'; + + char *match = strdup(copy + groups[1].rm_so); + if (!match) + { + free(copy); + regfree(®); + free(decoded_text); + weechat_printf( + account->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return strdup(text); + } + copy[groups[0].rm_so] = '\0'; + + char *prematch = strdup(copy); + if (!prematch) + { + free(match); + free(copy); + regfree(®); + free(decoded_text); + weechat_printf( + account->buffer, + _("%s%s: error allocating space for message"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return strdup(text); + } + free(copy); + + strncat(decoded_text, prematch, + MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + free(prematch); + + char *replacement = message__translate_code(account, match); + free(match); + + strncat(decoded_text, replacement, + MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + free(replacement); + } + strncat(decoded_text, cursor, + MESSAGE_MAX_LENGTH - strlen(decoded_text) - 1); + + message__htmldecode(decoded_text, decoded_text, + MESSAGE_MAX_LENGTH); + + regfree(®); + return decoded_text; +} diff --git a/message.h b/message.h new file mode 100644 index 0000000..fdf7263 --- /dev/null +++ b/message.h @@ -0,0 +1,13 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_MESSAGE_H_ +#define _WEECHAT_XMPP_MESSAGE_H_ + +#define MESSAGE_MAX_LENGTH 40000 + +char *message__decode(struct t_account *account, + const char *text); + +#endif /*WEECHAT_XMPP_MESSAGE_H*/ diff --git a/plugin.c b/plugin.c index 582a524..fc0c9f2 100644 --- a/plugin.c +++ b/plugin.c @@ -12,13 +12,13 @@ #include "config.h" #include "connection.h" #include "command.h" -//#include "xmpp-workspace.h" -//#include "xmpp-buffer.h" +#include "account.h" +#include "buffer.h" //#include "xmpp-completion.h" WEECHAT_PLUGIN_NAME(WEECHAT_XMPP_PLUGIN_NAME); -WEECHAT_PLUGIN_DESCRIPTION(N_("XMPP protocol")); +WEECHAT_PLUGIN_DESCRIPTION(N_("XMPP client protocol")); WEECHAT_PLUGIN_AUTHOR("bqv "); WEECHAT_PLUGIN_VERSION(WEECHAT_XMPP_PLUGIN_VERSION); WEECHAT_PLUGIN_LICENSE("MPL2"); @@ -26,35 +26,32 @@ WEECHAT_PLUGIN_PRIORITY(5500); struct t_weechat_plugin *weechat_xmpp_plugin = NULL; -struct t_hook *xmpp_hook_timer = NULL; +struct t_hook *weechat_xmpp_autoconnect_timer = NULL; +struct t_hook *weechat_xmpp_process_timer = NULL; -struct t_gui_bar_item *xmpp_typing_bar_item = NULL; +struct t_gui_bar_item *weechat_xmpp_typing_bar_item = NULL; int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { (void) argc; (void) argv; - weechat_plugin = plugin; + weechat_xmpp_plugin = plugin; - if (!xmpp_config_init()) + if (!config__init()) return WEECHAT_RC_ERROR; - xmpp_config_read(); + config__read(); - xmpp_connection_init(); + connection__init(); - xmpp_command_init(); + command__init(); - //xmpp_completion_init(); + //completion__init(); - xmpp_hook_timer = weechat_hook_timer(1 * 1000, 0, 1, - &xmpp_connection_autoconnect, - NULL, NULL); - - xmpp_hook_timer = weechat_hook_timer(0.1 * 1000, 0, 0, - &xmpp_connection_check_events, - NULL, NULL); + weechat_xmpp_process_timer = weechat_hook_timer(0.1 * 1000, 0, 0, + &account__timer_cb, + NULL, NULL); if (!weechat_bar_search("typing")) { @@ -64,9 +61,9 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) "off", "xmpp_typing"); } - //xmpp_typing_bar_item = weechat_bar_item_new("xmpp_typing", - // &xmpp_buffer_typing_bar_cb, - // NULL, NULL); + weechat_xmpp_typing_bar_item = weechat_bar_item_new("xmpp_typing", + &buffer__typing_bar_cb, + NULL, NULL); return WEECHAT_RC_OK; } @@ -76,25 +73,19 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) // make C compiler happy (void) plugin; - if (xmpp_typing_bar_item) - weechat_bar_item_remove(xmpp_typing_bar_item); - - if (xmpp_hook_timer) - weechat_unhook(xmpp_hook_timer); + if (weechat_xmpp_typing_bar_item) + weechat_bar_item_remove(weechat_xmpp_typing_bar_item); - xmpp_config_write(); + if (weechat_xmpp_autoconnect_timer) + weechat_unhook(weechat_xmpp_autoconnect_timer); + if (weechat_xmpp_process_timer) + weechat_unhook(weechat_xmpp_process_timer); - if (xmpp_connection) - { - xmpp_ctx_t *xmpp_context = xmpp_conn_get_context(xmpp_connection); + config__write(); - if (xmpp_conn_is_connected(xmpp_connection)) - xmpp_disconnect(xmpp_connection); + account__disconnect_all(); - xmpp_conn_release(xmpp_connection); - - xmpp_ctx_free(xmpp_context); - } + account__free_all(); xmpp_shutdown(); diff --git a/user.c b/user.c new file mode 100644 index 0000000..2469af3 --- /dev/null +++ b/user.c @@ -0,0 +1,242 @@ +// 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 + +#include "plugin.h" +#include "account.h" +#include "user.h" +#include "channel.h" + +const char *user__get_colour(struct t_user *user) +{ + return weechat_info_get("nick_color", user->profile.display_name); +} + +const char *user__get_colour_for_nicklist(struct t_user *user) +{ + return weechat_info_get("nick_color_name", user->profile.display_name); +} + +const char *user__as_prefix(struct t_account *account, + struct t_user *user, + const char *name) +{ + static char result[256]; + + (void) account; + + snprintf(result, sizeof(result), "%s%s\t", + user__get_colour(user), + name ? name : user->profile.display_name); + + return result; +} + +struct t_user *user__bot_search(struct t_account *account, + const char *bot_id) +{ + struct t_user *ptr_user; + + if (!account || !bot_id) + return NULL; + + for (ptr_user = account->users; ptr_user; + ptr_user = ptr_user->next_user) + { + if (ptr_user->profile.bot_id && + weechat_strcasecmp(ptr_user->profile.bot_id, bot_id) == 0) + return ptr_user; + } + + return NULL; +} + +struct t_user *user__search(struct t_account *account, + const char *id) +{ + struct t_user *ptr_user; + + if (!account || !id) + return NULL; + + for (ptr_user = account->users; ptr_user; + ptr_user = ptr_user->next_user) + { + if (weechat_strcasecmp(ptr_user->id, id) == 0) + return ptr_user; + } + + return NULL; +} + +void user__nicklist_add(struct t_account *account, + struct t_channel *channel, + struct t_user *user) +{ + struct t_gui_nick_group *ptr_group; + struct t_gui_buffer *ptr_buffer; + + ptr_buffer = channel ? channel->buffer : account->buffer; + + ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, + user->is_away ? + "+" : "..."); + weechat_nicklist_add_nick(ptr_buffer, ptr_group, + user->profile.display_name, + user->is_away ? + "weechat.color.nicklist_away" : + user__get_colour_for_nicklist(user), + user->is_away ? "+" : "", + "bar_fg", + 1); +} + +struct t_user *user__new(struct t_account *account, + const char *id, const char *display_name) +{ + struct t_user *new_user, *ptr_user; + + if (!account || !id || !display_name) + { + return NULL; + } + + if (!display_name[0] && strcmp("USLACKBOT", id) == 0) + return NULL; + + if (!account->users) + channel__add_nicklist_groups(account, NULL); + + ptr_user = user__search(account, id); + if (ptr_user) + { + user__nicklist_add(account, NULL, ptr_user); + return ptr_user; + } + + if ((new_user = malloc(sizeof(*new_user))) == NULL) + { + return NULL; + } + + new_user->prev_user = account->last_user; + new_user->next_user = NULL; + if (account->last_user) + (account->last_user)->next_user = new_user; + else + account->users = new_user; + account->last_user = new_user; + + new_user->id = strdup(id); + new_user->name = NULL; + new_user->team_id = NULL; + new_user->real_name = NULL; + new_user->colour = NULL; + new_user->deleted = 0; + + new_user->tz = NULL; + new_user->tz_label = NULL; + new_user->tz_offset = 0; + new_user->locale = NULL; + + new_user->profile.avatar_hash = NULL; + new_user->profile.status_text = NULL; + new_user->profile.status_emoji = NULL; + new_user->profile.real_name = NULL; + new_user->profile.display_name = display_name[0] ? + strdup(display_name) : + strdup("xmppbot"); + new_user->profile.real_name_normalized = NULL; + new_user->profile.email = NULL; + new_user->profile.team = NULL; + new_user->profile.bot_id = NULL; + new_user->updated = 0; + new_user->is_away = 0; + + new_user->is_admin = 0; + new_user->is_owner = 0; + new_user->is_primary_owner = 0; + new_user->is_restricted = 0; + new_user->is_ultra_restricted = 0; + new_user->is_bot = 0; + new_user->is_stranger = 0; + new_user->is_app_user = 0; + new_user->has_2fa = 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->team_id) + free(user->team_id); + if (user->real_name) + free(user->real_name); + if (user->colour) + free(user->colour); + if (user->tz) + free(user->tz); + if (user->tz_label) + free(user->tz_label); + if (user->locale) + free(user->locale); + if (user->profile.avatar_hash) + free(user->profile.avatar_hash); + if (user->profile.status_text) + free(user->profile.status_text); + if (user->profile.status_emoji) + free(user->profile.status_emoji); + if (user->profile.real_name) + free(user->profile.real_name); + if (user->profile.display_name) + free(user->profile.display_name); + if (user->profile.real_name_normalized) + free(user->profile.real_name_normalized); + if (user->profile.email) + free(user->profile.email); + if (user->profile.team) + free(user->profile.team); + + free(user); + + account->users = new_users; +} + +void user__free_all(struct t_account *account) +{ + while (account->users) + user__free(account, account->users); +} diff --git a/user.h b/user.h new file mode 100644 index 0000000..88aaf96 --- /dev/null +++ b/user.h @@ -0,0 +1,75 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_USER_H_ +#define _WEECHAT_XMPP_USER_H_ + +struct t_user_profile +{ + char *avatar_hash; + char *status_text; + char *status_emoji; + char *real_name; + char *display_name; + char *real_name_normalized; + char *email; + char *team; + char *bot_id; +}; + +struct t_user +{ + char *id; + char *name; + char *team_id; + char *real_name; + char *colour; + + int deleted; + char *tz; + char *tz_label; + int tz_offset; + char *locale; + + struct t_user_profile profile; + int updated; + int is_away; + + int is_admin; + int is_owner; + int is_primary_owner; + int is_restricted; + int is_ultra_restricted; + int is_bot; + int is_stranger; + int is_app_user; + int has_2fa; + + struct t_user *prev_user; + struct t_user *next_user; +}; +struct t_channel; + +const char *user__get_colour(struct t_user *user); + +const char *user__as_prefix(struct t_account *account, + struct t_user *user, + const char *name); + +struct t_user *user__bot_search(struct t_account *account, + const char *bot_id); + +struct t_user *user__search(struct t_account *account, + const char *id); + +struct t_user *user__new(struct t_account *account, + const char *id, const char *display_name); + +void user__free_all(struct t_account *account); + +void user__nicklist_add(struct t_account *account, + struct t_channel *channel, + struct t_user *user); + +#endif /*WEECHAT_XMPP_USER_H*/ From 020c61af845fbd3eea93143f83ac50587f9d33b2 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 30 Jun 2021 09:54:59 +0100 Subject: [PATCH 077/118] channels for pm --- account.c | 39 +++++----------- account.h | 4 +- channel.c | 112 +++++++++++++++------------------------------- channel.h | 83 ++++++++++++----------------------- command.c | 23 +++++----- config.c | 26 ++++++++++- connection.c | 122 +++++++++++++++++++-------------------------------- connection.h | 8 +--- plugin.c | 3 -- 9 files changed, 158 insertions(+), 262 deletions(-) diff --git a/account.c b/account.c index e70c2cc..e490634 100644 --- a/account.c +++ b/account.c @@ -28,6 +28,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "password", "" }, { "tls", "normal" }, { "nickname", "" }, + { "autoconnect", "" }, }; struct t_account *account__search(const char *name) @@ -83,8 +84,8 @@ int account__search_option(const char *option_name) return -1; } -void log_emit_weechat(void *const userdata, const xmpp_log_level_t level, - const char *const area, const char *const msg) +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; @@ -131,18 +132,13 @@ struct t_account *account__alloc(const char *name) /* set name */ new_account->name = strdup(name); - /* set properties */ - new_account->jid = NULL; - new_account->password = NULL; - new_account->tls = 1; - /* internal vars */ new_account->reloading_from_config = 0; new_account->is_connected = 0; new_account->disconnected = 0; - new_account->logger.handler = &log_emit_weechat; + new_account->logger.handler = &account__log_emit_weechat; new_account->logger.userdata = new_account; new_account->context = xmpp_ctx_new(NULL, &new_account->logger); new_account->connection = NULL; @@ -236,19 +232,12 @@ void account__free_data(struct t_account *account) if (account->name) free(account->name); - if (account->jid) - free(account->jid); - if (account->password) - free(account->password); - - if (account->nickname) - free(account->nickname); if (account->buffer_as_string) free(account->buffer_as_string); - channel__free_all(account); - user__free_all(account); + //channel__free_all(account); + //user__free_all(account); } void account__free(struct t_account *account) @@ -459,19 +448,11 @@ int account__connect(struct t_account *account) account__close_connection(account); - account->jid = !account->options[ACCOUNT_OPTION_JID] ? NULL : - weechat_config_string(account->options[ACCOUNT_OPTION_JID]); - account->password = !account->options[ACCOUNT_OPTION_PASSWORD] ? NULL : - weechat_config_string(account->options[ACCOUNT_OPTION_PASSWORD]); - account->tls = !account->options[ACCOUNT_OPTION_TLS] ? NULL : - weechat_config_integer(account->options[ACCOUNT_OPTION_TLS]); - account->nickname = !account->options[ACCOUNT_OPTION_NICKNAME] ? NULL : - weechat_config_string(account->options[ACCOUNT_OPTION_NICKNAME]); - account->is_connected = - connection__connect(account->context, &account->connection, - &account->logger, account->jid, - account->password, account->tls); + connection__connect(account, &account->connection, + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + weechat_config_string(account->options[ACCOUNT_OPTION_PASSWORD]), + weechat_config_string(account->options[ACCOUNT_OPTION_TLS])); return account->is_connected; } diff --git a/account.h b/account.h index c963bde..4720016 100644 --- a/account.h +++ b/account.h @@ -14,15 +14,13 @@ enum t_account_option ACCOUNT_OPTION_PASSWORD, ACCOUNT_OPTION_TLS, ACCOUNT_OPTION_NICKNAME, + ACCOUNT_OPTION_AUTOCONNECT, ACCOUNT_NUM_OPTIONS, }; struct t_account { const char *name; - const char *jid; - const char *password; - int tls; struct t_config_option *options[ACCOUNT_NUM_OPTIONS]; int reloading_from_config; diff --git a/channel.c b/channel.c index a2dd60c..546ec9c 100644 --- a/channel.c +++ b/channel.c @@ -17,7 +17,7 @@ #include "buffer.h" struct t_channel *channel__search(struct t_account *account, - const char *id) + const char *id) { struct t_channel *ptr_channel; @@ -35,8 +35,8 @@ struct t_channel *channel__search(struct t_account *account, } struct t_gui_buffer *channel__search_buffer(struct t_account *account, - enum t_channel_type type, - const char *name) + enum t_channel_type type, + const char *name) { struct t_hdata *hdata_buffer; struct t_gui_buffer *ptr_buffer; @@ -57,11 +57,9 @@ 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_channel_name && ptr_channel_name[0] - && ( (( (type == CHANNEL_TYPE_CHANNEL) - || (type == CHANNEL_TYPE_GROUP)) + && ( (( (type == CHANNEL_TYPE_MUC)) && (strcmp(ptr_type, "channel") == 0)) - || (( (type == CHANNEL_TYPE_MPIM) - || (type == CHANNEL_TYPE_IM)) + || (( (type == CHANNEL_TYPE_PM)) && (strcmp(ptr_type, "private") == 0))) && (strcmp(ptr_account_name, account->name) == 0) && (weechat_strcasecmp(ptr_channel_name, name) == 0)) @@ -76,8 +74,8 @@ struct t_gui_buffer *channel__search_buffer(struct t_account *account, } struct t_gui_buffer *channel__create_buffer(struct t_account *account, - enum t_channel_type type, - const char *name) + enum t_channel_type type, + const char *name) { struct t_gui_buffer *ptr_buffer; int buffer_created; @@ -125,8 +123,7 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, weechat_buffer_set(ptr_buffer, "name", buffer_name); weechat_buffer_set(ptr_buffer, "localvar_set_type", - (type == CHANNEL_TYPE_IM || - type == CHANNEL_TYPE_MPIM) ? "private" : "channel"); + (type == CHANNEL_TYPE_PM) ? "private" : "channel"); weechat_buffer_set(ptr_buffer, "localvar_set_nick", account->nickname); weechat_buffer_set(ptr_buffer, "localvar_set_server", account->name); weechat_buffer_set(ptr_buffer, "localvar_set_channel", name); @@ -137,7 +134,7 @@ 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_IM) + if (type != CHANNEL_TYPE_PM) { weechat_buffer_set(ptr_buffer, "nicklist", "1"); weechat_buffer_set(ptr_buffer, "nicklist_display_groups", "0"); @@ -157,14 +154,12 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, } void channel__add_nicklist_groups(struct t_account *account, - struct t_channel *channel) + struct t_channel *channel) { struct t_gui_buffer *ptr_buffer; char str_group[32]; - if (channel && channel->type == CHANNEL_TYPE_MPIM) - return; - if (channel && channel->type == CHANNEL_TYPE_IM) + if (channel && channel->type == CHANNEL_TYPE_PM) return; ptr_buffer = channel ? channel->buffer : account->buffer; @@ -180,13 +175,13 @@ void channel__add_nicklist_groups(struct t_account *account, } struct t_channel *channel__new(struct t_account *account, - enum t_channel_type type, - const char *id, const char *name) + enum t_channel_type type, + const char *id, const char *name) { struct t_channel *new_channel, *ptr_channel; struct t_gui_buffer *ptr_buffer; struct t_hook *typing_timer; - char buffer_name[CHANNEL_NAME_MAX_LEN + 2]; + char buffer_name[128]; if (!account || !id || !name || !name[0]) return NULL; @@ -198,7 +193,7 @@ struct t_channel *channel__new(struct t_account *account, } buffer_name[0] = '#'; - strncpy(&buffer_name[1], name, CHANNEL_NAME_MAX_LEN + 1); + strncpy(&buffer_name[1], name, sizeof(buffer_name)); ptr_buffer = channel__create_buffer(account, type, buffer_name); if (!ptr_buffer) @@ -214,29 +209,16 @@ struct t_channel *channel__new(struct t_account *account, new_channel->type = type; new_channel->id = strdup(id); new_channel->name = strdup(name); - new_channel->created = 0; - - new_channel->is_general = 0; - new_channel->name_normalized = NULL; - new_channel->is_shared = 0; - new_channel->is_org_shared = 0; - new_channel->is_member = 0; new_channel->topic.value = NULL; new_channel->topic.creator = NULL; new_channel->topic.last_set = 0; - new_channel->purpose.value = NULL; - new_channel->purpose.creator = NULL; - new_channel->purpose.last_set = 0; - new_channel->is_archived = 0; new_channel->creator = NULL; new_channel->last_read = 0.0; new_channel->unread_count = 0; new_channel->unread_count_display = 0; - new_channel->is_user_deleted = 0; - new_channel->typing_hook_timer = typing_timer; new_channel->members_speaking[0] = NULL; new_channel->members_speaking[1] = NULL; @@ -259,8 +241,8 @@ struct t_channel *channel__new(struct t_account *account, } void channel__member_speaking_add_to_list(struct t_channel *channel, - const char *nick, - int highlight) + const char *nick, + int highlight) { int size, to_remove, i; struct t_weelist_item *ptr_item; @@ -293,7 +275,7 @@ void channel__member_speaking_add_to_list(struct t_channel *channel, } void channel__member_speaking_add(struct t_channel *channel, - const char *nick, int highlight) + const char *nick, int highlight) { if (highlight < 0) highlight = 0; @@ -306,8 +288,8 @@ void channel__member_speaking_add(struct t_channel *channel, } void channel__member_speaking_rename(struct t_channel *channel, - const char *old_nick, - const char *new_nick) + const char *old_nick, + const char *new_nick) { struct t_weelist_item *ptr_item; int i; @@ -324,8 +306,8 @@ void channel__member_speaking_rename(struct t_channel *channel, } void channel__member_speaking_rename_if_present(struct t_account *account, - struct t_channel *channel, - const char *nick) + struct t_channel *channel, + const char *nick) { struct t_weelist_item *ptr_item; int i, j, list_size; @@ -348,7 +330,7 @@ void channel__member_speaking_rename_if_present(struct t_account *account, } void channel__typing_free(struct t_channel *channel, - struct t_channel_typing *typing) + struct t_channel_typing *typing) { struct t_channel_typing *new_typings; @@ -387,8 +369,8 @@ void channel__typing_free_all(struct t_channel *channel) } int channel__typing_cb(const void *pointer, - void *data, - int remaining_calls) + void *data, + int remaining_calls) { struct t_channel_typing *ptr_typing, *next_typing; struct t_channel *channel; @@ -437,9 +419,8 @@ int channel__typing_cb(const void *pointer, return WEECHAT_RC_OK; } -struct t_channel_typing *channel__typing_search( - struct t_channel *channel, - const char *id) +struct t_channel_typing *channel__typing_search(struct t_channel *channel, + const char *id) { struct t_channel_typing *ptr_typing; @@ -457,7 +438,7 @@ struct t_channel_typing *channel__typing_search( } void channel__add_typing(struct t_channel *channel, - struct t_user *user) + struct t_user *user) { struct t_channel_typing *new_typing; @@ -482,7 +463,7 @@ void channel__add_typing(struct t_channel *channel, } void channel__member_free(struct t_channel *channel, - struct t_channel_member *member) + struct t_channel_member *member) { struct t_channel_member *new_members; @@ -519,7 +500,7 @@ void channel__member_free_all(struct t_channel *channel) } void channel__free(struct t_account *account, - struct t_channel *channel) + struct t_channel *channel) { struct t_channel *new_channels; @@ -553,16 +534,10 @@ void channel__free(struct t_account *account, free(channel->id); if (channel->name) free(channel->name); - if (channel->name_normalized) - free(channel->name_normalized); if (channel->topic.value) free(channel->topic.value); if (channel->topic.creator) free(channel->topic.creator); - if (channel->purpose.value) - free(channel->purpose.value); - if (channel->purpose.creator) - free(channel->purpose.creator); if (channel->creator) free(channel->creator); if (channel->members_speaking[0]) @@ -584,9 +559,9 @@ void channel__free_all(struct t_account *account) } void channel__update_topic(struct t_channel *channel, - const char* topic, - const char* creator, - int last_set) + const char* topic, + const char* creator, + int last_set) { if (channel->topic.value) free(channel->topic.value); @@ -602,24 +577,9 @@ void channel__update_topic(struct t_channel *channel, weechat_buffer_set(channel->buffer, "title", ""); } -void channel__update_purpose(struct t_channel *channel, - const char* purpose, - const char* creator, - int last_set) -{ - if (channel->purpose.value) - free(channel->purpose.value); - if (channel->purpose.creator) - free(channel->purpose.creator); - channel->purpose.value = (purpose) ? strdup(purpose) : NULL; - channel->purpose.creator = (creator) ? strdup(creator) : NULL; - channel->purpose.last_set = last_set; -} - -struct t_channel_member *channel__add_member( - struct t_account *account, - struct t_channel *channel, - const char *id) +struct t_channel_member *channel__add_member(struct t_account *account, + struct t_channel *channel, + const char *id) { struct t_channel_member *member; struct t_user *user; diff --git a/channel.h b/channel.h index 5b79c79..3498c47 100644 --- a/channel.h +++ b/channel.h @@ -7,14 +7,10 @@ #define CHANNEL_MEMBERS_SPEAKING_LIMIT 128 -#define CHANNEL_NAME_MAX_LEN 22 - enum t_channel_type { - CHANNEL_TYPE_CHANNEL, - CHANNEL_TYPE_GROUP, - CHANNEL_TYPE_MPIM, - CHANNEL_TYPE_IM, + CHANNEL_TYPE_MUC, + CHANNEL_TYPE_PM, }; struct t_channel_typing @@ -42,31 +38,13 @@ struct t_channel_topic time_t last_set; }; -struct t_channel_purpose -{ - char *value; - char *creator; - time_t last_set; -}; - struct t_channel { - enum t_channel_type type; + enum t_channel_type type; char *id; char *name; - time_t created; - - /* channel */ - int is_general; - char *name_normalized; - int is_shared; - int is_org_shared; - int is_member; - /* group */ struct t_channel_topic topic; - struct t_channel_purpose purpose; - int is_archived; /* mpim */ char *creator; @@ -74,9 +52,6 @@ struct t_channel int unread_count; int unread_count_display; - /* im */ - int is_user_deleted; - struct t_hook *typing_hook_timer; struct t_weelist *members_speaking[2]; struct t_channel_typing *typings; @@ -91,57 +66,55 @@ struct t_channel }; struct t_channel *channel__search(struct t_account *account, - const char *id); + const char *id); void channel__add_nicklist_groups(struct t_account *account, - struct t_channel *channel); + struct t_channel *channel); struct t_channel *channel__new(struct t_account *account, - enum t_channel_type type, - const char *id, const char *name); + 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); + const char *nick, int highlight); void channel__member_speaking_rename(struct t_channel *channel, - const char *old_nick, - const char *new_nick); + 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); + struct t_channel *channel, + const char *nick); void channel__typing_free(struct t_channel *channel, - struct t_channel_typing *typing); + 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); + void *data, + int remaining_calls); -struct t_channel_typing *channel__typing_search( - struct t_channel *channel, - const char *id); +struct t_channel_typing *channel__typing_search(struct t_channel *channel, + const char *id); void channel__add_typing(struct t_channel *channel, - struct t_user *user); + struct t_user *user); 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); + const char* title, + const char* creator, + int last_set); 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* 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); #endif /*WEECHAT_XMPP_CHANNEL_H*/ diff --git a/command.c b/command.c index fe39db0..6ed8acd 100644 --- a/command.c +++ b/command.c @@ -33,7 +33,7 @@ void command__display_account(struct t_account *account) weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - (account->jid) ? account->jid : "???", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), weechat_color("chat_delimiters"), weechat_color("reset"), (account->is_connected) ? _("connected") : _("not connected"), @@ -53,7 +53,7 @@ void command__display_account(struct t_account *account) weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - (account->jid) ? account->jid : "???", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), weechat_color("chat_delimiters"), weechat_color("reset")); } @@ -138,17 +138,14 @@ void command__add_account(const char *name, const char *jid, const char *passwor account->name = strdup(name); if (jid) - account->jid = strdup(jid); + weechat_config_option_set(account->options[ACCOUNT_OPTION_JID], + strdup(jid), 1); if (password) - account->password = strdup(password); - weechat_config_option_set(account->options[ACCOUNT_OPTION_JID], - account->jid, 1); - weechat_config_option_set(account->options[ACCOUNT_OPTION_PASSWORD], - account->password, 1); - weechat_config_option_set(account->options[ACCOUNT_OPTION_NICKNAME], - account->jid ? xmpp_jid_node(account->context, - account->jid) - : NULL, 1); + weechat_config_option_set(account->options[ACCOUNT_OPTION_PASSWORD], + strdup(password), 1); + if (jid) + weechat_config_option_set(account->options[ACCOUNT_OPTION_NICKNAME], + strdup(xmpp_jid_node(account->context, jid)), 1); weechat_printf ( NULL, @@ -159,7 +156,7 @@ void command__add_account(const char *name, const char *jid, const char *passwor weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - account->jid ? account->jid : "???", + jid ? jid : "???", weechat_color("chat_delimiters"), weechat_color("reset")); } diff --git a/config.c b/config.c index dcc1c2c..b2cf31f 100644 --- a/config.c +++ b/config.c @@ -126,7 +126,23 @@ config__account_new_option (struct t_config_file *config_file, new_option = weechat_config_new_option ( config_file, section, option_name, "string", - N_("XMPP Server JID"), + 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, @@ -216,6 +232,14 @@ int config__account_read_cb (const void *pointer, void *data, 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 { diff --git a/connection.c b/connection.c index 0f0b93e..07e919b 100644 --- a/connection.c +++ b/connection.c @@ -9,13 +9,9 @@ #include "plugin.h" #include "config.h" +#include "account.h" +#include "channel.h" #include "connection.h" -//#include "api/xmpp-api-hello.h" -//#include "api/xmpp-api-error.h" -//#include "api/xmpp-api-message.h" -//#include "api/xmpp-api-user-typing.h" - -xmpp_conn_t *connection; void connection__init() { @@ -26,37 +22,39 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { xmpp_stanza_t *reply, *query, *name, *version, *text; const char *ns; - xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + struct t_account *account = (struct t_account *)userdata; + const char *weechat_name = "weechat"; + const char *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"); - query = xmpp_stanza_new(ctx); + 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); } - name = xmpp_stanza_new(ctx); + 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(ctx); - xmpp_stanza_set_text(text, "libstrophe example bot"); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, weechat_name); xmpp_stanza_add_child(name, text); xmpp_stanza_release(text); - version = xmpp_stanza_new(ctx); + version = xmpp_stanza_new(account->context); xmpp_stanza_set_name(version, "version"); - xmpp_stanza_add_child(query, version); + xmpp_stanza_add_child(query, weechat_version); xmpp_stanza_release(version); - text = xmpp_stanza_new(ctx); - xmpp_stanza_set_text(text, "1.0"); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, version); xmpp_stanza_add_child(version, text); xmpp_stanza_release(text); @@ -65,14 +63,17 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_send(conn, reply); xmpp_stanza_release(reply); + if (version) + free (version); + return 1; } int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { - xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + struct t_account *account = (struct t_account *)userdata; xmpp_stanza_t *body, *reply; - const char *type; + const char *type, *from, *from_jid; char *intext, *replytext; int quit = 0; @@ -82,68 +83,68 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) type = xmpp_stanza_get_type(stanza); if (type != NULL && strcmp(type, "error") == 0) return 1; + from = xmpp_stanza_get_from(stanza); + from_jid = xmpp_jid_bare(account->context, from); intext = xmpp_stanza_get_text(body); - weechat_printf(NULL, "Incoming message from %s: %s", xmpp_stanza_get_from(stanza), - intext); + struct t_channel *channel = channel__search(account, from_jid); + if (!channel) + channel = channel__new(account, CHANNEL_TYPE_PM, from_jid, from_jid); + + weechat_printf(channel->buffer, "%s: %s", from_jid, intext); reply = xmpp_stanza_reply(stanza); if (xmpp_stanza_get_type(reply) == NULL) xmpp_stanza_set_type(reply, "chat"); - if (strcmp(intext, "quit") == 0) { - replytext = strdup("bye!"); - quit = 1; - } else { - replytext = (char *)malloc(strlen(" to you too!") + strlen(intext) + 1); - strcpy(replytext, intext); - strcat(replytext, " to you too!"); - } - xmpp_free(ctx, intext); + replytext = (char *)malloc(strlen(" received!") + strlen(intext) + 1); + strcpy(replytext, intext); + strcat(replytext, " received!"); + + xmpp_free(account->context, intext); xmpp_message_set_body(reply, replytext); xmpp_send(conn, reply); xmpp_stanza_release(reply); + weechat_printf(channel->buffer, "%s: %s", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + replytext); free(replytext); - if (quit) - xmpp_disconnect(conn); - return 1; } void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, - int error, xmpp_stream_error_t *stream_error, - void *userdata) + int error, xmpp_stream_error_t *stream_error, + void *userdata) { - xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + struct t_account *account = (struct t_account *)userdata; (void)error; (void)stream_error; if (status == XMPP_CONN_CONNECT) { xmpp_stanza_t *pres; - weechat_printf(NULL, "DEBUG: connected"); + weechat_printf(account->buffer, "DEBUG: connected"); xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, - ctx); - xmpp_handler_add(conn, message_handler, NULL, "message", NULL, ctx); + account); + xmpp_handler_add(conn, message_handler, NULL, "message", NULL, account); /* Send initial so that we appear online to contacts */ - pres = xmpp_presence_new(ctx); + pres = xmpp_presence_new(account->context); xmpp_send(conn, pres); xmpp_stanza_release(pres); } else { - weechat_printf(NULL, "DEBUG: disconnected"); - xmpp_stop(ctx); + weechat_printf(account->buffer, "DEBUG: disconnected"); + //xmpp_stop(account->context); } } -int connection__connect(xmpp_ctx_t *context, xmpp_conn_t **connection, - xmpp_log_t *logger, const char* jid, - const char* password, int tls) +int connection__connect(struct t_account *account, xmpp_conn_t **connection, + const char* jid, const char* password, int tls) { - *connection = xmpp_conn_new(context); + *connection = xmpp_conn_new(account->context); xmpp_conn_set_jid(*connection, jid); xmpp_conn_set_pass(*connection, password); @@ -163,7 +164,7 @@ int connection__connect(xmpp_ctx_t *context, xmpp_conn_t **connection, } xmpp_conn_set_flags(*connection, flags); - if (xmpp_connect_client(*connection, NULL, 0, &connection__handler, context) + if (xmpp_connect_client(*connection, NULL, 0, &connection__handler, account) != XMPP_EOK) { weechat_printf( @@ -174,11 +175,6 @@ int connection__connect(xmpp_ctx_t *context, xmpp_conn_t **connection, return 0; } - weechat_printf( - NULL, - _("%s%s: c'necting to %s"), - weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, - jid); return 1; } @@ -191,29 +187,3 @@ void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, timeout); } } - -int connection__route_message(xmpp_conn_t *workspace, - const char *type, void *message) -{ - //struct stringcase key; - //key.string = type; - - //size_t case_count = sizeof(cases) / sizeof(cases[0]); - //void *entry_ptr = bsearch(&key, cases, case_count, - // sizeof(struct stringcase), stringcase_cmp); - - //if (entry_ptr) - //{ - // struct stringcase *entry = (struct stringcase *)entry_ptr; - // return (*entry->func)(workspace, message); - //} - //else - //{ - // weechat_printf( - // workspace->buffer, - // _("%s%s: got unhandled message of type: %s"), - // weechat_prefix("error"), XMPP_PLUGIN_NAME, - // type); - return 1; - //} -} diff --git a/connection.h b/connection.h index 1b049ea..54eb1dc 100644 --- a/connection.h +++ b/connection.h @@ -7,14 +7,10 @@ void connection__init(); -int connection__connect(xmpp_ctx_t *context, xmpp_conn_t **connection, - xmpp_log_t *logger, const char* jid, - const char* password, int tls); +int connection__connect(struct t_account *account, xmpp_conn_t **connection, + const char* jid, const char* password, int tls); void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, const unsigned long timeout); -int connection__route_message(xmpp_conn_t *connection, - const char *type, void *message); - #endif /*WEECHAT_XMPP_CONNECTION_H*/ diff --git a/plugin.c b/plugin.c index fc0c9f2..02fa0a5 100644 --- a/plugin.c +++ b/plugin.c @@ -26,7 +26,6 @@ WEECHAT_PLUGIN_PRIORITY(5500); struct t_weechat_plugin *weechat_xmpp_plugin = NULL; -struct t_hook *weechat_xmpp_autoconnect_timer = NULL; struct t_hook *weechat_xmpp_process_timer = NULL; struct t_gui_bar_item *weechat_xmpp_typing_bar_item = NULL; @@ -76,8 +75,6 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) if (weechat_xmpp_typing_bar_item) weechat_bar_item_remove(weechat_xmpp_typing_bar_item); - if (weechat_xmpp_autoconnect_timer) - weechat_unhook(weechat_xmpp_autoconnect_timer); if (weechat_xmpp_process_timer) weechat_unhook(weechat_xmpp_process_timer); From fe5caf0594ccbc569b2cd375e2a3e2796cc9f61d Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 30 Jun 2021 21:39:08 +0100 Subject: [PATCH 078/118] formatted stanza logs --- Makefile | 4 ++-- account.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++------- channel.c | 6 +----- 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 657cd60..1f137d2 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,10 @@ ifdef DEBUG endif RM=rm -f FIND=find -INCLUDES=-Ilibstrophe +INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) -LDLIBS=-lstrophe -lpthread +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib diff --git a/account.c b/account.c index e490634..9b20bcc 100644 --- a/account.c +++ b/account.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "plugin.h" @@ -14,8 +15,6 @@ #include "input.h" #include "account.h" #include "connection.h" -//#include "xmpp-api.h" -//#include "xmpp-request.h" #include "user.h" #include "channel.h" #include "buffer.h" @@ -94,11 +93,60 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve time_t date = time(NULL); const char *timestamp = weechat_util_get_time_string(&date); - weechat_printf( - account ? account->buffer : NULL, - _("%s%s (%s): %s"), - weechat_prefix("error"), area, - log_level_name[level], msg); + char *xml; + if ((level == XMPP_LEVEL_DEBUG) && ((xml = strchr(msg, '<')) != NULL)) + { + FILE *nullfd = fopen("/dev/null", "w+"); + xmlGenericErrorContext = nullfd; + + const char *header = strndup(msg, xml - msg); + xmlDocPtr *doc = xmlRecoverMemory(xml, strlen(xml)); + if (doc == NULL) { + weechat_printf( + account ? account->buffer : NULL, + "xml: Error parsing the xml document"); + fclose(nullfd); + return; + } + xmlChar *buf = malloc(strlen(xml) * 2); + if (buf == NULL) { + weechat_printf( + account ? account->buffer : NULL, + "xml: Error allocating the xml buffer"); + fclose(nullfd); + return; + } + int size = -1; + xmlDocDumpFormatMemory(doc, &buf, &size, 1); + if (size <= 0) { + weechat_printf( + account ? account->buffer : NULL, + "xml: Error formatting the xml document"); + fclose(nullfd); + return; + } + const char **lines = weechat_string_split(buf, "\r\n", NULL, + 0, 0, &size); + weechat_printf( + account ? account->buffer : NULL, + _("%s%s (%s): %s"), + weechat_prefix("error"), area, + log_level_name[level], header); + for (int i = 1; i < size; i++) + weechat_printf( + account ? account->buffer : NULL, + _("%s"), lines[i]); + + fclose(nullfd); + } + else + { + weechat_printf( + account ? account->buffer : NULL, + _("%s%s (%s): %s"), + weechat_prefix("error"), area, + log_level_name[level], msg); + } } struct t_account *account__alloc(const char *name) diff --git a/channel.c b/channel.c index 546ec9c..04c277f 100644 --- a/channel.c +++ b/channel.c @@ -181,7 +181,6 @@ struct t_channel *channel__new(struct t_account *account, struct t_channel *new_channel, *ptr_channel; struct t_gui_buffer *ptr_buffer; struct t_hook *typing_timer; - char buffer_name[128]; if (!account || !id || !name || !name[0]) return NULL; @@ -192,10 +191,7 @@ struct t_channel *channel__new(struct t_account *account, return ptr_channel; } - buffer_name[0] = '#'; - strncpy(&buffer_name[1], name, sizeof(buffer_name)); - - ptr_buffer = channel__create_buffer(account, type, buffer_name); + ptr_buffer = channel__create_buffer(account, type, name); if (!ptr_buffer) return NULL; From d5a009f5471203f5643a5998dea02ba6433ddaaf Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 30 Jun 2021 23:31:20 +0100 Subject: [PATCH 079/118] replies in pm at least --- Makefile | 2 +- connection.c | 15 ++++++++------- input.c | 17 ++++++++--------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 1f137d2..9a19fb7 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ xmpp.so: $(OBJS) test: xmpp.so env LD_PRELOAD=$(DEBUG) \ - weechat -a -P buflist -r '/plugin load ./xmpp.so' + weechat -a -P 'buflist,irc' -r '/plugin load ./xmpp.so' debug: xmpp.so gdb -ex "handle SIGPIPE nostop noprint pass" --args \ diff --git a/connection.c b/connection.c index 07e919b..8b0a787 100644 --- a/connection.c +++ b/connection.c @@ -72,8 +72,8 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *body, *reply; - const char *type, *from, *from_jid; + xmpp_stanza_t *body, *reply, *to; + const char *type, *from, *from_bare; char *intext, *replytext; int quit = 0; @@ -84,15 +84,16 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (type != NULL && strcmp(type, "error") == 0) return 1; from = xmpp_stanza_get_from(stanza); - from_jid = xmpp_jid_bare(account->context, from); + from_bare = xmpp_jid_bare(account->context, from); + to = xmpp_stanza_get_to(stanza); intext = xmpp_stanza_get_text(body); - struct t_channel *channel = channel__search(account, from_jid); + struct t_channel *channel = channel__search(account, from_bare); if (!channel) - channel = channel__new(account, CHANNEL_TYPE_PM, from_jid, from_jid); + channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - weechat_printf(channel->buffer, "%s: %s", from_jid, intext); + weechat_printf(channel->buffer, "<-(%s)- %s: %s", to, from, intext); reply = xmpp_stanza_reply(stanza); if (xmpp_stanza_get_type(reply) == NULL) @@ -107,7 +108,7 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_send(conn, reply); xmpp_stanza_release(reply); - weechat_printf(channel->buffer, "%s: %s", + weechat_printf(channel->buffer, "-> %s: %s", weechat_config_string(account->options[ACCOUNT_OPTION_JID]), replytext); free(replytext); diff --git a/input.c b/input.c index 6aebd91..d4ed0a9 100644 --- a/input.c +++ b/input.c @@ -10,7 +10,6 @@ #include "account.h" #include "channel.h" #include "buffer.h" -//#include "request.h" #include "message.h" #include "input.h" @@ -18,7 +17,7 @@ int input__data(struct t_gui_buffer *buffer, const char *text) { struct t_account *account = NULL; struct t_channel *channel = NULL; - struct t_request *request; + struct xmpp_stanza_t *message; buffer__get_account_and_channel(buffer, &account, &channel); @@ -35,13 +34,13 @@ int input__data(struct t_gui_buffer *buffer, const char *text) return WEECHAT_RC_OK; } - //TODO: SEND - //request = request_chat_postmessage(account, - // weechat_config_string( - // account->options[ACCOUNT_OPTION_TOKEN]), - // channel->id, text); - //if (request) - // account__register_request(account, request); + message = xmpp_message_new(account->context, "chat", channel->id, NULL); + xmpp_message_set_body(message, text); + xmpp_send(account->connection, message); + xmpp_stanza_release(message); + weechat_printf(channel->buffer, "-> %s: %s", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + text); } else { From 60db9faf1bffb0ddfae6f4ca258b1706706ed838 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 1 Jul 2021 00:01:56 +0100 Subject: [PATCH 080/118] bump readme --- README.org | 47 +++++++++++++++++++++++++++-------------------- channel.c | 6 ++++++ connection.c | 16 ---------------- plugin.h | 2 +- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/README.org b/README.org index 01cce45..43336ac 100644 --- a/README.org +++ b/README.org @@ -17,24 +17,23 @@ [[https://github.com/bqv/weechat-xmpp/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-xmpp.svg]] [[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-xmpp-blue.svg]] - | Status: | Aaaaaaaaaaaaaaaaa | - | Location: | [[http://github.com/bqv/weechat-xmpp]] | - | Version: | 0.1.0 | - | Disclaimer: | I'm lazy | + | Status: | XMPP for power users and digital masochists | + | Location: | [[http://github.com/bqv/weechat-xmpp]] | + | Version: | 0.1.1 | + | Disclaimer: | I'm lazy and unashamedly clinically insane | * Description A weechat plugin in C to extend the chat client to - support XMPP and ideally a maximal set of XEPs. - + support XMPP and a currently minimal but ideally maximal + set of XEPs. + * Usage - 1. Start with =/xmpp register= for instructions on how - to obtain a token, or if you already have a token, use - =/xmpp register =. + 1. Start with =/xmpp add=, use =/help xmpp= for instructions. - 2. Use =/xmpp connect = with the name - returned by register + 2. Use =/xmpp connect = with the name set at + add-time. * Installing @@ -42,9 +41,9 @@ * Dependencies - - libstrophe (static, submodule) - - json-c (static, submodule) - - weechat (>= v1.7) + - libstrophe (dynamic, dependency) + - libxml2 (dynamic, dependency) + - weechat (>= v2.5) * Building @@ -54,19 +53,19 @@ make make install #+end_src - + Do *NOT* run make install as root, it installs the plugin to your local weechat plugins directory - + * Development - + I use emacs for development of this, although I am also a fan of vim. My debug build process involves static analysis with clang and cppcheck, and dynamic analysis with address-sanitizer and leak-sanitizer. My debug evaluation process involves gdb/mi run with the arguments =-ex "handle SIGPIPE nostop noprint pass" --args weechat -a 2>asan.log= since part of weechat and it's default plugins use SIGPIPE as control. - + I have no real requests for style of pull requests besides a wish that you keep vaguely to the style I have adopted for this project. @@ -74,8 +73,16 @@ * Tasks -** TODO [#A] Implement basic functionality (milestone v0.1) -** TODO [#A] Implement essential events (milestone v0.2) +** DONE [#A] Implement basic functionality (milestone v0.1) + * [x] Connecting + * [x] Pretty-printing stanzas + * [x] Receiveing and formatting PMs to a dedicated buffer + * [x] Responding to PMs and formatting responses +** TODO [#A] Implement essential functionality (milestone v0.2) + * [ ] MUCs + * [ ] OMEMO presence + * [ ] OMEMO messages + * [ ] MUC PMs ** TODO [#B] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) diff --git a/channel.c b/channel.c index 04c277f..c7da101 100644 --- a/channel.c +++ b/channel.c @@ -597,3 +597,9 @@ struct t_channel_member *channel__add_member(struct t_account *account, return member; } + +void channel__send_message(struct t_account *account, struct t_channel *channel, + const char *to, const char *message) +{ + +} diff --git a/connection.c b/connection.c index 8b0a787..39a3111 100644 --- a/connection.c +++ b/connection.c @@ -95,23 +95,7 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) weechat_printf(channel->buffer, "<-(%s)- %s: %s", to, from, intext); - reply = xmpp_stanza_reply(stanza); - if (xmpp_stanza_get_type(reply) == NULL) - xmpp_stanza_set_type(reply, "chat"); - - replytext = (char *)malloc(strlen(" received!") + strlen(intext) + 1); - strcpy(replytext, intext); - strcat(replytext, " received!"); - xmpp_free(account->context, intext); - xmpp_message_set_body(reply, replytext); - - xmpp_send(conn, reply); - xmpp_stanza_release(reply); - weechat_printf(channel->buffer, "-> %s: %s", - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), - replytext); - free(replytext); return 1; } diff --git a/plugin.h b/plugin.h index bc5ff5d..d2a3f07 100644 --- a/plugin.h +++ b/plugin.h @@ -7,7 +7,7 @@ #define weechat_plugin weechat_xmpp_plugin #define WEECHAT_XMPP_PLUGIN_NAME "xmpp" -#define WEECHAT_XMPP_PLUGIN_VERSION "0.1" +#define WEECHAT_XMPP_PLUGIN_VERSION "0.1.1" extern struct t_weechat_plugin *weechat_xmpp_plugin; From b48a796e3d8dc99ffd5f0908c33dd42a319cdc00 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 1 Jul 2021 03:07:18 +0100 Subject: [PATCH 081/118] handle /me --- README.org | 2 ++ buffer.c | 25 ++++++++++++------------- buffer.h | 23 +++++++++++------------ channel.c | 12 +++++++++--- channel.h | 3 +++ command.c | 22 +++++++++++----------- connection.c | 12 ++++++++---- input.c | 9 +-------- 8 files changed, 57 insertions(+), 51 deletions(-) diff --git a/README.org b/README.org index 43336ac..4e9bd15 100644 --- a/README.org +++ b/README.org @@ -83,6 +83,8 @@ * [ ] OMEMO presence * [ ] OMEMO messages * [ ] MUC PMs + * [ ] Send typing notifications + * [ ] Recv typing notifications ** TODO [#B] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) diff --git a/buffer.c b/buffer.c index 48232b3..6e974c9 100644 --- a/buffer.c +++ b/buffer.c @@ -12,8 +12,8 @@ #include "buffer.h" void buffer__get_account_and_channel(struct t_gui_buffer *buffer, - struct t_account **account, - struct t_channel **channel) + struct t_account **account, + struct t_channel **channel) { struct t_account *ptr_account; struct t_channel *ptr_channel; @@ -21,7 +21,7 @@ void buffer__get_account_and_channel(struct t_gui_buffer *buffer, if (!buffer) return; - /* look for a account or channel using this buffer */ + /* look for a account or channel using this buffer */ for (ptr_account = accounts; ptr_account; ptr_account = ptr_account->next_account) { @@ -49,12 +49,11 @@ void buffer__get_account_and_channel(struct t_gui_buffer *buffer, /* no account or channel found */ } -char *buffer__typing_bar_cb(const void *pointer, - void *data, - struct t_gui_bar_item *item, - struct t_gui_window *window, - struct t_gui_buffer *buffer, - struct t_hashtable *extra_info) +char *buffer__typing_bar_cb(const void *pointer, void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info) { struct t_channel_typing *ptr_typing; struct t_account *account; @@ -111,9 +110,9 @@ char *buffer__typing_bar_cb(const void *pointer, } int buffer__nickcmp_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *nick1, - const char *nick2) + struct t_gui_buffer *buffer, + const char *nick1, + const char *nick2) { struct t_account *account; @@ -135,7 +134,7 @@ int buffer__nickcmp_cb(const void *pointer, void *data, } int buffer__close_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer) + struct t_gui_buffer *buffer) { struct t_weechat_plugin *buffer_plugin = NULL; struct t_account *ptr_account = NULL; diff --git a/buffer.h b/buffer.h index b126d9d..c07794c 100644 --- a/buffer.h +++ b/buffer.h @@ -6,22 +6,21 @@ #define _WEECHAT_XMPP_BUFFER_H_ void buffer__get_account_and_channel(struct t_gui_buffer *buffer, - struct t_account **account, - struct t_channel **channel); + struct t_account **account, + struct t_channel **channel); -char *buffer__typing_bar_cb(const void *pointer, - void *data, - struct t_gui_bar_item *item, - struct t_gui_window *window, - struct t_gui_buffer *buffer, - struct t_hashtable *extra_info); +char *buffer__typing_bar_cb(const void *pointer, void *data, + struct t_gui_bar_item *item, + struct t_gui_window *window, + struct t_gui_buffer *buffer, + struct t_hashtable *extra_info); int buffer__nickcmp_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *nick1, - const char *nick2); + struct t_gui_buffer *buffer, + const char *nick1, + const char *nick2); int buffer__close_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer); + struct t_gui_buffer *buffer); #endif /*WEECHAT_XMPP_BUFFER_H*/ diff --git a/channel.c b/channel.c index c7da101..8b3fed8 100644 --- a/channel.c +++ b/channel.c @@ -115,7 +115,7 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, "localvar_channel"); if (!short_name || - (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) + (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) { weechat_buffer_set (ptr_buffer, "short_name", name); } @@ -599,7 +599,13 @@ struct t_channel_member *channel__add_member(struct t_account *account, } void channel__send_message(struct t_account *account, struct t_channel *channel, - const char *to, const char *message) + const char *to, const char *body) { - + struct xmpp_stanza_t *message = xmpp_message_new(account->context, "chat", to, NULL); + xmpp_message_set_body(message, body); + xmpp_send(account->connection, message); + xmpp_stanza_release(message); + weechat_printf(channel->buffer, "%s: %s", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + body); } diff --git a/channel.h b/channel.h index 3498c47..3145fa1 100644 --- a/channel.h +++ b/channel.h @@ -117,4 +117,7 @@ struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel *channel, const char *id); +void channel__send_message(struct t_account *account, struct t_channel *channel, + const char *to, const char *body); + #endif /*WEECHAT_XMPP_CHANNEL_H*/ diff --git a/command.c b/command.c index 6ed8acd..25a75d7 100644 --- a/command.c +++ b/command.c @@ -332,13 +332,12 @@ int command__me(const void *pointer, void *data, char **argv, char **argv_eol) { struct t_account *ptr_account = NULL; - struct t_xmpp_channel *ptr_channel = NULL; - //struct t_xmpp_request *request; + struct t_channel *ptr_channel = NULL; + struct xmpp_stanza_t *message; char *text; (void) pointer; (void) data; - (void) buffer; (void) argv; buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); @@ -365,14 +364,15 @@ int command__me(const void *pointer, void *data, if (argc > 1) { - text = argv_eol[1]; - - //request = xmpp_request_chat_memessage(ptr_account, - // weechat_config_string( - // ptr_account->options[XMPP_ACCOUNT_OPTION_TOKEN]), - // ptr_channel->id, text); - //if (request) - // xmpp_account_register_request(ptr_account, request); + text = argv_eol[0]; + + message = xmpp_message_new(ptr_account->context, "chat", ptr_channel->name, NULL); + xmpp_message_set_body(message, text); + xmpp_send(ptr_account->connection, message); + xmpp_stanza_release(message); + weechat_printf(ptr_channel->buffer, "* %s %s", + weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]), + text); } return WEECHAT_RC_OK; diff --git a/connection.c b/connection.c index 39a3111..c8adde4 100644 --- a/connection.c +++ b/connection.c @@ -75,7 +75,6 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *body, *reply, *to; const char *type, *from, *from_bare; char *intext, *replytext; - int quit = 0; body = xmpp_stanza_get_child_by_name(stanza, "body"); if (body == NULL) @@ -93,7 +92,12 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - weechat_printf(channel->buffer, "<-(%s)- %s: %s", to, from, intext); + if (strcmp(to, channel->id) == 0) + weechat_printf(channel->buffer, "%s [to %s]: %s", from, to, intext); + else if (strncmp(intext, "/me ", 4) == 0) + weechat_printf(channel->buffer, "* %s %s", from, intext+4); + else + weechat_printf(channel->buffer, "%s: %s", from, intext); xmpp_free(account->context, intext); @@ -111,7 +115,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, if (status == XMPP_CONN_CONNECT) { xmpp_stanza_t *pres; - weechat_printf(account->buffer, "DEBUG: connected"); + //weechat_printf(account->buffer, "DEBUG: connected"); xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, account); xmpp_handler_add(conn, message_handler, NULL, "message", NULL, account); @@ -121,7 +125,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, pres); xmpp_stanza_release(pres); } else { - weechat_printf(account->buffer, "DEBUG: disconnected"); + //weechat_printf(account->buffer, "DEBUG: disconnected"); //xmpp_stop(account->context); } } diff --git a/input.c b/input.c index d4ed0a9..e454ede 100644 --- a/input.c +++ b/input.c @@ -17,7 +17,6 @@ int input__data(struct t_gui_buffer *buffer, const char *text) { struct t_account *account = NULL; struct t_channel *channel = NULL; - struct xmpp_stanza_t *message; buffer__get_account_and_channel(buffer, &account, &channel); @@ -34,13 +33,7 @@ int input__data(struct t_gui_buffer *buffer, const char *text) return WEECHAT_RC_OK; } - message = xmpp_message_new(account->context, "chat", channel->id, NULL); - xmpp_message_set_body(message, text); - xmpp_send(account->connection, message); - xmpp_stanza_release(message); - weechat_printf(channel->buffer, "-> %s: %s", - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), - text); + channel__send_message(account, channel, channel->id, text); } else { From f6c67a1a337278b5b1a7238c2e194680e4b65f49 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 1 Jul 2021 21:37:43 +0100 Subject: [PATCH 082/118] merry MUCmas --- Makefile | 2 +- README.org | 20 ++++++-- channel.c | 17 ++++--- command.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ connection.c | 9 ++++ 5 files changed, 174 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 9a19fb7..b452cdd 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ xmpp.so: $(OBJS) test: xmpp.so env LD_PRELOAD=$(DEBUG) \ - weechat -a -P 'buflist,irc' -r '/plugin load ./xmpp.so' + weechat -a -P 'alias,buflist,irc' -r '/plugin load ./xmpp.so' debug: xmpp.so gdb -ex "handle SIGPIPE nostop noprint pass" --args \ diff --git a/README.org b/README.org index 4e9bd15..d93dc88 100644 --- a/README.org +++ b/README.org @@ -74,18 +74,28 @@ * Tasks ** DONE [#A] Implement basic functionality (milestone v0.1) - * [x] Connecting - * [x] Pretty-printing stanzas - * [x] Receiveing and formatting PMs to a dedicated buffer - * [x] Responding to PMs and formatting responses + * [X] Connecting + * [X] Pretty-printing stanzas + * [X] Receiveing and formatting PMs to a dedicated buffer + * [X] Responding to PMs and formatting responses + * [X] Opening PMs (/chat) ** TODO [#A] Implement essential functionality (milestone v0.2) + * [X] Opening PMs with initial message + * [ ] Handle wide errors gracefully * [ ] MUCs + * [X] Opening (/enter) + * [X] Receiving + * [X] Sending + * [ ] [#B] Handle errors gracefully + * [ ] [#B] Presence/nicklist + * [ ] [#B] Show topic + * [ ] [#B] Edits * [ ] OMEMO presence * [ ] OMEMO messages * [ ] MUC PMs * [ ] Send typing notifications * [ ] Recv typing notifications -** TODO [#B] Implement completion engine (milestone v0.3) +** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) * Contributing diff --git a/channel.c b/channel.c index 8b3fed8..09e56b1 100644 --- a/channel.c +++ b/channel.c @@ -117,11 +117,12 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, if (!short_name || (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) { - weechat_buffer_set (ptr_buffer, "short_name", name); + weechat_buffer_set (ptr_buffer, "short_name", xmpp_jid_node(account->context, + name)); } } - weechat_buffer_set(ptr_buffer, "name", buffer_name); + weechat_buffer_set(ptr_buffer, "name", name); weechat_buffer_set(ptr_buffer, "localvar_set_type", (type == CHANNEL_TYPE_PM) ? "private" : "channel"); weechat_buffer_set(ptr_buffer, "localvar_set_nick", account->nickname); @@ -601,11 +602,15 @@ struct t_channel_member *channel__add_member(struct t_account *account, void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body) { - struct xmpp_stanza_t *message = xmpp_message_new(account->context, "chat", to, NULL); + struct xmpp_stanza_t *message = xmpp_message_new(account->context, + channel->type == CHANNEL_TYPE_MUC + ? "groupchat" : "chat", + to, NULL); xmpp_message_set_body(message, body); xmpp_send(account->connection, message); xmpp_stanza_release(message); - weechat_printf(channel->buffer, "%s: %s", - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), - body); + if (channel->type != CHANNEL_TYPE_MUC) + weechat_printf(channel->buffer, "%s: %s", + weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + body); } diff --git a/command.c b/command.c index 25a75d7..a5c5799 100644 --- a/command.c +++ b/command.c @@ -327,6 +327,126 @@ int command__account(const void *pointer, void *data, return WEECHAT_RC_OK; } +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; + struct xmpp_stanza_t *pres; + char *jid, *pres_jid, *text; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + jid = argv[1]; + pres_jid = argv[1]; + + if(!xmpp_jid_resource(ptr_account->context, pres_jid)) + pres_jid = xmpp_jid_new( + ptr_account->context, + xmpp_jid_node(ptr_account->context, jid), + xmpp_jid_domain(ptr_account->context, jid), + weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME]) + && strlen(weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME])) + ? weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME]) + : xmpp_jid_node(ptr_account->context, + weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]))); + + ptr_channel = channel__search(ptr_account, jid); + if (!ptr_channel) + ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, jid, jid); + + pres = xmpp_presence_new(ptr_account->context); + xmpp_stanza_set_to(pres, pres_jid); + xmpp_stanza_set_from(pres, weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID])); + + struct xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); + xmpp_stanza_set_name(pres__x, "x"); + xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); + xmpp_stanza_add_child(pres, pres__x); + + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres__x); + xmpp_stanza_release(pres); + + if (argc > 2) + { + text = argv_eol[2]; + + channel__send_message(ptr_account, ptr_channel, jid, text); + } + } + + return WEECHAT_RC_OK; +} + +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; + struct xmpp_stanza_t *pres; + char *jid, *text; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + jid = argv[1]; + + pres = xmpp_presence_new(ptr_account->context); + xmpp_stanza_set_to(pres, jid); + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres); + + ptr_channel = channel__search(ptr_account, jid); + if (!ptr_channel) + ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_PM, jid, jid); + + if (argc > 2) + { + text = argv_eol[2]; + + channel__send_message(ptr_account, ptr_channel, jid, text); + } + } + + return WEECHAT_RC_OK; +} + int command__me(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) @@ -401,6 +521,24 @@ void command__init() if (!hook) weechat_printf(NULL, "Failed to setup command /account"); + hook = weechat_hook_command( + "enter", + N_("enter an xmpp multi-user-chat (muc)"), + N_(""), + N_("jid: muc to enter"), + NULL, &command__enter, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /enter"); + + hook = weechat_hook_command( + "open", + N_("open a direct xmpp chat"), + N_(""), + N_("jid: jid to target"), + NULL, &command__open, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /chat"); + hook = weechat_hook_command( "me", N_("send a xmpp action to the current channel"), diff --git a/connection.c b/connection.c index c8adde4..49aaf61 100644 --- a/connection.c +++ b/connection.c @@ -92,6 +92,15 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + if (weechat_strcasecmp(type, "groupchat") == 0) + { + from = weechat_strcasecmp(channel->name, + xmpp_jid_bare(account->context, + from)) == 0 + ? xmpp_jid_resource(account->context, from) + : from; + } + if (strcmp(to, channel->id) == 0) weechat_printf(channel->buffer, "%s [to %s]: %s", from, to, intext); else if (strncmp(intext, "/me ", 4) == 0) From 71531be5e6cbc4db8aba7b954daf20665ce7a6d3 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 1 Jul 2021 22:08:50 +0100 Subject: [PATCH 083/118] fix segfault on empty body --- connection.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/connection.c b/connection.c index 49aaf61..70f9457 100644 --- a/connection.c +++ b/connection.c @@ -83,10 +83,14 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (type != NULL && strcmp(type, "error") == 0) return 1; from = xmpp_stanza_get_from(stanza); + if (from == NULL) + return 1; from_bare = xmpp_jid_bare(account->context, from); to = xmpp_stanza_get_to(stanza); intext = xmpp_stanza_get_text(body); + if (intext == NULL) + intext = strdup(""); struct t_channel *channel = channel__search(account, from_bare); if (!channel) @@ -103,7 +107,7 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (strcmp(to, channel->id) == 0) weechat_printf(channel->buffer, "%s [to %s]: %s", from, to, intext); - else if (strncmp(intext, "/me ", 4) == 0) + else if (weechat_string_match(intext, "/me *", 0)) weechat_printf(channel->buffer, "* %s %s", from, intext+4); else weechat_printf(channel->buffer, "%s: %s", from, intext); From 8988d969a04ac273578372bc2ab1b4597935852b Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 1 Jul 2021 23:08:12 +0100 Subject: [PATCH 084/118] hacky colours --- account.c | 4 ++-- channel.c | 6 ++++-- command.c | 9 ++++++--- connection.c | 12 +++++++++--- user.c | 32 +++++++++++++++++++++++--------- user.h | 17 ++++++++++------- 6 files changed, 54 insertions(+), 26 deletions(-) diff --git a/account.c b/account.c index 9b20bcc..c1d52ae 100644 --- a/account.c +++ b/account.c @@ -130,7 +130,7 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve weechat_printf( account ? account->buffer : NULL, _("%s%s (%s): %s"), - weechat_prefix("error"), area, + weechat_prefix("network"), area, log_level_name[level], header); for (int i = 1; i < size; i++) weechat_printf( @@ -144,7 +144,7 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve weechat_printf( account ? account->buffer : NULL, _("%s%s (%s): %s"), - weechat_prefix("error"), area, + weechat_prefix("network"), area, log_level_name[level], msg); } } diff --git a/channel.c b/channel.c index 09e56b1..9e92730 100644 --- a/channel.c +++ b/channel.c @@ -610,7 +610,9 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_send(account->connection, message); xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) - weechat_printf(channel->buffer, "%s: %s", - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + weechat_printf(channel->buffer, "%s%s", + user__as_prefix_raw( + account, + weechat_config_string(account->options[ACCOUNT_OPTION_JID])), body); } diff --git a/command.c b/command.c index a5c5799..6c09ed3 100644 --- a/command.c +++ b/command.c @@ -11,6 +11,7 @@ //#include "oauth.h" //#include "teaminfo.h" #include "account.h" +#include "user.h" #include "channel.h" #include "buffer.h" #include "message.h" @@ -490,9 +491,11 @@ int command__me(const void *pointer, void *data, xmpp_message_set_body(message, text); xmpp_send(ptr_account->connection, message); xmpp_stanza_release(message); - weechat_printf(ptr_channel->buffer, "* %s %s", - weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]), - text); + if (ptr_channel->type != CHANNEL_TYPE_MUC) + weechat_printf(ptr_channel->buffer, "%s%s %s", + weechat_prefix("action"), + weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]), + text); } return WEECHAT_RC_OK; diff --git a/connection.c b/connection.c index 70f9457..c1013d4 100644 --- a/connection.c +++ b/connection.c @@ -10,6 +10,7 @@ #include "plugin.h" #include "config.h" #include "account.h" +#include "user.h" #include "channel.h" #include "connection.h" @@ -106,11 +107,16 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) } if (strcmp(to, channel->id) == 0) - weechat_printf(channel->buffer, "%s [to %s]: %s", from, to, intext); + weechat_printf(channel->buffer, "%s[to %s]: %s", + user__as_prefix_raw(account->context, from), + to, intext); else if (weechat_string_match(intext, "/me *", 0)) - weechat_printf(channel->buffer, "* %s %s", from, intext+4); + weechat_printf(channel->buffer, "%s%s %s", + weechat_prefix("action"), from, intext+4); else - weechat_printf(channel->buffer, "%s: %s", from, intext); + weechat_printf(channel->buffer, "%s%s", + user__as_prefix_raw(account->context, from), + intext); xmpp_free(account->context, intext); diff --git a/user.c b/user.c index 2469af3..4cc62ac 100644 --- a/user.c +++ b/user.c @@ -23,11 +23,25 @@ const char *user__get_colour_for_nicklist(struct t_user *user) return weechat_info_get("nick_color_name", user->profile.display_name); } +const char *user__as_prefix_raw(struct t_account *account, + const char *name) +{ + static char result[2048]; + + (void) account; + + snprintf(result, sizeof(result), "%s%s\t", + weechat_info_get("nick_color", name), + name); + + return result; +} + const char *user__as_prefix(struct t_account *account, - struct t_user *user, - const char *name) + struct t_user *user, + const char *name) { - static char result[256]; + static char result[2048]; (void) account; @@ -39,7 +53,7 @@ const char *user__as_prefix(struct t_account *account, } struct t_user *user__bot_search(struct t_account *account, - const char *bot_id) + const char *bot_id) { struct t_user *ptr_user; @@ -58,7 +72,7 @@ struct t_user *user__bot_search(struct t_account *account, } struct t_user *user__search(struct t_account *account, - const char *id) + const char *id) { struct t_user *ptr_user; @@ -76,8 +90,8 @@ struct t_user *user__search(struct t_account *account, } void user__nicklist_add(struct t_account *account, - struct t_channel *channel, - struct t_user *user) + struct t_channel *channel, + struct t_user *user) { struct t_gui_nick_group *ptr_group; struct t_gui_buffer *ptr_buffer; @@ -89,7 +103,7 @@ void user__nicklist_add(struct t_account *account, "+" : "..."); weechat_nicklist_add_nick(ptr_buffer, ptr_group, user->profile.display_name, - user->is_away ? + user->is_away ? "weechat.color.nicklist_away" : user__get_colour_for_nicklist(user), user->is_away ? "+" : "", @@ -98,7 +112,7 @@ void user__nicklist_add(struct t_account *account, } struct t_user *user__new(struct t_account *account, - const char *id, const char *display_name) + const char *id, const char *display_name) { struct t_user *new_user, *ptr_user; diff --git a/user.h b/user.h index 88aaf96..624aaf2 100644 --- a/user.h +++ b/user.h @@ -53,23 +53,26 @@ struct t_channel; const char *user__get_colour(struct t_user *user); +const char *user__as_prefix_raw(struct t_account *account, + const char *name); + const char *user__as_prefix(struct t_account *account, - struct t_user *user, - const char *name); + struct t_user *user, + const char *name); struct t_user *user__bot_search(struct t_account *account, - const char *bot_id); + const char *bot_id); struct t_user *user__search(struct t_account *account, - const char *id); + const char *id); struct t_user *user__new(struct t_account *account, - const char *id, const char *display_name); + const char *id, const char *display_name); void user__free_all(struct t_account *account); void user__nicklist_add(struct t_account *account, - struct t_channel *channel, - struct t_user *user); + struct t_channel *channel, + struct t_user *user); #endif /*WEECHAT_XMPP_USER_H*/ From 28106825e85adf7f294f86378de0c3f9c79df772 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 00:13:15 +0100 Subject: [PATCH 085/118] add libaxolotl --- .envrc | 3 ++- .gitmodules | 3 +++ Makefile | 34 +++++++++++++++++++++------------- README.org | 16 +++++++++++----- axc | 1 + 5 files changed, 38 insertions(+), 19 deletions(-) create mode 160000 axc diff --git a/.envrc b/.envrc index 989115f..0e1023d 100644 --- a/.envrc +++ b/.envrc @@ -36,7 +36,8 @@ use_guix() PACKAGES=( autoconf autoconf-archive automake libtool make cmake gcc-toolchain pkg-config patchelf - weechat xz libxml2 libstrophe json-c + weechat libxml2 libstrophe + glib libsignal-protocol-c sqlite ) # Thanks diff --git a/.gitmodules b/.gitmodules index e69de29..88ff237 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "axc"] + path = axc + url = https://github.com/gkdr/axc diff --git a/Makefile b/Makefile index b452cdd..1979980 100644 --- a/Makefile +++ b/Makefile @@ -14,28 +14,32 @@ LIBDIR ?= $(PREFIX)/lib INSTALL ?= /usr/bin/install SRCS=plugin.c \ - account.c \ - buffer.c \ - channel.c \ - command.c \ - config.c \ - connection.c \ - input.c \ - message.c \ - user.c \ - -DEPS= + account.c \ + buffer.c \ + channel.c \ + command.c \ + config.c \ + connection.c \ + input.c \ + message.c \ + user.c \ + +DEPS=axc/build/libaxc.a OBJS=$(subst .c,.o,$(SRCS)) all: weechat-xmpp weechat-xmpp: $(DEPS) xmpp.so -xmpp.so: $(OBJS) - $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(LDLIBS) +xmpp.so: $(OBJS) $(DEPS) + $(CC) $(LDFLAGS) -o xmpp.so $(OBJS) $(DEPS) $(LDLIBS) which patchelf >/dev/null && \ patchelf --set-rpath $(LIBRARY_PATH):$(shell realpath $(shell dirname $(shell gcc --print-libgcc-file-name))/../../../) xmpp.so && \ patchelf --shrink-rpath xmpp.so || true +axc/build/libaxc.a: + $(MAKE) -C axc +axc: axc/build/libaxc.a + test: xmpp.so env LD_PRELOAD=$(DEBUG) \ weechat -a -P 'alias,buflist,irc' -r '/plugin load ./xmpp.so' @@ -55,6 +59,10 @@ tidy: clean: $(RM) $(OBJS) + $(MAKE) -C axc clean + git submodule foreach --recursive git clean -xfd || true + git submodule foreach --recursive git reset --hard || true + git submodule update --init --recursive || true distclean: clean $(RM) *~ .depend diff --git a/README.org b/README.org index d93dc88..6b5244d 100644 --- a/README.org +++ b/README.org @@ -81,20 +81,26 @@ * [X] Opening PMs (/chat) ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message - * [ ] Handle wide errors gracefully + * [ ] [#B] Handle wide errors gracefully * [ ] MUCs * [X] Opening (/enter) * [X] Receiving * [X] Sending + * [ ] [#B] Edits * [ ] [#B] Handle errors gracefully * [ ] [#B] Presence/nicklist - * [ ] [#B] Show topic - * [ ] [#B] Edits - * [ ] OMEMO presence - * [ ] OMEMO messages + * [ ] [#B] Enters + * [ ] [#B] Leaves + * [ ] [#B] Tracking + * [ ] [#B] Set/show topic + * [ ] OMEMO (libsignal-protocol-c / axc) + * [ ] Presence + * [ ] Messages * [ ] MUC PMs * [ ] Send typing notifications * [ ] Recv typing notifications + * [ ] OTR (libotr) + * [ ] PGP (libgpgme) ** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) diff --git a/axc b/axc new file mode 160000 index 0000000..1d4454e --- /dev/null +++ b/axc @@ -0,0 +1 @@ +Subproject commit 1d4454ea42d39a2064955f2a8de5f89787743f2a From cd2a3966985f353b0291fc1621096c3f6fadea1b Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 05:55:43 +0100 Subject: [PATCH 086/118] add libomemo --- .gitmodules | 3 +++ README.org | 1 + account.c | 27 +++++++++++++++++++-------- account.h | 22 ++++++++++++++++++++-- channel.c | 20 +++++++++++--------- command.c | 27 ++++++++++++--------------- connection.c | 2 ++ omemo | 1 + plugin.c | 2 +- plugin.h | 1 + 10 files changed, 71 insertions(+), 35 deletions(-) create mode 160000 omemo diff --git a/.gitmodules b/.gitmodules index 88ff237..56502e4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "axc"] path = axc url = https://github.com/gkdr/axc +[submodule "omemo"] + path = omemo + url = https://github.com/gkdr/libomemo diff --git a/README.org b/README.org index 6b5244d..e6acbed 100644 --- a/README.org +++ b/README.org @@ -99,6 +99,7 @@ * [ ] MUC PMs * [ ] Send typing notifications * [ ] Recv typing notifications + * [ ] Read receipts * [ ] OTR (libotr) * [ ] PGP (libgpgme) ** TODO [#C] Implement completion engine (milestone v0.3) diff --git a/account.c b/account.c index c1d52ae..b76434d 100644 --- a/account.c +++ b/account.c @@ -100,7 +100,7 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve xmlGenericErrorContext = nullfd; const char *header = strndup(msg, xml - msg); - xmlDocPtr *doc = xmlRecoverMemory(xml, strlen(xml)); + xmlDocPtr doc = xmlRecoverMemory(xml, strlen(xml)); if (doc == NULL) { weechat_printf( account ? account->buffer : NULL, @@ -108,6 +108,21 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve fclose(nullfd); return; } + xmlNodePtr root = xmlDocGetRootElement(doc); + const char *tag = root ? root->name : ""; + const char *colour = weechat_color("blue"); + if (weechat_strcasecmp(tag, "message")) + { + colour = weechat_color("green"); + } + else if (weechat_strcasecmp(tag, "presence")) + { + colour = weechat_color("yellow"); + } + else if (weechat_strcasecmp(tag, "iq")) + { + colour = weechat_color("red"); + } xmlChar *buf = malloc(strlen(xml) * 2); if (buf == NULL) { weechat_printf( @@ -135,7 +150,7 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve for (int i = 1; i < size; i++) weechat_printf( account ? account->buffer : NULL, - _("%s"), lines[i]); + _("%s%s"), colour, lines[i]); fclose(nullfd); } @@ -191,8 +206,6 @@ struct t_account *account__alloc(const char *name) new_account->context = xmpp_ctx_new(NULL, &new_account->logger); new_account->connection = NULL; - new_account->nickname = NULL; - new_account->buffer = NULL; new_account->buffer_as_string = NULL; new_account->users = NULL; @@ -497,10 +510,8 @@ int account__connect(struct t_account *account) account__close_connection(account); account->is_connected = - connection__connect(account, &account->connection, - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), - weechat_config_string(account->options[ACCOUNT_OPTION_PASSWORD]), - weechat_config_string(account->options[ACCOUNT_OPTION_TLS])); + connection__connect(account, &account->connection, account_jid(account), + account_password(account), account_tls(account)); return account->is_connected; } diff --git a/account.h b/account.h index 4720016..8f2b040 100644 --- a/account.h +++ b/account.h @@ -18,6 +18,26 @@ enum t_account_option 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) \ + weechat_config_string(account->options[ACCOUNT_OPTION_JID]) +#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]) + struct t_account { const char *name; @@ -32,8 +52,6 @@ struct t_account struct xmpp_ctx_t *context; struct xmpp_conn_t *connection; - char *nickname; - struct t_gui_buffer *buffer; char *buffer_as_string; struct t_user *users; diff --git a/channel.c b/channel.c index 9e92730..04f1c84 100644 --- a/channel.c +++ b/channel.c @@ -111,21 +111,25 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, else { short_name = weechat_buffer_get_string (ptr_buffer, "short_name"); - localvar_channel = weechat_buffer_get_string (ptr_buffer, - "localvar_channel"); + localvar_channel = weechat_buffer_get_string(ptr_buffer, + "localvar_channel"); if (!short_name || (localvar_channel && (strcmp(localvar_channel, short_name) == 0))) { - weechat_buffer_set (ptr_buffer, "short_name", xmpp_jid_node(account->context, - name)); + weechat_buffer_set(ptr_buffer, "short_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))); weechat_buffer_set(ptr_buffer, "name", name); weechat_buffer_set(ptr_buffer, "localvar_set_type", (type == CHANNEL_TYPE_PM) ? "private" : "channel"); - weechat_buffer_set(ptr_buffer, "localvar_set_nick", account->nickname); + weechat_buffer_set(ptr_buffer, "localvar_set_nick", + account_nickname(account)); weechat_buffer_set(ptr_buffer, "localvar_set_server", account->name); weechat_buffer_set(ptr_buffer, "localvar_set_channel", name); @@ -146,7 +150,7 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, } weechat_buffer_set(ptr_buffer, "highlight_words_add", - account->nickname); + account_nickname(account)); weechat_buffer_set(ptr_buffer, "highlight_tags_restrict", "message"); } @@ -611,8 +615,6 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) weechat_printf(channel->buffer, "%s%s", - user__as_prefix_raw( - account, - weechat_config_string(account->options[ACCOUNT_OPTION_JID])), + user__as_prefix_raw(account, account_jid(account)), body); } diff --git a/command.c b/command.c index 6c09ed3..78bd7c4 100644 --- a/command.c +++ b/command.c @@ -34,7 +34,7 @@ void command__display_account(struct t_account *account) weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + account_jid(account), weechat_color("chat_delimiters"), weechat_color("reset"), (account->is_connected) ? _("connected") : _("not connected"), @@ -54,7 +54,7 @@ void command__display_account(struct t_account *account) weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - weechat_config_string(account->options[ACCOUNT_OPTION_JID]), + account_jid(account), weechat_color("chat_delimiters"), weechat_color("reset")); } @@ -139,14 +139,12 @@ void command__add_account(const char *name, const char *jid, const char *passwor account->name = strdup(name); if (jid) - weechat_config_option_set(account->options[ACCOUNT_OPTION_JID], - strdup(jid), 1); + account_option_set(account, ACCOUNT_OPTION_JID, strdup(jid)); if (password) - weechat_config_option_set(account->options[ACCOUNT_OPTION_PASSWORD], - strdup(password), 1); + account_option_set(account, ACCOUNT_OPTION_PASSWORD, strdup(password)); if (jid) - weechat_config_option_set(account->options[ACCOUNT_OPTION_NICKNAME], - strdup(xmpp_jid_node(account->context, jid)), 1); + account_option_set(account, ACCOUNT_OPTION_NICKNAME, + strdup(xmpp_jid_node(account->context, jid))); weechat_printf ( NULL, @@ -364,11 +362,11 @@ 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), - weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME]) - && strlen(weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME])) - ? weechat_config_string(ptr_account->options[ACCOUNT_OPTION_NICKNAME]) + account_nickname(ptr_account) + && strlen(account_nickname(ptr_account)) + ? account_nickname(ptr_account) : xmpp_jid_node(ptr_account->context, - weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]))); + account_jid(ptr_account))); ptr_channel = channel__search(ptr_account, jid); if (!ptr_channel) @@ -376,7 +374,7 @@ int command__enter(const void *pointer, void *data, pres = xmpp_presence_new(ptr_account->context); xmpp_stanza_set_to(pres, pres_jid); - xmpp_stanza_set_from(pres, weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID])); + xmpp_stanza_set_from(pres, account_jid(ptr_account)); struct xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); xmpp_stanza_set_name(pres__x, "x"); @@ -493,8 +491,7 @@ int command__me(const void *pointer, void *data, xmpp_stanza_release(message); if (ptr_channel->type != CHANNEL_TYPE_MUC) weechat_printf(ptr_channel->buffer, "%s%s %s", - weechat_prefix("action"), - weechat_config_string(ptr_account->options[ACCOUNT_OPTION_JID]), + weechat_prefix("action"), account_jid(ptr_account), text); } diff --git a/connection.c b/connection.c index c1013d4..241d588 100644 --- a/connection.c +++ b/connection.c @@ -163,6 +163,8 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, flags |= XMPP_CONN_FLAG_DISABLE_TLS; break; case 1: + flags |= ~XMPP_CONN_FLAG_DISABLE_TLS; + flags |= ~XMPP_CONN_FLAG_TRUST_TLS; break; case 2: flags |= XMPP_CONN_FLAG_TRUST_TLS; diff --git a/omemo b/omemo new file mode 160000 index 0000000..7667e54 --- /dev/null +++ b/omemo @@ -0,0 +1 @@ +Subproject commit 7667e54d6488aba85701bb4dd6e09fd98bfb3a2c diff --git a/plugin.c b/plugin.c index 02fa0a5..0479cee 100644 --- a/plugin.c +++ b/plugin.c @@ -48,7 +48,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) //completion__init(); - weechat_xmpp_process_timer = weechat_hook_timer(0.1 * 1000, 0, 0, + weechat_xmpp_process_timer = weechat_hook_timer(TIMER_INTERVAL_SEC * 1000, 0, 0, &account__timer_cb, NULL, NULL); diff --git a/plugin.h b/plugin.h index d2a3f07..27e196f 100644 --- a/plugin.h +++ b/plugin.h @@ -8,6 +8,7 @@ #define weechat_plugin weechat_xmpp_plugin #define WEECHAT_XMPP_PLUGIN_NAME "xmpp" #define WEECHAT_XMPP_PLUGIN_VERSION "0.1.1" +#define TIMER_INTERVAL_SEC 0.01 extern struct t_weechat_plugin *weechat_xmpp_plugin; From 5a13c57a3363090c512db092d8c396951ee66d36 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 07:48:09 +0100 Subject: [PATCH 087/118] device resource --- account.c | 1 + account.h | 10 ++++++++++ command.c | 1 + config.c | 16 ++++++++++++++++ connection.c | 35 ++++++++++++++++++++++++++++++++++- 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/account.c b/account.c index b76434d..25d8454 100644 --- a/account.c +++ b/account.c @@ -28,6 +28,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "tls", "normal" }, { "nickname", "" }, { "autoconnect", "" }, + { "resource", "" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index 8f2b040..b5fe1d1 100644 --- a/account.h +++ b/account.h @@ -15,6 +15,7 @@ enum t_account_option ACCOUNT_OPTION_TLS, ACCOUNT_OPTION_NICKNAME, ACCOUNT_OPTION_AUTOCONNECT, + ACCOUNT_OPTION_RESOURCE, ACCOUNT_NUM_OPTIONS, }; @@ -29,6 +30,13 @@ enum t_account_option #define account_jid(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_JID]) +#define account_jid_device(account) \ + 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) \ @@ -37,6 +45,8 @@ enum t_account_option 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]) struct t_account { diff --git a/command.c b/command.c index 78bd7c4..55dacac 100644 --- a/command.c +++ b/command.c @@ -428,6 +428,7 @@ int command__open(const void *pointer, void *data, pres = xmpp_presence_new(ptr_account->context); xmpp_stanza_set_to(pres, jid); + xmpp_stanza_set_from(pres, account_jid(ptr_account)); xmpp_send(ptr_account->connection, pres); xmpp_stanza_release(pres); diff --git a/config.c b/config.c index b2cf31f..a963b31 100644 --- a/config.c +++ b/config.c @@ -154,6 +154,22 @@ config__account_new_option (struct t_config_file *config_file, 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_NUM_OPTIONS: break; } diff --git a/connection.c b/connection.c index 241d588..7dbf5cd 100644 --- a/connection.c +++ b/connection.c @@ -2,7 +2,9 @@ // 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 #include @@ -141,6 +143,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, /* Send initial so that we appear online to contacts */ pres = xmpp_presence_new(account->context); + xmpp_stanza_set_from(pres, account_jid(account)); xmpp_send(conn, pres); xmpp_stanza_release(pres); } else { @@ -149,11 +152,41 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, } } +char *const rand_string(int length) +{ + char *string = malloc(length); + srand(time(NULL)); + for(int i = 0; i < length; ++i){ + string[i] = '0' + rand()%72; // starting on '0', ending on '}' + if (!((string[i] >= '0' && string[i] <= '9') || + (string[i] >= 'A' && string[i] <= 'Z') || + (string[i] >= 'a' && string[i] <= 'z'))) + i--; // reroll + } + string[length] = 0; + return string; +} + int connection__connect(struct t_account *account, xmpp_conn_t **connection, const char* jid, const char* password, int tls) { *connection = xmpp_conn_new(account->context); - xmpp_conn_set_jid(*connection, jid); + char *resource = account_resource(account); + if (!(resource && strlen(resource))) + { + 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); + } + 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); auto flags = xmpp_conn_get_flags(*connection); From a18a815c0c46a4966cecb7ab30864a0713f577f6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 09:29:21 +0100 Subject: [PATCH 088/118] presence and backlog --- Makefile | 2 +- README.org | 1 + connection.c | 67 +++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 1979980..e09fd72 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ endif RM=rm -f FIND=find INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) -CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers $(INCLUDES) +CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=500 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) diff --git a/README.org b/README.org index e6acbed..dc1c278 100644 --- a/README.org +++ b/README.org @@ -82,6 +82,7 @@ ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message * [ ] [#B] Handle wide errors gracefully + * [ ] [#B] Event-driven MUC entrance * [ ] MUCs * [X] Opening (/enter) * [X] Receiving diff --git a/connection.c b/connection.c index 7dbf5cd..83a9887 100644 --- a/connection.c +++ b/connection.c @@ -72,12 +72,40 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) return 1; } +int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +{ + struct t_account *account = (struct t_account *)userdata; + const char *to, *from, *from_bare; + + from = xmpp_stanza_get_from(stanza); + if (from == NULL) + return 1; + from_bare = xmpp_jid_bare(account->context, from); + to = xmpp_stanza_get_to(stanza); + + struct t_user *user = user__search(account, from); + if (!user) + user = user__new(account, from, from); + + struct t_channel *channel = channel__search(account, from_bare); + if (!channel) + channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + + weechat_printf(account->buffer, "%s%s (%s) presence", + weechat_prefix("action"), + user->name, user->profile.display_name); + + return 1; +} + int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *body, *reply, *to; - const char *type, *from, *from_bare; + xmpp_stanza_t *body, *reply, *delay; + const char *type, *from, *from_bare, *to, *timestamp = 0; char *intext, *replytext; + struct tm time = {0}; + time_t date = 0; body = xmpp_stanza_get_child_by_name(stanza, "body"); if (body == NULL) @@ -107,18 +135,25 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) ? xmpp_jid_resource(account->context, from) : from; } + delay = xmpp_stanza_get_child_by_name_and_ns(stanza, "delay", "urn:xmpp:delay"); + timestamp = delay ? xmpp_stanza_get_attribute(delay, "stamp") : NULL; + if (timestamp) + { + strptime(timestamp, "%FT%T", &time); + date = mktime(&time); + } if (strcmp(to, channel->id) == 0) - weechat_printf(channel->buffer, "%s[to %s]: %s", - user__as_prefix_raw(account->context, from), - to, intext); + weechat_printf_date_tags(channel->buffer, date, NULL, "%s[to %s]: %s", + user__as_prefix_raw(account->context, from), + to, intext); else if (weechat_string_match(intext, "/me *", 0)) - weechat_printf(channel->buffer, "%s%s %s", - weechat_prefix("action"), from, intext+4); + weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s %s", + weechat_prefix("action"), from, intext+4); else - weechat_printf(channel->buffer, "%s%s", - user__as_prefix_raw(account->context, from), - intext); + weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s", + user__as_prefix_raw(account->context, from), + intext); xmpp_free(account->context, intext); @@ -136,10 +171,10 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, if (status == XMPP_CONN_CONNECT) { xmpp_stanza_t *pres; - //weechat_printf(account->buffer, "DEBUG: connected"); - xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, - account); - xmpp_handler_add(conn, message_handler, NULL, "message", NULL, account); + + xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, account); + xmpp_handler_add(conn, presence_handler, NULL, "presence", NULL, account); + xmpp_handler_add(conn, message_handler, NULL, "message", /*type*/ NULL, account); /* Send initial so that we appear online to contacts */ pres = xmpp_presence_new(account->context); @@ -196,8 +231,8 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, flags |= XMPP_CONN_FLAG_DISABLE_TLS; break; case 1: - flags |= ~XMPP_CONN_FLAG_DISABLE_TLS; - flags |= ~XMPP_CONN_FLAG_TRUST_TLS; + flags &= ~XMPP_CONN_FLAG_DISABLE_TLS; + flags &= ~XMPP_CONN_FLAG_TRUST_TLS; break; case 2: flags |= XMPP_CONN_FLAG_TRUST_TLS; From c5436de3703403c5b43bcf79004b6947d37ab3c4 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 17:26:23 +0100 Subject: [PATCH 089/118] nicklists and subject --- Makefile | 2 +- README.org | 6 +++--- channel.c | 3 ++- connection.c | 41 +++++++++++++++++++++++++++++++---------- user.c | 8 ++++++-- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index e09fd72..04dbd77 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ endif RM=rm -f FIND=find INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) -CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=500 $(INCLUDES) +CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) diff --git a/README.org b/README.org index dc1c278..9decce2 100644 --- a/README.org +++ b/README.org @@ -90,10 +90,10 @@ * [ ] [#B] Edits * [ ] [#B] Handle errors gracefully * [ ] [#B] Presence/nicklist - * [ ] [#B] Enters + * [X] [#B] Enters * [ ] [#B] Leaves - * [ ] [#B] Tracking - * [ ] [#B] Set/show topic + * [X] [#B] Tracking + * [X] [#B] Set/show topic * [ ] OMEMO (libsignal-protocol-c / axc) * [ ] Presence * [ ] Messages diff --git a/channel.c b/channel.c index 04f1c84..8ea3510 100644 --- a/channel.c +++ b/channel.c @@ -323,7 +323,8 @@ void channel__member_speaking_rename_if_present(struct t_account *account, for (j = 0; j < list_size; j++) { ptr_item = weechat_list_get (channel->members_speaking[i], j); - if (ptr_item && (strcasecmp(weechat_list_string(ptr_item), nick) == 0)) + if (ptr_item && (weechat_strcasecmp(weechat_list_string(ptr_item), + nick) == 0)) weechat_list_set(ptr_item, nick); } } diff --git a/connection.c b/connection.c index 83a9887..6e57c60 100644 --- a/connection.c +++ b/connection.c @@ -75,6 +75,8 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { struct t_account *account = (struct t_account *)userdata; + struct t_user *user; + struct t_channel *channel; const char *to, *from, *from_bare; from = xmpp_stanza_get_from(stanza); @@ -83,13 +85,14 @@ int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) from_bare = xmpp_jid_bare(account->context, from); to = xmpp_stanza_get_to(stanza); - struct t_user *user = user__search(account, from); + user = user__search(account, from); if (!user) user = user__new(account, from, from); - struct t_channel *channel = channel__search(account, from_bare); + channel = channel__search(account, from_bare); if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + channel__add_member(account, channel, from); weechat_printf(account->buffer, "%s%s (%s) presence", weechat_prefix("action"), @@ -101,7 +104,8 @@ int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *body, *reply, *delay; + struct t_channel *channel; + xmpp_stanza_t *body, *reply, *delay, *topic; const char *type, *from, *from_bare, *to, *timestamp = 0; char *intext, *replytext; struct tm time = {0}; @@ -109,7 +113,24 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) body = xmpp_stanza_get_child_by_name(stanza, "body"); if (body == NULL) + { + topic = xmpp_stanza_get_child_by_name(stanza, "subject"); + if (topic == NULL) + return 1; + intext = xmpp_stanza_get_text(topic); + 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); + if (!channel) + channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + channel__update_topic(channel, intext ? intext : "", from, 0); + if (intext != NULL) + xmpp_free(account->context, intext); return 1; + } type = xmpp_stanza_get_type(stanza); if (type != NULL && strcmp(type, "error") == 0) return 1; @@ -120,10 +141,8 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) to = xmpp_stanza_get_to(stanza); intext = xmpp_stanza_get_text(body); - if (intext == NULL) - intext = strdup(""); - struct t_channel *channel = channel__search(account, from_bare); + channel = channel__search(account, from_bare); if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); @@ -146,16 +165,18 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, NULL, "%s[to %s]: %s", user__as_prefix_raw(account->context, from), - to, intext); + to, intext ? intext : ""); else if (weechat_string_match(intext, "/me *", 0)) weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s %s", - weechat_prefix("action"), from, intext+4); + weechat_prefix("action"), from, + intext ? intext+4 : ""); else weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s", user__as_prefix_raw(account->context, from), - intext); + intext ? intext : ""); - xmpp_free(account->context, intext); + if (intext) + xmpp_free(account->context, intext); return 1; } diff --git a/user.c b/user.c index 4cc62ac..b6d740c 100644 --- a/user.c +++ b/user.c @@ -95,6 +95,10 @@ void user__nicklist_add(struct t_account *account, { struct t_gui_nick_group *ptr_group; struct t_gui_buffer *ptr_buffer; + char *name = user->profile.display_name; + if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name), + channel->id) == 0) + name = xmpp_jid_resource(account->context, name); ptr_buffer = channel ? channel->buffer : account->buffer; @@ -102,7 +106,7 @@ void user__nicklist_add(struct t_account *account, user->is_away ? "+" : "..."); weechat_nicklist_add_nick(ptr_buffer, ptr_group, - user->profile.display_name, + name, user->is_away ? "weechat.color.nicklist_away" : user__get_colour_for_nicklist(user), @@ -165,7 +169,7 @@ struct t_user *user__new(struct t_account *account, new_user->profile.real_name = NULL; new_user->profile.display_name = display_name[0] ? strdup(display_name) : - strdup("xmppbot"); + strdup("???"); new_user->profile.real_name_normalized = NULL; new_user->profile.email = NULL; new_user->profile.team = NULL; From 4e2bfee7142f7c1c9fd9cab4614eceb8222757b0 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 19:46:58 +0100 Subject: [PATCH 090/118] hacky impl of oob --- Makefile | 5 +++-- README.org | 1 + channel.c | 23 +++++++++++++++++++++++ command.c | 2 +- connection.c | 14 +++++++++++++- omemo.c | 16 ++++++++++++++++ omemo.h | 10 ++++++++++ 7 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 omemo.c create mode 100644 omemo.h diff --git a/Makefile b/Makefile index 04dbd77..306715e 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,10 @@ ifdef DEBUG endif RM=rm -f FIND=find -INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) +INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags glib-2.0) $(shell pkg-config --cflags libsignal-protocol-c) CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) -LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs glib-2.0) $(shell pkg-config --libs libsignal-protocol-c) PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -22,6 +22,7 @@ SRCS=plugin.c \ connection.c \ input.c \ message.c \ + omemo.c \ user.c \ DEPS=axc/build/libaxc.a diff --git a/README.org b/README.org index 9decce2..d5cc9d0 100644 --- a/README.org +++ b/README.org @@ -81,6 +81,7 @@ * [X] Opening PMs (/chat) ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message + * [X] OOB media messages * [ ] [#B] Handle wide errors gracefully * [ ] [#B] Event-driven MUC entrance * [ ] MUCs diff --git a/channel.c b/channel.c index 8ea3510..7c2f9b3 100644 --- a/channel.c +++ b/channel.c @@ -612,6 +612,29 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, ? "groupchat" : "chat", to, NULL); xmpp_message_set_body(message, body); + + char *url = strstr(body, "http"); + if (url) + { + struct 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"); + + struct xmpp_stanza_t *message__x__url = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(message__x__url, "url"); + + struct xmpp_stanza_t *message__x__url__text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(message__x__url__text, url); + xmpp_stanza_add_child(message__x__url, message__x__url__text); + xmpp_stanza_release(message__x__url__text); + + xmpp_stanza_add_child(message__x, message__x__url); + xmpp_stanza_release(message__x__url); + + xmpp_stanza_add_child(message, message__x); + xmpp_stanza_release(message__x); + } + xmpp_send(account->connection, message); xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) diff --git a/command.c b/command.c index 55dacac..e409df3 100644 --- a/command.c +++ b/command.c @@ -380,9 +380,9 @@ int command__enter(const void *pointer, void *data, xmpp_stanza_set_name(pres__x, "x"); xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); xmpp_stanza_add_child(pres, pres__x); + xmpp_stanza_release(pres__x); xmpp_send(ptr_account->connection, pres); - xmpp_stanza_release(pres__x); xmpp_stanza_release(pres); if (argc > 2) diff --git a/connection.c b/connection.c index 6e57c60..fd962c9 100644 --- a/connection.c +++ b/connection.c @@ -191,7 +191,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, (void)stream_error; if (status == XMPP_CONN_CONNECT) { - xmpp_stanza_t *pres; + xmpp_stanza_t *pres, *pres__c; + char cap_hash[28+1] = {0}; xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, account); xmpp_handler_add(conn, presence_handler, NULL, "presence", NULL, account); @@ -200,6 +201,17 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, /* Send initial so that we appear online to contacts */ pres = xmpp_presence_new(account->context); xmpp_stanza_set_from(pres, account_jid(account)); + + 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"); + snprintf(cap_hash, sizeof(cap_hash), "%027d=", time(NULL)); + xmpp_stanza_set_attribute(pres__c, "ver", cap_hash); + xmpp_stanza_add_child(pres, pres__c); + xmpp_stanza_release(pres__c); + xmpp_send(conn, pres); xmpp_stanza_release(pres); } else { diff --git a/omemo.c b/omemo.c new file mode 100644 index 0000000..affb2b0 --- /dev/null +++ b/omemo.c @@ -0,0 +1,16 @@ +// 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 "omemo/src/libomemo.h" +#include "axc/src/axc.h" + +#include "omemo.h" + +void omemo__init() +{ + const char* ns_devicelist = "eu.siacs.conversations.axolotl.devicelist"; + const char* ft_devicelist = "eu.siacs.conversations.axolotl.devicelist+notify"; +} diff --git a/omemo.h b/omemo.h new file mode 100644 index 0000000..7fb146c --- /dev/null +++ b/omemo.h @@ -0,0 +1,10 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_OMEMO_H_ +#define _WEECHAT_XMPP_OMEMO_H_ + +void omemo__init(); + +#endif /*WEECHAT_XMPP_OMEMO_H*/ From ec3e91871229af2fc1a2dce9d95a1076b128d910 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 2 Jul 2021 23:10:40 +0100 Subject: [PATCH 091/118] freebsd has no install, eek --- Makefile | 13 ++++++++----- README.org | 6 ++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 306715e..1ec5c26 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,6 @@ LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib -INSTALL ?= /usr/bin/install SRCS=plugin.c \ account.c \ @@ -59,8 +58,8 @@ tidy: $(FIND) . -name "*.o" -delete clean: - $(RM) $(OBJS) - $(MAKE) -C axc clean + $(RM) -f $(OBJS) + $(MAKE) -C axc clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true git submodule update --init --recursive || true @@ -70,9 +69,13 @@ distclean: clean install: xmpp.so ifeq ($(shell id -u),0) - $(INSTALL) -s -t $(DESTDIR)$(LIBDIR)/weechat/plugins -D -m 0644 xmpp.so + mkdir -p $(DESTDIR)$(LIBDIR)/weechat/plugins + cp xmpp.so $(DESTDIR)$(LIBDIR)/weechat/plugins/xmpp.so + chmod 644 $(DESTDIR)$(LIBDIR)/weechat/plugins/xmpp.so else - $(INSTALL) -s -t ~/.weechat/plugins -D -m 0755 xmpp.so + mkdir -p ~/.weechat/plugins + cp xmpp.so ~/.weechat/plugins/xmpp.so + chmod 755 ~/.weechat/plugins/xmpp.so endif .PHONY: tags cs diff --git a/README.org b/README.org index d5cc9d0..5ae53d4 100644 --- a/README.org +++ b/README.org @@ -43,13 +43,19 @@ - libstrophe (dynamic, dependency) - libxml2 (dynamic, dependency) + - glib (dynamic, dependency of libomemo) + - sqlite (dynamic, dependency of libomemo/axc) + - libsignal-protocol-c (dynamic, dependency of axc) - weechat (>= v2.5) + .. or just use the guix spec in .envrc + * Building #+begin_src sh git clone git://github.com/bqv/weechat-xmpp.git cd weechat-xmpp + git submodule update --init --recursive make make install #+end_src From cd0beab6767b17bca4250a202f4eb7447c8abe84 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 3 Jul 2021 00:05:36 +0100 Subject: [PATCH 092/118] presence status --- README.org | 3 +++ account.c | 1 + account.h | 3 +++ config.c | 16 ++++++++++++++++ connection.c | 13 ++++++++++++- 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 5ae53d4..7e85286 100644 --- a/README.org +++ b/README.org @@ -88,6 +88,9 @@ ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message * [X] OOB media messages + * [ ] Buffer autoswitch on enter/open + * [ ] Handle open/enter jids with a resource without breaking + * [ ] Allow /close without crashing * [ ] [#B] Handle wide errors gracefully * [ ] [#B] Event-driven MUC entrance * [ ] MUCs diff --git a/account.c b/account.c index 25d8454..2535275 100644 --- a/account.c +++ b/account.c @@ -29,6 +29,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "nickname", "" }, { "autoconnect", "" }, { "resource", "" }, + { "status", "probably about to segfault" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index b5fe1d1..202c5fa 100644 --- a/account.h +++ b/account.h @@ -16,6 +16,7 @@ enum t_account_option ACCOUNT_OPTION_NICKNAME, ACCOUNT_OPTION_AUTOCONNECT, ACCOUNT_OPTION_RESOURCE, + ACCOUNT_OPTION_STATUS, ACCOUNT_NUM_OPTIONS, }; @@ -47,6 +48,8 @@ enum t_account_option 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]) struct t_account { diff --git a/config.c b/config.c index a963b31..b7e6c66 100644 --- a/config.c +++ b/config.c @@ -170,6 +170,22 @@ config__account_new_option (struct t_config_file *config_file, 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_NUM_OPTIONS: break; } diff --git a/connection.c b/connection.c index fd962c9..5676ec6 100644 --- a/connection.c +++ b/connection.c @@ -191,7 +191,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, (void)stream_error; if (status == XMPP_CONN_CONNECT) { - xmpp_stanza_t *pres, *pres__c; + xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text; char cap_hash[28+1] = {0}; xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, account); @@ -212,6 +212,17 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_stanza_add_child(pres, pres__c); xmpp_stanza_release(pres__c); + 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)); + xmpp_stanza_add_child(pres__status, pres__status__text); + xmpp_stanza_release(pres__status__text); + + xmpp_stanza_add_child(pres, pres__status); + xmpp_stanza_release(pres__status); + xmpp_send(conn, pres); xmpp_stanza_release(pres); } else { From fe633d3363df250248876c337d49c78f4541a8ae Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 3 Jul 2021 21:58:55 +0100 Subject: [PATCH 093/118] badge --- README.org | 1 + account.c | 1 + account.h | 3 +++ command.h | 3 +++ config.c | 16 ++++++++++++++++ connection.c | 5 +++++ 6 files changed, 29 insertions(+) diff --git a/README.org b/README.org index 7e85286..797c19d 100644 --- a/README.org +++ b/README.org @@ -16,6 +16,7 @@ [[https://github.com/bqv/weechat-xmpp/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-xmpp.svg]] [[https://github.com/bqv/weechat-xmpp/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-xmpp.svg]] [[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-xmpp-blue.svg]] +[[https://github.com/bqv/weechat-extras/][file:https://inverse.chat/badge.svg?room=weechat@conference.hmm.st]] | Status: | XMPP for power users and digital masochists | | Location: | [[http://github.com/bqv/weechat-xmpp]] | diff --git a/account.c b/account.c index 2535275..b0a14d8 100644 --- a/account.c +++ b/account.c @@ -30,6 +30,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "autoconnect", "" }, { "resource", "" }, { "status", "probably about to segfault" }, + { "autojoin", "" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index 202c5fa..2f56de8 100644 --- a/account.h +++ b/account.h @@ -17,6 +17,7 @@ enum t_account_option ACCOUNT_OPTION_AUTOCONNECT, ACCOUNT_OPTION_RESOURCE, ACCOUNT_OPTION_STATUS, + ACCOUNT_OPTION_AUTOJOIN, ACCOUNT_NUM_OPTIONS, }; @@ -50,6 +51,8 @@ enum t_account_option weechat_config_string(account->options[ACCOUNT_OPTION_RESOURCE]) #define account_status(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_STATUS]) +#define account_autojoin(account) \ + weechat_config_string(account->options[ACCOUNT_OPTION_AUTOJOIN]) struct t_account { diff --git a/command.h b/command.h index f8af048..fb87318 100644 --- a/command.h +++ b/command.h @@ -5,6 +5,9 @@ #ifndef _WEECHAT_XMPP_COMMAND_H_ #define _WEECHAT_XMPP_COMMAND_H_ +int command__enter(const void *pointer, void *data, + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol); void command__init(); #endif /*WEECHAT_XMPP_COMMAND_H*/ diff --git a/config.c b/config.c index b7e6c66..09fa0c6 100644 --- a/config.c +++ b/config.c @@ -186,6 +186,22 @@ config__account_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; + case ACCOUNT_OPTION_AUTOJOIN: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("XMPP Channel Autojoin"), + 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; } diff --git a/connection.c b/connection.c index 5676ec6..899c36b 100644 --- a/connection.c +++ b/connection.c @@ -225,6 +225,11 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, pres); xmpp_stanza_release(pres); + + command__enter(NULL, NULL, account->buffer, 2, argv, argv_eol); + + xmpp_send(conn, pres); + xmpp_stanza_release(pres); } else { //weechat_printf(account->buffer, "DEBUG: disconnected"); //xmpp_stop(account->context); From 4e2e7d91cc8be3b3e2c581683a658e26da7e2230 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 4 Jul 2021 00:22:57 +0100 Subject: [PATCH 094/118] autojoin --- account.c | 16 +++++----- account.h | 6 ++-- channel.c | 14 ++++----- command.c | 84 ++++++++++++++++++++++++++++------------------------ config.c | 2 +- connection.c | 36 ++++++++++++---------- plugin.c | 2 +- 7 files changed, 87 insertions(+), 73 deletions(-) diff --git a/account.c b/account.c index b0a14d8..39bb552 100644 --- a/account.c +++ b/account.c @@ -93,9 +93,6 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve static const char *log_level_name[4] = {"debug", "info", "warn", "error"}; - time_t date = time(NULL); - const char *timestamp = weechat_util_get_time_string(&date); - char *xml; if ((level == XMPP_LEVEL_DEBUG) && ((xml = strchr(msg, '<')) != NULL)) { @@ -112,7 +109,7 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve return; } xmlNodePtr root = xmlDocGetRootElement(doc); - const char *tag = root ? root->name : ""; + const char *tag = root ? (const char*)root->name : ""; const char *colour = weechat_color("blue"); if (weechat_strcasecmp(tag, "message")) { @@ -143,8 +140,10 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve fclose(nullfd); return; } - const char **lines = weechat_string_split(buf, "\r\n", NULL, - 0, 0, &size); + char **lines = weechat_string_split((char*)buf, "\r\n", NULL, + 0, 0, &size); + if (lines[size-1][0] == 0) + lines[--size] = 0; weechat_printf( account ? account->buffer : NULL, _("%s%s (%s): %s"), @@ -155,6 +154,7 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve account ? account->buffer : NULL, _("%s%s"), colour, lines[i]); + weechat_string_free_split(lines); fclose(nullfd); } else @@ -257,7 +257,7 @@ struct t_account *account__alloc(const char *name) void account__free_data(struct t_account *account) { - int i; + //int i; if (!account) return; @@ -535,4 +535,6 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls) || xmpp_conn_is_connected(ptr_account->connection))) connection__process(ptr_account->context, ptr_account->connection, 10); } + + return WEECHAT_RC_OK; } diff --git a/account.h b/account.h index 2f56de8..8fff73c 100644 --- a/account.h +++ b/account.h @@ -56,7 +56,7 @@ enum t_account_option struct t_account { - const char *name; + char *name; struct t_config_option *options[ACCOUNT_NUM_OPTIONS]; int reloading_from_config; @@ -65,8 +65,8 @@ struct t_account int disconnected; xmpp_log_t logger; - struct xmpp_ctx_t *context; - struct xmpp_conn_t *connection; + xmpp_ctx_t *context; + xmpp_conn_t *connection; struct t_gui_buffer *buffer; char *buffer_as_string; diff --git a/channel.c b/channel.c index 7c2f9b3..0379285 100644 --- a/channel.c +++ b/channel.c @@ -607,23 +607,23 @@ struct t_channel_member *channel__add_member(struct t_account *account, void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body) { - struct xmpp_stanza_t *message = xmpp_message_new(account->context, - channel->type == CHANNEL_TYPE_MUC - ? "groupchat" : "chat", - to, NULL); + xmpp_stanza_t *message = xmpp_message_new(account->context, + channel->type == CHANNEL_TYPE_MUC + ? "groupchat" : "chat", + to, NULL); xmpp_message_set_body(message, body); char *url = strstr(body, "http"); if (url) { - struct 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"); - struct 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"); - struct 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, url); xmpp_stanza_add_child(message__x__url, message__x__url__text); xmpp_stanza_release(message__x__url__text); diff --git a/command.c b/command.c index e409df3..899eeab 100644 --- a/command.c +++ b/command.c @@ -168,8 +168,10 @@ void command__account_add(int argc, char **argv) { case 5: password = argv[4]; + // fall through case 4: jid = argv[3]; + // fall through case 3: name = argv[2]; command__add_account(name, jid, password); @@ -332,7 +334,7 @@ int command__enter(const void *pointer, void *data, { struct t_account *ptr_account = NULL; struct t_channel *ptr_channel = NULL; - struct xmpp_stanza_t *pres; + xmpp_stanza_t *pres; char *jid, *pres_jid, *text; (void) pointer; @@ -354,43 +356,49 @@ int command__enter(const void *pointer, void *data, if (argc > 1) { - jid = argv[1]; - pres_jid = argv[1]; - - if(!xmpp_jid_resource(ptr_account->context, pres_jid)) - pres_jid = xmpp_jid_new( - 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) - : xmpp_jid_node(ptr_account->context, - account_jid(ptr_account))); - - ptr_channel = channel__search(ptr_account, jid); - if (!ptr_channel) - ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, jid, jid); - - pres = xmpp_presence_new(ptr_account->context); - xmpp_stanza_set_to(pres, pres_jid); - xmpp_stanza_set_from(pres, account_jid(ptr_account)); - - struct xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); - xmpp_stanza_set_name(pres__x, "x"); - xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); - xmpp_stanza_add_child(pres, pres__x); - xmpp_stanza_release(pres__x); - - xmpp_send(ptr_account->connection, pres); - xmpp_stanza_release(pres); - - if (argc > 2) + int n_jid = 0; + char **jids = weechat_string_split(argv[1], ",", NULL, 0, 0, &n_jid); + for (int i = 0; i < n_jid; i++) { - text = argv_eol[2]; + jid = xmpp_jid_bare(ptr_account->context, jids[i]); + pres_jid = jids[i]; + + if(!xmpp_jid_resource(ptr_account->context, pres_jid)) + pres_jid = xmpp_jid_new( + 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) + : xmpp_jid_node(ptr_account->context, + account_jid(ptr_account))); + + ptr_channel = channel__search(ptr_account, jid); + if (!ptr_channel) + ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, jid, jid); + + 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_t *pres__x = xmpp_stanza_new(ptr_account->context); + xmpp_stanza_set_name(pres__x, "x"); + xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); + xmpp_stanza_add_child(pres, pres__x); + xmpp_stanza_release(pres__x); + + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres); + + if (argc > 2) + { + text = argv_eol[2]; - channel__send_message(ptr_account, ptr_channel, jid, text); + channel__send_message(ptr_account, ptr_channel, jid, text); + } } + weechat_string_free_split(jids); } return WEECHAT_RC_OK; @@ -402,7 +410,7 @@ int command__open(const void *pointer, void *data, { struct t_account *ptr_account = NULL; struct t_channel *ptr_channel = NULL; - struct xmpp_stanza_t *pres; + xmpp_stanza_t *pres; char *jid, *text; (void) pointer; @@ -424,7 +432,7 @@ int command__open(const void *pointer, void *data, if (argc > 1) { - jid = argv[1]; + jid = xmpp_jid_bare(ptr_account->context, argv[1]); pres = xmpp_presence_new(ptr_account->context); xmpp_stanza_set_to(pres, jid); @@ -453,7 +461,7 @@ int command__me(const void *pointer, void *data, { struct t_account *ptr_account = NULL; struct t_channel *ptr_channel = NULL; - struct xmpp_stanza_t *message; + xmpp_stanza_t *message; char *text; (void) pointer; diff --git a/config.c b/config.c index 09fa0c6..8718d03 100644 --- a/config.c +++ b/config.c @@ -190,7 +190,7 @@ config__account_new_option (struct t_config_file *config_file, new_option = weechat_config_new_option ( config_file, section, option_name, "string", - N_("XMPP Channel Autojoin"), + N_("XMPP MUC Autojoins"), NULL, 0, 0, default_value, value, null_value_allowed, diff --git a/connection.c b/connection.c index 899c36b..62190d1 100644 --- a/connection.c +++ b/connection.c @@ -53,11 +53,11 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) version = xmpp_stanza_new(account->context); xmpp_stanza_set_name(version, "version"); - xmpp_stanza_add_child(query, weechat_version); + xmpp_stanza_add_child(query, version); xmpp_stanza_release(version); text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, version); + xmpp_stanza_set_text(text, weechat_version); xmpp_stanza_add_child(version, text); xmpp_stanza_release(text); @@ -74,16 +74,17 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { + (void) conn; + struct t_account *account = (struct t_account *)userdata; struct t_user *user; struct t_channel *channel; - const char *to, *from, *from_bare; + const char *from, *from_bare; from = xmpp_stanza_get_from(stanza); if (from == NULL) return 1; from_bare = xmpp_jid_bare(account->context, from); - to = xmpp_stanza_get_to(stanza); user = user__search(account, from); if (!user) @@ -103,11 +104,13 @@ int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { + (void) conn; + struct t_account *account = (struct t_account *)userdata; struct t_channel *channel; - xmpp_stanza_t *body, *reply, *delay, *topic; + xmpp_stanza_t *body, *delay, *topic; const char *type, *from, *from_bare, *to, *timestamp = 0; - char *intext, *replytext; + char *intext; struct tm time = {0}; time_t date = 0; @@ -164,7 +167,7 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) if (strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, NULL, "%s[to %s]: %s", - user__as_prefix_raw(account->context, from), + user__as_prefix_raw(account, from), to, intext ? intext : ""); else if (weechat_string_match(intext, "/me *", 0)) weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s %s", @@ -172,7 +175,7 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) intext ? intext+4 : ""); else weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s", - user__as_prefix_raw(account->context, from), + user__as_prefix_raw(account, from), intext ? intext : ""); if (intext) @@ -207,7 +210,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, 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"); - snprintf(cap_hash, sizeof(cap_hash), "%027d=", time(NULL)); + snprintf(cap_hash, sizeof(cap_hash), "%027ld=", time(NULL)); xmpp_stanza_set_attribute(pres__c, "ver", cap_hash); xmpp_stanza_add_child(pres, pres__c); xmpp_stanza_release(pres__c); @@ -226,17 +229,18 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, pres); xmpp_stanza_release(pres); - command__enter(NULL, NULL, account->buffer, 2, argv, argv_eol); - - xmpp_send(conn, pres); - xmpp_stanza_release(pres); + char **command = weechat_string_dyn_alloc(256); + weechat_string_dyn_concat(command, "/enter ", -1); + weechat_string_dyn_concat(command, account_autojoin(account), -1); + weechat_command(account->buffer, *command); + weechat_string_dyn_free(command, 1); } else { //weechat_printf(account->buffer, "DEBUG: disconnected"); //xmpp_stop(account->context); } } -char *const rand_string(int length) +char* rand_string(int length) { char *string = malloc(length); srand(time(NULL)); @@ -255,7 +259,7 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, const char* jid, const char* password, int tls) { *connection = xmpp_conn_new(account->context); - char *resource = account_resource(account); + const char *resource = account_resource(account); if (!(resource && strlen(resource))) { char *const rand = rand_string(8); @@ -273,7 +277,7 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, resource)); xmpp_conn_set_pass(*connection, password); - auto flags = xmpp_conn_get_flags(*connection); + int flags = xmpp_conn_get_flags(*connection); switch (tls) { case 0: diff --git a/plugin.c b/plugin.c index 0479cee..3905393 100644 --- a/plugin.c +++ b/plugin.c @@ -10,9 +10,9 @@ #include "plugin.h" #include "config.h" +#include "account.h" #include "connection.h" #include "command.h" -#include "account.h" #include "buffer.h" //#include "xmpp-completion.h" From 020da2710e85970a2cc0c472f51d2299787ce32c Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 4 Jul 2021 02:25:34 +0100 Subject: [PATCH 095/118] bugs --- README.org | 7 +-- account.c | 10 ++-- buffer.c | 59 +++++++++++++++------ channel.h | 3 ++ command.c | 147 +++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 177 insertions(+), 49 deletions(-) diff --git a/README.org b/README.org index 797c19d..325b96b 100644 --- a/README.org +++ b/README.org @@ -89,13 +89,14 @@ ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message * [X] OOB media messages - * [ ] Buffer autoswitch on enter/open - * [ ] Handle open/enter jids with a resource without breaking - * [ ] Allow /close without crashing + * [X] Buffer autoswitch on enter/open + * [X] Handle open/enter jids with a resource without breaking + * [X] Allow /close without crashing * [ ] [#B] Handle wide errors gracefully * [ ] [#B] Event-driven MUC entrance * [ ] MUCs * [X] Opening (/enter) + * [ ] Leave on /close * [X] Receiving * [X] Sending * [ ] [#B] Edits diff --git a/account.c b/account.c index 39bb552..daf0e3d 100644 --- a/account.c +++ b/account.c @@ -352,7 +352,6 @@ void account__disconnect(struct t_account *account, int reconnect) (void) reconnect; struct t_channel *ptr_channel; - (void) ptr_channel; if (account->is_connected) { @@ -415,7 +414,9 @@ void account__disconnect(struct t_account *account, int reconnect) account__set_lag (account); account->monitor = 0; account->monitor_time = 0; + */ + /* if (reconnect && IRC_SERVER_OPTION_BOOLEAN(account, IRC_SERVER_OPTION_AUTORECONNECT)) account__reconnect_schedule(account); @@ -437,10 +438,8 @@ void account__disconnect(struct t_account *account, int reconnect) */ /* send signal "account_disconnected" with account name */ - /* - (void) weechat_hook_signal_send("account_disconnected", + (void) weechat_hook_signal_send("xmpp_account_disconnected", WEECHAT_HOOK_SIGNAL_STRING, account->name); - */ } void account__disconnect_all() @@ -516,6 +515,9 @@ int account__connect(struct t_account *account) connection__connect(account, &account->connection, account_jid(account), account_password(account), account_tls(account)); + (void) weechat_hook_signal_send("xmpp_account_connected", + WEECHAT_HOOK_SIGNAL_STRING, account->name); + return account->is_connected; } diff --git a/buffer.c b/buffer.c index 6e974c9..11ed14d 100644 --- a/buffer.c +++ b/buffer.c @@ -21,6 +21,9 @@ void buffer__get_account_and_channel(struct t_gui_buffer *buffer, if (!buffer) return; + *account = NULL; + *channel = NULL; + /* look for a account or channel using this buffer */ for (ptr_account = accounts; ptr_account; ptr_account = ptr_account->next_account) @@ -45,8 +48,6 @@ void buffer__get_account_and_channel(struct t_gui_buffer *buffer, } } } - - /* no account or channel found */ } char *buffer__typing_bar_cb(const void *pointer, void *data, @@ -73,7 +74,7 @@ char *buffer__typing_bar_cb(const void *pointer, void *data, buffer__get_account_and_channel(buffer, &account, &channel); if (!channel) - return strdup(""); + return strndup("", 0); typecount = 0; @@ -105,7 +106,7 @@ char *buffer__typing_bar_cb(const void *pointer, void *data, } else { - return strdup(""); + return strndup("", 0); } } @@ -140,24 +141,50 @@ int buffer__close_cb(const void *pointer, void *data, struct t_account *ptr_account = NULL; struct t_channel *ptr_channel = NULL; - buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin"); - if (buffer_plugin == weechat_plugin) - buffer__get_account_and_channel(buffer, - &ptr_account, &ptr_channel); - (void) pointer; (void) data; - (void) buffer; - if (ptr_account) + buffer_plugin = weechat_buffer_get_pointer(buffer, "plugin"); + if (buffer_plugin != weechat_plugin) + return WEECHAT_RC_OK; + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + const char* type = weechat_buffer_get_string(buffer, "localvar_type"); + + if (weechat_strcasecmp(type, "server") == 0) { - if (!ptr_account->disconnected) + if (ptr_account) { - //command_quit_account(ptr_account, NULL); - account__disconnect(ptr_account, 0); - } + if (!ptr_account->disconnected) + { + account__disconnect(ptr_account, 0); + } - ptr_account->buffer = NULL; + ptr_account->buffer = NULL; + } + } + else if (weechat_strcasecmp(type, "channel") == 0) + { + if (ptr_account && ptr_channel) + { + if (!ptr_account->disconnected) + { + channel__free(ptr_account, ptr_channel); + } + } + } + else if (weechat_strcasecmp(type, "private") == 0) + { + if (ptr_account && ptr_channel) + { + if (!ptr_account->disconnected) + { + channel__free(ptr_account, ptr_channel); + } + } + } + else + { } return WEECHAT_RC_OK; diff --git a/channel.h b/channel.h index 3145fa1..4877714 100644 --- a/channel.h +++ b/channel.h @@ -101,6 +101,9 @@ struct t_channel_typing *channel__typing_search(struct t_channel *channel, void channel__add_typing(struct t_channel *channel, struct t_user *user); +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, diff --git a/command.c b/command.c index 899eeab..dfa1c0f 100644 --- a/command.c +++ b/command.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -237,6 +238,66 @@ int command__account_connect(int argc, char **argv) return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; } +int command__disconnect_account(struct t_account *account) +{ + if (!account) + return 0; + + if (!account->is_connected) + { + weechat_printf( + NULL, + _("%s%s: not connected to account \"%s\"!"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + account->name); + } + + account__disconnect(account, 0); + + return 1; +} + +int command__account_disconnect(int argc, char **argv) +{ + int i, nb_disconnect, disconnect_ok; + struct t_account *ptr_account; + + (void) argc; + (void) argv; + + disconnect_ok = 1; + + nb_disconnect = 0; + for (i = 2; i < argc; i++) + { + nb_disconnect++; + ptr_account = account__search(argv[i]); + if (ptr_account) + { + if (!command__disconnect_account(ptr_account)) + { + disconnect_ok = 0; + } + } + else + { + weechat_printf( + NULL, + _("%s%s: account not found \"%s\" "), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + argv[i]); + } + } + + return (disconnect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; +} + +int command__account_reconnect(int argc, char **argv) +{ + command__account_disconnect(argc, argv); + return command__account_connect(argc, argv); +} + void command__account_delete(int argc, char **argv) { struct t_account *account; @@ -316,6 +377,18 @@ int command__account(const void *pointer, void *data, return WEECHAT_RC_OK; } + if (weechat_strcasecmp(argv[1], "disconnect") == 0) + { + command__account_disconnect(argc, argv); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp(argv[1], "reconnect") == 0) + { + command__account_reconnect(argc, argv); + return WEECHAT_RC_OK; + } + if (weechat_strcasecmp(argv[1], "delete") == 0) { command__account_delete(argc, argv); @@ -385,18 +458,23 @@ int command__enter(const void *pointer, void *data, xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); xmpp_stanza_set_name(pres__x, "x"); xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); - xmpp_stanza_add_child(pres, pres__x); - xmpp_stanza_release(pres__x); + xmpp_stanza_add_child(pres, pres__x); + xmpp_stanza_release(pres__x); - xmpp_send(ptr_account->connection, pres); - xmpp_stanza_release(pres); + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres); - if (argc > 2) - { - text = argv_eol[2]; + if (argc > 2) + { + text = argv_eol[2]; - channel__send_message(ptr_account, ptr_channel, jid, text); - } + channel__send_message(ptr_account, ptr_channel, jid, text); + } + + char buf[16]; + int num = weechat_buffer_get_integer(ptr_channel->buffer, "number"); + snprintf(buf, sizeof(buf), "/buffer %d", num); + weechat_command(ptr_account->buffer, buf); } weechat_string_free_split(jids); } @@ -432,24 +510,35 @@ int command__open(const void *pointer, void *data, if (argc > 1) { - jid = xmpp_jid_bare(ptr_account->context, argv[1]); + int n_jid = 0; + char **jids = weechat_string_split(argv[1], ",", NULL, 0, 0, &n_jid); + for (int i = 0; i < n_jid; i++) + { + jid = xmpp_jid_bare(ptr_account->context, jids[i]); - pres = xmpp_presence_new(ptr_account->context); - xmpp_stanza_set_to(pres, jid); - xmpp_stanza_set_from(pres, account_jid(ptr_account)); - xmpp_send(ptr_account->connection, pres); - xmpp_stanza_release(pres); + pres = xmpp_presence_new(ptr_account->context); + xmpp_stanza_set_to(pres, jid); + xmpp_stanza_set_from(pres, account_jid(ptr_account)); + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres); - ptr_channel = channel__search(ptr_account, jid); - if (!ptr_channel) - ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_PM, jid, jid); + ptr_channel = channel__search(ptr_account, jid); + if (!ptr_channel) + ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_PM, jid, jid); - if (argc > 2) - { - text = argv_eol[2]; + if (argc > 2) + { + text = argv_eol[2]; + + channel__send_message(ptr_account, ptr_channel, jid, text); + } - channel__send_message(ptr_account, ptr_channel, jid, text); + char buf[16]; + int num = weechat_buffer_get_integer(ptr_channel->buffer, "number"); + snprintf(buf, sizeof(buf), "/buffer %d", num); + weechat_command(ptr_account->buffer, buf); } + weechat_string_free_split(jids); } return WEECHAT_RC_OK; @@ -517,14 +606,20 @@ void command__init() N_("list" " || add " " || connect " + " || disconnect " + " || reconnect " " || delete "), - N_(" list: list accounts\n" - " add: add a xmpp account\n" - "connect: connect to a xmpp account\n" - " delete: delete a xmpp account\n"), + N_(" list: list accounts\n" + " add: add a xmpp account\n" + " connect: connect to a xmpp account\n" + "disconnect: disconnect from a xmpp account\n" + " reconnect: reconnect an xmpp account\n" + " delete: delete a xmpp account\n"), "list" " || add %(xmpp_account)" " || connect %(xmpp_account)" + " || disconnect %(xmpp_account)" + " || reconnect %(xmpp_account)" " || delete %(xmpp_account)", &command__account, NULL, NULL); if (!hook) From 09ce7489b73f12d120c785965309d13c199e7a83 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 4 Jul 2021 06:39:30 +0100 Subject: [PATCH 096/118] show enters and leaves --- README.org | 9 +- channel.c | 62 +++++++++++++ channel.h | 4 + connection.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++---- user.c | 20 +++++ user.h | 4 + 6 files changed, 328 insertions(+), 19 deletions(-) diff --git a/README.org b/README.org index 325b96b..6a17567 100644 --- a/README.org +++ b/README.org @@ -47,7 +47,7 @@ - glib (dynamic, dependency of libomemo) - sqlite (dynamic, dependency of libomemo/axc) - libsignal-protocol-c (dynamic, dependency of axc) - - weechat (>= v2.5) + - weechat (>= v3.0) .. or just use the guix spec in .envrc @@ -101,13 +101,15 @@ * [X] Sending * [ ] [#B] Edits * [ ] [#B] Handle errors gracefully - * [ ] [#B] Presence/nicklist + * [X] [#B] Presence/nicklist * [X] [#B] Enters - * [ ] [#B] Leaves + * [X] [#B] Leaves * [X] [#B] Tracking * [X] [#B] Set/show topic * [ ] OMEMO (libsignal-protocol-c / axc) * [ ] Presence + * [X] Disco + * [ ] Disco response * [ ] Messages * [ ] MUC PMs * [ ] Send typing notifications @@ -117,6 +119,7 @@ * [ ] PGP (libgpgme) ** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) + * [ ] Absorb libomemo / axc, and drop glib * Contributing diff --git a/channel.c b/channel.c index 0379285..4732b98 100644 --- a/channel.c +++ b/channel.c @@ -601,6 +601,68 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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(channel->buffer, "%s%s entered", + weechat_prefix("join"), + jid_resource); + else + weechat_printf(channel->buffer, "%s%s (%s) entered", + weechat_prefix("join"), + xmpp_jid_bare(account->context, user->id), + xmpp_jid_resource(account->context, user->id)); + + return member; +} + +struct t_channel_member *channel__member_search(struct t_channel *channel, + const char *id) +{ + struct t_channel_member *ptr_member; + + if (!channel || !id) + return NULL; + + for (ptr_member = channel->members; ptr_member; + ptr_member = ptr_member->next_member) + { + if (weechat_strcasecmp(ptr_member->id, id) == 0) + return ptr_member; + } + + return NULL; +} + +struct t_channel_member *channel__remove_member(struct t_account *account, + struct t_channel *channel, + const char *id) +{ + struct t_channel_member *member; + struct t_user *user; + + user = user__search(account, id); + if (user) + user__nicklist_remove(account, channel, user); + + member = channel__member_search(channel, id); + if (member) + channel__member_free(channel, member); + + 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(channel->buffer, "%s%s left", + weechat_prefix("quit"), + jid_resource); + else + weechat_printf(channel->buffer, "%s%s (%s) left", + weechat_prefix("quit"), + xmpp_jid_bare(account->context, user->id), + xmpp_jid_resource(account->context, user->id)); + return member; } diff --git a/channel.h b/channel.h index 4877714..ed9ca23 100644 --- a/channel.h +++ b/channel.h @@ -120,6 +120,10 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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); + void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body); diff --git a/connection.c b/connection.c index 62190d1..0dac172 100644 --- a/connection.c +++ b/connection.c @@ -21,7 +21,7 @@ void connection__init() xmpp_initialize(); } -int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +int connection__version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { xmpp_stanza_t *reply, *query, *name, *version, *text; const char *ns; @@ -72,37 +72,51 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) return 1; } -int presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { (void) conn; struct t_account *account = (struct t_account *)userdata; struct t_user *user; struct t_channel *channel; - const char *from, *from_bare; + xmpp_stanza_t *iq__x, *iq__x__item; + const char *from, *from_bare, *role = NULL, *affiliation = NULL; from = xmpp_stanza_get_from(stanza); if (from == NULL) return 1; from_bare = xmpp_jid_bare(account->context, from); + iq__x = xmpp_stanza_get_child_by_name_and_ns( + stanza, "x", "http://jabber.org/protocol/muc#user"); + if (iq__x) + { + iq__x__item = xmpp_stanza_get_child_by_name(iq__x, "item"); + role = xmpp_stanza_get_attribute(iq__x__item, "role"); + affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation"); + } user = user__search(account, from); if (!user) user = user__new(account, from, from); channel = channel__search(account, from_bare); - if (!channel) - channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - channel__add_member(account, channel, from); - - weechat_printf(account->buffer, "%s%s (%s) presence", - weechat_prefix("action"), - user->name, user->profile.display_name); + if (!iq__x) + { + if (!channel) + channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + channel__add_member(account, channel, from); + } + else if (channel) + { + if (weechat_strcasecmp(role, "none") == 0) + channel__remove_member(account, channel, from); + channel__add_member(account, channel, from); + } return 1; } -int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { (void) conn; @@ -184,6 +198,203 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) return 1; } +#include +int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +{ + (void) conn; + + struct t_account *account = (struct t_account *)userdata; + xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; + char client_name[64], *node; + static struct utsname osinfo; + + reply = xmpp_stanza_reply(stanza); + xmpp_stanza_set_type(reply, "result"); + + query = xmpp_stanza_get_child_by_name_and_ns( + stanza, "query", "http://jabber.org/protocol/disco#info"); + node = xmpp_stanza_get_attribute(query, "node"); + xmpp_stanza_set_attribute(reply, "id", node); + + identity = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(identity, "identity"); + xmpp_stanza_set_attribute(identity, "category", "client"); + snprintf(client_name, sizeof(client_name), + "weechat %s", weechat_info_get("version", NULL)); + xmpp_stanza_set_attribute(identity, "name", client_name); + xmpp_stanza_set_attribute(identity, "type", "pc"); + xmpp_stanza_add_child(query, identity); + xmpp_stanza_release(identity); + +#define FEATURE(ns) \ + 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); \ + xmpp_stanza_release(feature); + + FEATURE("http://jabber.org/protocol/caps"); + FEATURE("http://jabber.org/protocol/disco#info"); + FEATURE("http://jabber.org/protocol/disco#items"); + FEATURE("http://jabber.org/protocol/muc"); + FEATURE("eu.siacs.conversations.axolotl.devicelist"); + FEATURE("eu.siacs.conversations.axolotl.devicelist+notify"); +#undef FEATURE + + 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"); + + if (uname(&osinfo) >= 0) + { + osinfo.machine; + } + + { + 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); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "urn:xmpp:dataforms:softwareinfo"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "ip_version"); + xmpp_stanza_set_attribute(field, "type", "text-multi"); + + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "ipv4"); + 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); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "ipv6"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "os"); + + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, osinfo.sysname); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "os_version"); + + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, osinfo.release); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "software"); + + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "weechat"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "software_version"); + + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, weechat_info_get("version", NULL)); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + xmpp_stanza_add_child(query, x); + xmpp_stanza_release(x); + + xmpp_stanza_add_child(reply, query); + + xmpp_send(conn, reply); + xmpp_stanza_release(reply); + + return 1; +} + void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, int error, xmpp_stream_error_t *stream_error, void *userdata) @@ -197,9 +408,14 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text; char cap_hash[28+1] = {0}; - xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, account); - xmpp_handler_add(conn, presence_handler, NULL, "presence", NULL, account); - xmpp_handler_add(conn, message_handler, NULL, "message", /*type*/ NULL, account); + 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", "get", account); /* Send initial so that we appear online to contacts */ pres = xmpp_presence_new(account->context); @@ -240,7 +456,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, } } -char* rand_string(int length) +char* connection__rand_string(int length) { char *string = malloc(length); srand(time(NULL)); @@ -262,7 +478,7 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, const char *resource = account_resource(account); if (!(resource && strlen(resource))) { - char *const rand = rand_string(8); + char *const rand = connection__rand_string(8); char ident[64] = {0}; snprintf(ident, sizeof(ident), "weechat.%s", rand); free(rand); diff --git a/user.c b/user.c index b6d740c..4a9a654 100644 --- a/user.c +++ b/user.c @@ -115,6 +115,26 @@ void user__nicklist_add(struct t_account *account, 1); } +void user__nicklist_remove(struct t_account *account, + struct t_channel *channel, + struct t_user *user) +{ + struct t_gui_nick_group *ptr_group; + struct t_gui_buffer *ptr_buffer; + char *name = user->profile.display_name; + if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name), + channel->id) == 0) + name = xmpp_jid_resource(account->context, name); + + ptr_buffer = channel ? channel->buffer : account->buffer; + + ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, + user->is_away ? + "+" : "..."); + weechat_nicklist_remove_nick(ptr_buffer, + weechat_nicklist_search_nick(ptr_buffer, ptr_group, name)); +} + struct t_user *user__new(struct t_account *account, const char *id, const char *display_name) { diff --git a/user.h b/user.h index 624aaf2..f90e535 100644 --- a/user.h +++ b/user.h @@ -75,4 +75,8 @@ void user__nicklist_add(struct t_account *account, struct t_channel *channel, struct t_user *user); +void user__nicklist_remove(struct t_account *account, + struct t_channel *channel, + struct t_user *user); + #endif /*WEECHAT_XMPP_USER_H*/ From 7c15319f50c366a4028df7ee5794d77ed12c6cd7 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 5 Jul 2021 01:31:57 +0100 Subject: [PATCH 097/118] begin scaffolding objects --- .dir-locals.el | 8 +- .envrc | 2 +- Makefile | 22 +- README.org | 2 +- command.c | 47 +- completion.c | 155 ++ completion.h | 10 + connection.c | 42 +- plugin.c | 4 +- plugin.h | 6 +- profanity | 3790 +++++++++++++++++++++++++++++++++++++++++++++++ result | 1 + xmpp/presence.c | 48 + xmpp/stanza.h | 12 + 14 files changed, 4113 insertions(+), 36 deletions(-) create mode 100644 completion.c create mode 100644 completion.h create mode 100644 profanity create mode 120000 result create mode 100644 xmpp/presence.c create mode 100644 xmpp/stanza.h diff --git a/.dir-locals.el b/.dir-locals.el index 89604c0..671bf21 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -9,8 +9,14 @@ (list (concat "-I" (expand-file-name "libstrophe" (projectile-project-root))) (concat "-I" (expand-file-name "json-c" (projectile-project-root)))))) (eval . (setq-local tags-table-list (expand-file-name ".git/tags" (projectile-project-root)))) + (eval . (setq-local gud-gdb-command-name + (string-join `("gdb" + "-ex 'handle SIGPIPE nostop noprint pass'" + ,(concat "--args weechat -a -P 'alias,buflist,exec,irc' -r '/plugin load " + (expand-file-name "xmpp.so" (projectile-project-root)) + "'")) + " "))) (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) (flycheck-clang-language-standard . "gnu99") (flycheck-checker . c/c++-clang) (projectile-project-compilation-cmd . "scan-build-3.8 make -j8"))) - diff --git a/.envrc b/.envrc index 0e1023d..1cb1c12 100644 --- a/.envrc +++ b/.envrc @@ -46,4 +46,4 @@ use_guix() export CC=gcc } -use guix --with-debug-info=weechat --with-debug-info=libstrophe +use guix --with-debug-info=weechat --with-debug-info=libstrophe gdb diff --git a/Makefile b/Makefile index 1ec5c26..0fa960d 100644 --- a/Makefile +++ b/Makefile @@ -13,16 +13,18 @@ PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib SRCS=plugin.c \ - account.c \ - buffer.c \ - channel.c \ - command.c \ - config.c \ - connection.c \ - input.c \ - message.c \ - omemo.c \ - user.c \ + account.c \ + buffer.c \ + channel.c \ + command.c \ + completion.c \ + config.c \ + connection.c \ + input.c \ + message.c \ + omemo.c \ + user.c \ + xmpp/presence.c \ DEPS=axc/build/libaxc.a OBJS=$(subst .c,.o,$(SRCS)) diff --git a/README.org b/README.org index 6a17567..1392315 100644 --- a/README.org +++ b/README.org @@ -74,7 +74,7 @@ since part of weechat and it's default plugins use SIGPIPE as control. I have no real requests for style of pull requests besides a wish that - you keep vaguely to the style I have adopted for this project. + you keep vaguely to the indentation style I use for this project. Happy coding! diff --git a/command.c b/command.c index dfa1c0f..47547db 100644 --- a/command.c +++ b/command.c @@ -596,6 +596,42 @@ int command__me(const void *pointer, void *data, return WEECHAT_RC_OK; } +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; + xmpp_stanza_t *stanza; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + stanza = xmpp_stanza_new_from_string(ptr_account->context, + argv_eol[0]); + if (!stanza) + return WEECHAT_RC_ERROR; + + xmpp_send(ptr_account->connection, stanza); + xmpp_stanza_release(stanza); + } + + return WEECHAT_RC_OK; +} + void command__init() { struct t_hook *hook; @@ -641,7 +677,7 @@ void command__init() N_("jid: jid to target"), NULL, &command__open, NULL, NULL); if (!hook) - weechat_printf(NULL, "Failed to setup command /chat"); + weechat_printf(NULL, "Failed to setup command /open"); hook = weechat_hook_command( "me", @@ -651,4 +687,13 @@ void command__init() NULL, &command__me, NULL, NULL); if (!hook) weechat_printf(NULL, "Failed to setup command /me"); + + hook = weechat_hook_command( + "xml", + N_("send a raw xml stanza"), + N_(""), + N_("stanza: xml to send"), + NULL, &command__xml, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /xml"); } diff --git a/completion.c b/completion.c new file mode 100644 index 0000000..7a98152 --- /dev/null +++ b/completion.c @@ -0,0 +1,155 @@ +// 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 + +#include "plugin.h" +#include "config.h" +#include "account.h" +#include "channel.h" +#include "user.h" +#include "buffer.h" +#include "completion.h" + +void completion__channel_nicks_add_speakers(struct t_gui_completion *completion, + struct t_account *account, + struct t_channel *channel, + int highlight) +{ + struct t_user *user; + const char *member; + int list_size, i; + + if (channel->members_speaking[highlight]) + { + list_size = weechat_list_size(channel->members_speaking[highlight]); + for (i = 0; i < list_size; i++) + { + member = weechat_list_string ( + weechat_list_get(channel->members_speaking[highlight], i)); + if (member) + { + user = user__search(account, member); + if (user) + weechat_hook_completion_list_add(completion, + user->profile.display_name, + 1, WEECHAT_LIST_POS_BEGINNING); + } + } + } +} + +int completion__channel_nicks_cb(const void *pointer, void *data, + const char *completion_item, + 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; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) completion_item; + + ptr_account = NULL; + ptr_channel = NULL; + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (ptr_channel) + { + 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) + { + ptr_user = user__search(ptr_account, ptr_member->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) + { + 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) + { + 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, + 1, WEECHAT_LIST_POS_END); + break; + } + } + + return WEECHAT_RC_OK; +} + +int completion__accounts_cb(const void *pointer, void *data, + const char *completion_item, + 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 (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + weechat_hook_completion_list_add(completion, account_jid(ptr_account), + 0, WEECHAT_LIST_POS_SORT); + } + + return WEECHAT_RC_OK; +} + +void completion__init() +{ + struct t_config_option *option; + const char *default_template; + + + weechat_hook_completion("nick", + N_("nicks of current Slack channel"), + &completion__channel_nicks_cb, + NULL, NULL); + + weechat_hook_completion("account", + N_("xmpp accounts"), + &completion__accounts_cb, + NULL, NULL); + + option = weechat_config_get("weechat.completion.default_template"); + default_template = weechat_config_string(option); + if (!weechat_strcasestr(default_template, "%(account)")) + { + size_t length = snprintf(NULL, 0, "%s|%s", + default_template, + "%(account)") + 1; + char *new_template = malloc(length); + snprintf(new_template, length, "%s|%s", + default_template, + "%(account)"); + weechat_config_option_set(option, new_template, 1); + free(new_template); + } +} diff --git a/completion.h b/completion.h new file mode 100644 index 0000000..da99b23 --- /dev/null +++ b/completion.h @@ -0,0 +1,10 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_COMPLETION_H_ +#define _WEECHAT_XMPP_COMPLETION_H_ + +void completion__init(); + +#endif /*WEECHAT_XMPP_COMPLETION_H*/ diff --git a/connection.c b/connection.c index 0dac172..d224586 100644 --- a/connection.c +++ b/connection.c @@ -6,15 +6,18 @@ #include #include #include +#include #include #include #include "plugin.h" +#include "xmpp/stanza.h" #include "config.h" #include "account.h" #include "user.h" #include "channel.h" #include "connection.h" +#include "omemo.h" void connection__init() { @@ -27,7 +30,7 @@ int connection__version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * const char *ns; struct t_account *account = (struct t_account *)userdata; const char *weechat_name = "weechat"; - const char *weechat_version = weechat_info_get("version", NULL); + char *weechat_version = weechat_info_get("version", NULL); weechat_printf(NULL, "Received version request from %s", xmpp_stanza_get_from(stanza)); @@ -66,8 +69,8 @@ int connection__version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * xmpp_send(conn, reply); xmpp_stanza_release(reply); - if (version) - free (version); + if (weechat_version) + free(weechat_version); return 1; } @@ -198,16 +201,18 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * return 1; } -#include int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { (void) conn; struct t_account *account = (struct t_account *)userdata; xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; - char client_name[64], *node; + const char *node; static struct utsname osinfo; + char *client_name = weechat_string_eval_expression("weechat ${info:version}", + NULL, NULL, NULL); + reply = xmpp_stanza_reply(stanza); xmpp_stanza_set_type(reply, "result"); @@ -219,8 +224,6 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd identity = xmpp_stanza_new(account->context); xmpp_stanza_set_name(identity, "identity"); xmpp_stanza_set_attribute(identity, "category", "client"); - snprintf(client_name, sizeof(client_name), - "weechat %s", weechat_info_get("version", NULL)); xmpp_stanza_set_attribute(identity, "name", client_name); xmpp_stanza_set_attribute(identity, "type", "pc"); xmpp_stanza_add_child(query, identity); @@ -246,9 +249,10 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd xmpp_stanza_set_ns(x, "jabber:x:data"); xmpp_stanza_set_attribute(x, "type", "result"); - if (uname(&osinfo) >= 0) + if (uname(&osinfo) < 0) { - osinfo.machine; + *osinfo.sysname = 0; + *osinfo.release = 0; } { @@ -392,6 +396,8 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd xmpp_send(conn, reply); xmpp_stanza_release(reply); + free(client_name); + return 1; } @@ -405,7 +411,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, (void)stream_error; if (status == XMPP_CONN_CONNECT) { - xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text; + xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, **children; char cap_hash[28+1] = {0}; xmpp_handler_add(conn, connection__version_handler, @@ -418,8 +424,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, NULL, "iq", "get", account); /* Send initial so that we appear online to contacts */ - pres = xmpp_presence_new(account->context); - xmpp_stanza_set_from(pres, account_jid(account)); + children = malloc(sizeof(*children) * (2 + 1)); pres__c = xmpp_stanza_new(account->context); xmpp_stanza_set_name(pres__c, "c"); @@ -428,8 +433,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_stanza_set_attribute(pres__c, "node", "http://weechat.org"); snprintf(cap_hash, sizeof(cap_hash), "%027ld=", time(NULL)); xmpp_stanza_set_attribute(pres__c, "ver", cap_hash); - xmpp_stanza_add_child(pres, pres__c); - xmpp_stanza_release(pres__c); + children[0] = pres__c; pres__status = xmpp_stanza_new(account->context); xmpp_stanza_set_name(pres__status, "status"); @@ -439,9 +443,12 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_stanza_add_child(pres__status, pres__status__text); xmpp_stanza_release(pres__status__text); - xmpp_stanza_add_child(pres, pres__status); - xmpp_stanza_release(pres__status); + children[1] = pres__status; + children[2] = NULL; + pres = stanza__presence(account->context, NULL, + children, NULL, strdup(account_jid(account)), + NULL, NULL); xmpp_send(conn, pres); xmpp_stanza_release(pres); @@ -450,8 +457,9 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, weechat_string_dyn_concat(command, account_autojoin(account), -1); weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); + + omemo__init(account); } else { - //weechat_printf(account->buffer, "DEBUG: disconnected"); //xmpp_stop(account->context); } } diff --git a/plugin.c b/plugin.c index 3905393..85ed513 100644 --- a/plugin.c +++ b/plugin.c @@ -14,7 +14,7 @@ #include "connection.h" #include "command.h" #include "buffer.h" -//#include "xmpp-completion.h" +#include "completion.h" WEECHAT_PLUGIN_NAME(WEECHAT_XMPP_PLUGIN_NAME); @@ -46,7 +46,7 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) command__init(); - //completion__init(); + completion__init(); weechat_xmpp_process_timer = weechat_hook_timer(TIMER_INTERVAL_SEC * 1000, 0, 0, &account__timer_cb, diff --git a/plugin.h b/plugin.h index 27e196f..6711120 100644 --- a/plugin.h +++ b/plugin.h @@ -2,8 +2,8 @@ // 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/. -#ifndef _WEECHAT_XMPP_H_ -#define _WEECHAT_XMPP_H_ +#ifndef _WEECHAT_XMPP_PLUGIN_H_ +#define _WEECHAT_XMPP_PLUGIN_H_ #define weechat_plugin weechat_xmpp_plugin #define WEECHAT_XMPP_PLUGIN_NAME "xmpp" @@ -12,4 +12,4 @@ extern struct t_weechat_plugin *weechat_xmpp_plugin; -#endif /*WEECHAT_XMPP_H*/ +#endif /*WEECHAT_XMPP_PLUGIN_H*/ diff --git a/profanity b/profanity new file mode 100644 index 0000000..1f43cca --- /dev/null +++ b/profanity @@ -0,0 +1,3790 @@ +02/07/2021 22:30:43: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +02/07/2021 22:30:43: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +02/07/2021 22:31:56: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +02/07/2021 22:32:10: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:32:10: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:32:24: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +02/07/2021 22:32:56: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:32:57: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:33:10: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:33:12: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:33:12: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:33:14: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:33:17: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:33:20: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:33:20: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:33:29: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:33:41: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:33:44: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:33:44: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:33:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +02/07/2021 22:34:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:34:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:34:31: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +02/07/2021 22:34:33: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:34:33: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:34:36: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:34:38: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:34:38: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:35:14: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:35:16: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:35:16: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:35:18: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:35:21: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +02/07/2021 22:35:21: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +02/07/2021 22:38:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/ellenor@umbrellix.net +02/07/2021 22:38:29: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/ellenor@umbrellix.net +02/07/2021 22:38:54: prof: WRN: Generated sha-1 does not match given: +02/07/2021 22:38:54: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +02/07/2021 22:38:54: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +02/07/2021 22:39:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/ellenor@umbrellix.net +02/07/2021 22:39:44: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:39:53: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:39:57: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/Sarah Malik +02/07/2021 22:40:05: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/Sarah Malik +02/07/2021 22:46:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:46:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:46:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:46:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:46:10: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy +02/07/2021 22:46:51: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:47:05: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:47:10: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:47:20: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:47:37: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:47:50: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:48:09: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:49:08: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:49:28: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:49:48: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:50:32: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:54:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +02/07/2021 22:55:15: prof: ERR: IQ error received, id: NmIzOTExNmUtMzk0Yy00YjVlLWEwMjEtYjYzNzBmODhkYzI0ZDlmYTMxMmYzMDZjN2U1MTY1ODY2Yzk0YjA5OGU3NDhmNDM4MjBhOTNjYjliNDlhYjFhY2Q3ZWNhYTc5OTQ0ZA==, error: Request has timed out +02/07/2021 22:55:15: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +02/07/2021 22:56:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/qy +02/07/2021 22:57:01: prof: ERR: Message received without body for room: hmm@conference.hmm.st/acdw +02/07/2021 22:57:46: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:58:10: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:58:15: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:58:18: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:58:32: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:58:33: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:58:48: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +02/07/2021 22:58:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +02/07/2021 22:58:57: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:59:23: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 22:59:40: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:05: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:19: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:21: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:27: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:38: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:48: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:53: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:00:56: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:01:12: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:01:27: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:01:36: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:02:12: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:02:15: prof: ERR: Message received without body for room: hmm@conference.hmm.st/wgreenhouse +02/07/2021 23:02:23: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:02:54: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:03:01: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:03:44: prof: ERR: IQ error received, id: MmJhNmE2MWUtNzQzNi00MGNjLWI4MGYtZTIwMWNiYjhmYjk0NTdlYWI3NTQ1MTUyMmMwOGQ1NTA4OTM3OTcyM2FiM2I5ZmI2ZjVjYzE5NTlhOWYzZTFkNzllMjVkMGMxMDlhYg==, error: Request has timed out +02/07/2021 23:03:44: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +02/07/2021 23:03:45: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:04:03: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:04:22: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:04:26: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:04:35: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:04:46: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:05:04: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:05:43: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:05:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/elfchen +02/07/2021 23:05:59: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:06:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/elfchen +02/07/2021 23:06:06: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:06:22: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:06:44: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:06:46: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:06:55: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:07:00: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:07:04: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:07:13: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:07:35: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:07:44: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:07:52: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +02/07/2021 23:08:01: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:08:23: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:08:27: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:08:31: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:09:07: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:10:51: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:10:52: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:11:18: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:11:27: prof: ERR: Message received without body for room: chat@dino.im/512bit +02/07/2021 23:11:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit +02/07/2021 23:11:32: prof: ERR: Message received without body for room: chat@dino.im/512bit +02/07/2021 23:11:32: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit +02/07/2021 23:11:46: prof: ERR: Message received without body for room: chat@dino.im/512bit +02/07/2021 23:11:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit +02/07/2021 23:12:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:12:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:12:18: prof: ERR: Message received without body for room: chat@dino.im/512bit +02/07/2021 23:12:18: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit +02/07/2021 23:12:19: prof: ERR: Message received without body for room: chat@dino.im/512bit +02/07/2021 23:12:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit +02/07/2021 23:12:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:12:42: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:13:11: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:13:15: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:13:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:13:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +02/07/2021 23:13:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +02/07/2021 23:13:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:13:40: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:13:53: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:13:57: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:13:57: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:14:00: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:14:07: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +02/07/2021 23:14:07: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:14:10: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +02/07/2021 23:14:38: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:14:41: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:14:42: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:14:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:14:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:15:19: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:15:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:15:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:16:11: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:16:15: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:16:29: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:16:37: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:16:50: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:16:57: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:17:06: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:17:30: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:17:58: prof: WRN: Generated sha-1 does not match given: +02/07/2021 23:17:58: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +02/07/2021 23:17:58: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +02/07/2021 23:20:55: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:22:47: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:23:46: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:23:49: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:24:35: prof: ERR: IQ error received, id: ODE1ZWRmM2EtYjBhNi00M2M0LWFjYzctMjMwMmVhYTVmMzY3NzMyMGY1NjBjYjBiNzRkMWI2NGRhOTA3MmY0ZmUxNWQyY2Q4MWY2ZmZjNmI4NTdjOGZiZTAzYTEzNmFjN2UzYQ==, error: Request has timed out +02/07/2021 23:24:35: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +02/07/2021 23:26:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:26:10: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:26:11: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:26:17: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:27:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:27:55: prof: WRN: Generated sha-1 does not match given: +02/07/2021 23:27:55: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +02/07/2021 23:27:55: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +02/07/2021 23:29:08: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:30:35: prof: WRN: Generated sha-1 does not match given: +02/07/2021 23:30:35: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +02/07/2021 23:30:35: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +02/07/2021 23:32:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:38:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:38:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:43:26: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:45:43: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani +02/07/2021 23:45:51: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani +02/07/2021 23:45:57: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani +02/07/2021 23:46:11: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani +02/07/2021 23:46:32: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:46:49: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:46:56: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:50:44: prof: ERR: IQ error received, id: MWIwOWRhZDItNjZlYy00OTRmLWIyMzktNzIwNTYyMWRiZjhiNDMzYTg2MmFiZGE0NjNkODIyNGEzZWFkMGE0ZTIyNTY4MTQwMzdjODMzNDAxZDI3YzIzMWY3YTcwMjI0NDIxOA==, error: Request has timed out +02/07/2021 23:50:44: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +02/07/2021 23:51:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:51:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:52:17: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:52:53: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:52:55: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:52:59: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:53:16: prof: WRN: OMEMO: received a message with no corresponding key +02/07/2021 23:53:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:54:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:54:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:56:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:56:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:56:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:56:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:57:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:57:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:57:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:58:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:58:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:58:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:59:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:59:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:59:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +02/07/2021 23:59:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:00:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:00:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:00:10: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:00:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:00:43: prof: WRN: Generated sha-1 does not match given: +03/07/2021 00:00:43: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 00:00:43: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 00:00:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:00:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:01:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:01:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:01:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:01:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:12:58: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 00:13:04: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 00:13:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 00:14:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:14:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:14:26: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 00:14:31: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:14:32: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:14:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:14:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:15:41: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:15:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:19:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:20:44: prof: WRN: Generated sha-1 does not match given: +03/07/2021 00:20:44: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 00:20:44: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 00:33:17: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:33:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +03/07/2021 00:35:31: prof: ERR: IQ error received, id: Mjk0NWVmMjktNTgxZC00ZGExLWJkMjMtN2FkMWQzZDBhMDY1MDY3YjZkMmFiNjJkMmJkY2EyYTEwMjg1MTljM2MyYjRiZWUwYmYxYTFhYmZiNjY5N2M0MmY0NzY2MTE2YjEwMw==, error: Request has timed out +03/07/2021 00:35:31: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 00:40:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 00:55:31: prof: ERR: IQ error received, id: ZWM3NjA3NmMtMjgwNi00NDgzLWFmMTItYjFiYzY1NzM3ODAyZjZhYzYzOGZmZmVhODg5ZjMyOWI5ZmIwYWFmNmNiMGM3OTQ1YzQwOGQ3ZmIzYTcxZTI0NDAxN2U1MDA1Zjg1NQ==, error: Request has timed out +03/07/2021 00:55:31: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 01:01:38: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:03:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:03:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:03:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:04:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:04:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:10:14: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +03/07/2021 01:11:18: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +03/07/2021 01:15:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/qy +03/07/2021 01:20:30: prof: ERR: IQ error received, id: MTBkOTFmYzUtNzAwZi00MDFjLWFlNTUtNTlkNWI3Zjk0Nzk2OTk5MjQwMzQyZWE0NDkzZGRhYTc4YzRlNWEzOGQ2OGQ1MWQ1YmRkNTk4YjU5MTlhZmY3ZGM4ODYyNzJhZTFlZg==, error: Request has timed out +03/07/2021 01:20:30: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 01:31:05: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:31:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:32:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:33:04: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:34:09: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:34:28: prof: ERR: Message received without body for room: chat@dino.im/512bit +03/07/2021 01:34:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit +03/07/2021 01:36:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:36:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:37:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:37:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:38:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/jcarloss +03/07/2021 01:38:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:39:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:39:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:39:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:39:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:44:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:44:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:44:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:44:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:45:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:45:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 01:51:25: prof: ERR: Message received without body for room: hmm@conference.hmm.st/ben +03/07/2021 01:52:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +03/07/2021 01:52:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 01:52:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 01:52:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 01:54:59: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 01:55:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 01:55:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 02:01:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 02:01:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 02:09:28: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris +03/07/2021 02:11:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris +03/07/2021 02:23:53: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +03/07/2021 02:23:55: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +03/07/2021 02:34:07: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:34:14: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:34:16: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:34:19: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:34:20: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:34:32: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:34:36: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 02:56:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 02:58:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 02:58:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 02:58:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:08:26: prof: WRN: Generated sha-1 does not match given: +03/07/2021 03:08:26: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 03:08:26: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 03:08:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:08:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:09:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:09:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:09:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:09:59: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 03:26:03: prof: ERR: IQ error received, id: YmIxMWEwODgtNjZkYS00ZmFjLWI1NWUtYTBiMTg3NjE0ZjkyMjg5MmE0ODM3YmY1ZjJiMTI1MzU5ZWVmMTc0ZDFhMjRhNjBmNTljMzNmOGE4OWNkNmVkYWNmNWFkNWVmNzY2Ng==, error: Request has timed out +03/07/2021 03:26:03: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 03:39:28: prof: WRN: Generated sha-1 does not match given: +03/07/2021 03:39:28: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 03:39:28: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 03:50:34: prof: ERR: IQ error received, id: OGIwZDY5NTYtNTc5NC00MDdiLTkzZTItNWIwYTdmNWFkNWYxZGUyZWEzMzU4NTZhZjc3MDcxYzU5YWZjNWY4YTc2MTljZWU1ZWMyYjYzMTJmZDUwMWY2NGI5YmI0NjRlNjI2NQ==, error: Request has timed out +03/07/2021 03:50:34: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 03:59:27: prof: WRN: Generated sha-1 does not match given: +03/07/2021 03:59:27: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 03:59:27: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 04:17:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:22:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:24:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:28:17: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/timothy +03/07/2021 04:30:39: prof: WRN: Generated sha-1 does not match given: +03/07/2021 04:30:39: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 04:30:39: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 04:37:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:38:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:38:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:38:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:38:35: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:46:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou +03/07/2021 04:46:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:49:24: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 +03/07/2021 04:49:25: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +03/07/2021 04:49:25: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 +03/07/2021 04:50:42: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +03/07/2021 04:50:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:50:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 04:51:17: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +03/07/2021 04:53:20: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +03/07/2021 04:53:54: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +03/07/2021 04:54:54: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +03/07/2021 05:09:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:10:09: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:10:09: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Ge0rG +03/07/2021 05:10:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:10:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:10:31: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:10:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:11:04: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:11:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:11:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:11:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:12:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:12:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:12:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:13:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:13:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:14:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:15:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:18:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:18:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:18:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:18:59: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:19:10: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:19:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Ge0rG +03/07/2021 05:20:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:20:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:22:38: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:22:42: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:23:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:23:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:23:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:24:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:24:28: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:29:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:32:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:37:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 05:38:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 05:39:09: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 05:44:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Axel +03/07/2021 05:49:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:49:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:50:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 05:53:04: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 05:53:52: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 05:53:58: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 05:54:00: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 05:54:26: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 05:54:49: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 05:55:30: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:08:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 06:09:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 06:09:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 06:09:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 06:09:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 06:10:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +03/07/2021 06:29:08: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:29:08: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:29:10: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:29:29: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:29:32: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:29:46: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:29:54: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:30:11: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:30:14: prof: ERR: Message received without body for room: support@room.pix-art.de/strar +03/07/2021 06:47:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:47:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:47:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:48:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:48:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:48:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:48:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:51:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 06:52:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:52:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:52:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:52:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:52:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 06:53:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 06:56:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 07:07:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 07:09:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:09:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:09:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:10:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:10:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:10:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:10:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:12:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:14:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:19:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:25:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:25:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:26:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:26:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:26:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:27:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:28:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:28:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:28:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:29:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:30:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 07:30:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:30:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:30:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:31:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:31:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:31:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:31:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:32:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:32:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 07:33:19: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn +03/07/2021 07:36:43: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn +03/07/2021 07:36:44: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn +03/07/2021 07:37:41: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn +03/07/2021 07:37:41: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn +03/07/2021 07:37:49: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +03/07/2021 07:37:55: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +03/07/2021 07:41:19: prof: WRN: Generated sha-1 does not match given: +03/07/2021 07:41:19: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 07:41:19: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 07:47:11: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +03/07/2021 07:48:25: prof: ERR: Message received without body for room: support@room.pix-art.de/Chris +03/07/2021 07:49:37: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +03/07/2021 07:49:51: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +03/07/2021 07:50:19: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +03/07/2021 08:00:50: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke +03/07/2021 08:01:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:01:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:01:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:04:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:07:05: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 08:07:06: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 08:07:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 08:09:06: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 08:10:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:10:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:10:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:10:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:10:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 08:10:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:10:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:10:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:10:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 08:10:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 08:10:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 08:10:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 08:10:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 08:11:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 08:11:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:11:21: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 08:11:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:11:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:11:23: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +03/07/2021 08:11:28: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +03/07/2021 08:17:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:17:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:17:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:20:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:20:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:21:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:21:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:21:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:21:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:21:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:21:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:22:05: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 08:22:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 08:22:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:22:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:23:54: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 08:23:54: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 08:24:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:24:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:25:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:25:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:25:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mathieui +03/07/2021 08:25:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:25:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:26:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:26:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:26:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:26:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:26:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:26:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:26:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:26:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:26:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:26:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:27:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:27:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:27:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:27:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:27:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:27:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:27:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:27:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:27:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:27:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:27:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:28:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:28:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:28:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:28:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:28:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:28:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:28:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:28:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:29:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:29:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:29:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:29:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:29:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:29:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:29:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:29:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:29:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:30:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:30:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:30:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:30:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:31:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:31:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:31:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:32:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:32:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:32:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:32:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:32:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:32:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:32:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:32:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:32:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:34:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:34:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:34:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:34:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:34:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:34:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 08:35:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:35:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:36:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:37:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:37:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:38:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:38:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:38:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:38:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:38:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:39:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:39:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:39:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:39:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:39:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 08:39:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:40:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:43:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:43:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:43:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:43:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:46:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:46:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:46:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:46:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:46:46: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 08:46:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:46:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 08:47:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:47:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:47:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:48:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:48:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 08:51:07: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +03/07/2021 08:53:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:54:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 08:54:47: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:54:56: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:55:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:55:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:55:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 08:56:43: prof: WRN: Generated sha-1 does not match given: +03/07/2021 08:56:43: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 08:56:43: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 08:56:53: prof: WRN: Generated sha-1 does not match given: +03/07/2021 08:56:53: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 08:56:53: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 09:00:29: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/werdan +03/07/2021 09:01:20: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lemoldu +03/07/2021 09:01:20: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lemoldu +03/07/2021 09:01:24: prof: WRN: Generated sha-1 does not match given: +03/07/2021 09:01:24: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 09:01:24: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 09:07:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 09:07:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 09:09:25: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 09:26:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 09:26:51: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 09:26:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 09:26:55: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 09:27:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 09:27:46: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +03/07/2021 09:27:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 09:27:49: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +03/07/2021 09:27:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 09:43:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 09:45:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 09:47:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +03/07/2021 09:52:19: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +03/07/2021 09:55:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 09:55:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 09:55:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 09:57:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 09:58:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 09:58:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 09:58:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:00:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:02:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:02:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:02:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:02:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:03:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:03:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:03:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:04:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:04:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:04:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:04:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:05:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:05:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:05:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:06:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:06:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:06:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:07:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:07:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:07:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:07:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:07:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:07:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:07:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:07:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:08:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:08:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:08:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:08:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:08:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:08:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:08:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:08:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:09:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:09:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:09:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:09:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:09:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:09:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:10:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:10:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:10:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:10:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:10:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:10:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:10:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:10:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:10:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:10:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:10:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:10:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:11:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:11:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:12:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:12:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:12:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:12:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:12:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:12:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:12:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:13:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:13:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:13:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:13:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:13:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:13:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:13:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:13:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:13:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:14:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:14:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:15:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:17:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:17:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:18:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:20:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:21:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:21:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:22:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:22:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:22:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:22:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:23:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:23:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:23:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/bronko +03/07/2021 10:23:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:23:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:23:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:23:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:23:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:23:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/bronko +03/07/2021 10:23:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/bronko +03/07/2021 10:23:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:23:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:23:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:24:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:24:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:24:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:25:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:25:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:25:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:25:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:25:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:25:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:25:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:26:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:26:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:26:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:26:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:26:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:26:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:27:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:27:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:27:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:27:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:27:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:27:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/matkor +03/07/2021 10:27:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:27:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/matkor +03/07/2021 10:27:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/matkor +03/07/2021 10:27:41: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/matkor +03/07/2021 10:28:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:28:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:30:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:32:36: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 10:32:39: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 10:33:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:34:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:34:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou +03/07/2021 10:35:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:35:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:36:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:36:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:36:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:37:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:37:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 10:37:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 10:37:12: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 10:37:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:37:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:37:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:37:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:38:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:38:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:38:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:38:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:38:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:38:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:38:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:40:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:40:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:40:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:41:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:41:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:42:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:42:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:42:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:42:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:43:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:44:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:44:15: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:44:17: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:20: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:26: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke +03/07/2021 10:44:27: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:32: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:35: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:35: prof: ERR: Message received without body for room: en@chat.404.city/BDFL +03/07/2021 10:44:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:45:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:46:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:46:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:46:31: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:46:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:46:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:46:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:46:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:47:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 10:47:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:48:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:48:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:48:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:48:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:48:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:48:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:48:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:49:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:49:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:49:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:49:51: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:50:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 10:50:56: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:51:02: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:51:40: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:51:42: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:51:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:51:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d +03/07/2021 10:52:20: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:54:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:55:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:55:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:55:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 10:56:48: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 10:58:22: prof: ERR: Message received without body for room: support@room.pix-art.de/Chris +03/07/2021 11:00:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 11:01:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:02:35: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:02:36: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:05:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 11:07:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 11:16:45: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:18:05: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 11:18:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 11:19:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:31:29: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 11:31:33: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 11:35:33: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:35:37: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:38:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:38:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:38:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:39:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:39:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:40:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:41:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:41:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:41:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:41:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:41:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:42:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:42:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:42:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:42:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:42:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:42:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:44:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:44:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:44:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:45:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:45:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:45:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:45:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:45:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:45:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:45:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:45:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:46:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:46:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:46:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:46:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:46:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:46:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:46:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:47:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:47:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +03/07/2021 11:47:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 11:47:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 11:47:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:47:31: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 11:47:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 11:47:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 11:47:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 11:47:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:48:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 11:48:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 11:48:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 11:48:31: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:48:41: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:48:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:48:47: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:24: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:40: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 11:49:41: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 11:49:43: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:44: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:49:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:50:18: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:50:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:54:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 11:54:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 11:55:23: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 11:55:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 11:55:34: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 11:55:45: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 11:56:16: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 11:56:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 12:00:36: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 12:00:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 12:02:17: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 12:02:21: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 12:02:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:02:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 12:04:22: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 12:04:24: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 12:04:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 12:07:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 12:09:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 12:10:48: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:11:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:11:56: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:13:05: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:16:51: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:17:03: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:17:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:18:14: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:18:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:18:34: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:18:36: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:18:36: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:18:38: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:18:38: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:18:41: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:18:44: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:18:47: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:18:49: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:18:54: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:18:58: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:19:04: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:19:22: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:19:36: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:19:41: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:19:48: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:19:53: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:19:57: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:20:02: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:20:08: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion +03/07/2021 12:21:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:22:09: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:22:53: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 12:28:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:28:30: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:28:31: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 12:28:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:28:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:28:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:30:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 12:36:21: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 12:36:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 12:36:22: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 12:36:23: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 12:36:23: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 12:36:24: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 12:47:31: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] +03/07/2021 12:47:31: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] +03/07/2021 12:47:31: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien +03/07/2021 12:53:37: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] +03/07/2021 12:53:38: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] +03/07/2021 12:53:38: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien +03/07/2021 12:54:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 12:54:10: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 12:57:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 13:05:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd +03/07/2021 13:08:43: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:09:07: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:14:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin +03/07/2021 13:14:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:14:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:14:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:14:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:14:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:15:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:15:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:16:01: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:16:11: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:16:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:16:59: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:17:21: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:17:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:17:21: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:17:29: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:17:44: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:17:59: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:18:37: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:19:03: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:19:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:19:28: prof: WRN: Generated sha-1 does not match given: +03/07/2021 13:19:28: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 13:19:28: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 13:19:38: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:20:02: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:20:21: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:20:26: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:20:31: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:20:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:20:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:21:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:21:09: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:21:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:21:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:22:26: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:22:38: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:23:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:23:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho +03/07/2021 13:24:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin +03/07/2021 13:24:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin +03/07/2021 13:24:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin +03/07/2021 13:24:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin +03/07/2021 13:24:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:24:40: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:24:43: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:25:11: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:25:12: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:25:16: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:26:50: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:26:52: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:26:52: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:26:59: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:27:20: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:27:25: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:27:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:27:29: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:27:34: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:27:39: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:28:04: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:28:08: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:28:22: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:28:41: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:28:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 13:28:48: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:28:53: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 13:29:15: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:29:36: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:30:07: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:30:30: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:30:48: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:33:26: prof: WRN: Generated sha-1 does not match given: +03/07/2021 13:33:26: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 13:33:26: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 13:43:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:43:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:44:43: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:45:01: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:45:16: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:45:19: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:45:43: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:45:47: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:46:02: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:46:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 13:46:23: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 13:46:31: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:46:53: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:47:23: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:47:58: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:48:11: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:49:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:49:15: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:49:33: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 13:49:37: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:49:40: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 13:49:59: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:50:06: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:52:11: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:52:31: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:54:19: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:57:37: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:57:47: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:58:02: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 13:58:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 13:58:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 13:58:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 13:58:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 13:58:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 13:59:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:00:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:01:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:02:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:02:26: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:02:35: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/nonion +03/07/2021 14:03:00: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 14:03:10: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 14:03:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:03:20: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:03:20: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:03:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:03:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:03:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:03:29: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:03:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:04:09: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 14:05:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:05:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:05:31: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:05:43: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:05:51: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:06:04: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:06:40: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 14:07:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 14:09:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:09:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:09:38: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:09:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:11:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:12:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:12:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:12:32: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:12:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:12:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:12:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:12:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:13:47: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 14:14:34: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:14:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:16:42: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 14:18:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:18:44: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:19:28: prof: WRN: Generated sha-1 does not match given: +03/07/2021 14:19:28: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 14:19:28: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 14:19:32: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 14:19:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +03/07/2021 14:20:01: prof: WRN: Generated sha-1 does not match given: +03/07/2021 14:20:01: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 14:20:01: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 14:20:35: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:20:42: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:20:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:20:48: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:22:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine +03/07/2021 14:23:13: prof: WRN: Generated sha-1 does not match given: +03/07/2021 14:23:13: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 14:23:13: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 14:24:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 14:24:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 14:28:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:28:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 14:34:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 14:36:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne +03/07/2021 14:36:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne +03/07/2021 14:37:30: prof: WRN: Generated sha-1 does not match given: +03/07/2021 14:37:30: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 14:37:30: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 14:41:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:41:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:41:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 14:42:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:42:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 14:42:44: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:42:52: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 14:42:52: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 14:43:34: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 14:43:37: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 14:44:35: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 14:44:37: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 14:44:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:44:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:45:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:45:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:49:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:49:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:49:58: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:50:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:50:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:50:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:50:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 14:50:42: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 14:50:43: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 14:51:50: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 14:52:31: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 14:52:53: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 14:54:41: prof: WRN: Generated sha-1 does not match given: +03/07/2021 14:54:41: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 14:54:41: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 14:54:46: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:55:31: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:55:59: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:56:13: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:56:22: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:56:39: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:56:55: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:57:30: prof: WRN: Generated sha-1 does not match given: +03/07/2021 14:57:30: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 14:57:30: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 14:58:03: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:59:25: prof: ERR: Message received without body for room: operators@muc.xmpp.org/melvo +03/07/2021 14:59:45: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 14:59:47: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 15:00:22: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 15:01:03: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 15:01:11: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 15:08:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:08:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 15:08:30: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:08:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 15:09:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:09:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +03/07/2021 15:09:40: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 15:14:28: prof: WRN: Generated sha-1 does not match given: +03/07/2021 15:14:28: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 15:14:28: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 15:14:41: prof: WRN: Generated sha-1 does not match given: +03/07/2021 15:14:41: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 15:14:41: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 15:17:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 15:17:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 15:17:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:19:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:20:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:21:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:24:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +03/07/2021 15:25:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +03/07/2021 15:25:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +03/07/2021 15:27:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 15:27:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 15:28:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:28:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:30:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:30:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 15:30:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 15:30:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 15:31:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 15:31:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 15:38:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 15:38:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 15:38:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 15:43:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:44:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:44:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 15:45:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:45:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:45:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:45:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:45:25: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:45:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:45:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:46:13: prof: WRN: Generated sha-1 does not match given: +03/07/2021 15:46:13: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 15:46:13: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 15:46:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:47:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:47:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:47:56: prof: ERR: Message received without body for room: emacs@salas.suchat.org/pranavats +03/07/2021 15:48:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:48:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:48:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:49:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:49:32: prof: WRN: Generated sha-1 does not match given: +03/07/2021 15:49:32: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 15:49:32: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 15:49:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:49:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:49:50: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 15:49:59: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 15:49:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:54:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 15:54:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 15:54:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 15:55:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 15:55:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 15:55:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 15:55:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:56:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 15:58:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 15:58:13: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 15:58:16: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:00:53: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:01:51: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:01:51: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:01:54: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:01:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:01:55: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:01:59: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:02:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 16:02:02: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 16:02:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 16:02:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 16:02:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 16:02:42: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +03/07/2021 16:03:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +03/07/2021 16:04:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 16:04:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +03/07/2021 16:07:30: prof: ERR: IQ error received, id: ZTg3Y2QyOTctOGZkNS00NTY4LTliN2UtNTExMzlhNjA5ZmJjNTAyZGVjNDMxZTA4NzFhZTc1NGUzMzkxMDJiOTYzZjgyNjQ1OGFiMWVjYjEwMDE0OTkwNDgyMGZmNDU4ODc4Ng==, error: Request has timed out +03/07/2021 16:07:30: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Locness3: +03/07/2021 16:16:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 16:16:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 16:16:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ +03/07/2021 16:16:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 16:16:38: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 16:16:51: prof: WRN: Generated sha-1 does not match given: +03/07/2021 16:16:51: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 16:16:51: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 16:19:56: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:19:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:21:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:21:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:22:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:22:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 16:24:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +03/07/2021 16:24:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +03/07/2021 16:33:34: prof: WRN: Generated sha-1 does not match given: +03/07/2021 16:33:34: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 16:33:34: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 16:36:17: prof: WRN: Generated sha-1 does not match given: +03/07/2021 16:36:17: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 16:36:17: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 16:38:46: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 16:38:46: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 16:40:15: prof: WRN: Generated sha-1 does not match given: +03/07/2021 16:40:15: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 16:40:15: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 16:41:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat +03/07/2021 16:44:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:44:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:45:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:45:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:46:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:49:01: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:49:33: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:51:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:51:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:54:45: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:55:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 16:56:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL +03/07/2021 17:05:53: prof: ERR: Message received without body for room: en@chat.404.city/a +03/07/2021 17:05:53: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +03/07/2021 17:07:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 17:07:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 17:09:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +03/07/2021 17:10:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +03/07/2021 17:11:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne +03/07/2021 17:11:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne +03/07/2021 17:11:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 17:11:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 17:14:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 17:16:20: prof: ERR: IQ error received, id: NmNkMTIxNTQtN2NkOS00OTc1LTg4NzUtNTAzYmQxN2U1NGQ4ZGJlNTFmZjZjMjRiNTQ0M2Q3MGZhMzFhNGM3YmQ3MzA1ZDRhYTI4N2JiMDEyYTcxYWQ4NWFjZDE0NzkyYjExMw==, error: Request has timed out +03/07/2021 17:16:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 17:19:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 17:23:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 17:29:46: prof: ERR: IQ error received, id: M2NjMjIwOTItZTFlNC00OGUwLWJiNTMtODNjYWI0NDY3MDNlOWFjOWUxOTJkZWRhOGZlNmYzNTRhNDk2YTUyZTc0NTJkM2FkZGQ1ZjMzMzZkZTRiOTM5YmJiM2U2NjM3YWYyYg==, error: Request has timed out +03/07/2021 17:29:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 17:35:47: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 17:37:23: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +03/07/2021 17:40:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 17:42:11: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 17:43:30: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 17:55:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +03/07/2021 17:55:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +03/07/2021 17:58:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +03/07/2021 17:59:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lep +03/07/2021 18:00:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lep +03/07/2021 18:15:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 18:16:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 18:16:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 18:17:20: prof: ERR: IQ error received, id: ZDA5Y2I3ZWItYmEzOS00MDEyLThiN2YtODEzZmIwMWVkMGM3Y2ViZTNlZDg5NzNmMmYxNjI1Mjk4N2EyYmExMWNkMDMxOWYxZmM1YWIwZGRkMmI1MzE1NTZiNzVmMjU1Nzk0YQ==, error: Request has timed out +03/07/2021 18:17:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 18:20:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:20:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:21:33: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:22:14: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:22:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:22:44: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:23:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:23:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:23:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:23:49: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:30:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 18:30:26: prof: ERR: Message received without body for room: emacs@salas.suchat.org/qy +03/07/2021 18:30:26: prof: ERR: Message received without body for room: emacs@salas.suchat.org/qy +03/07/2021 18:30:43: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +03/07/2021 18:31:08: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:32:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:33:01: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:33:02: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:33:40: prof: ERR: IQ error received, id: ZmE2NjE1OWUtZTU3MC00ZjQzLWI1YzEtYzVmM2UxNjhmMmM3MjlmMjg0Yjk0MzUxODQ2OTliNjU3ODFhYTllM2E0YTkwMjk4NjcwOTYyOWU3ODcyOGZiMWJmYzVlZmZiOTlkNA==, error: Request has timed out +03/07/2021 18:33:40: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 18:34:38: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:34:40: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:34:42: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:34:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:34:43: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:34:54: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:34:54: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 18:34:57: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 18:35:27: prof: WRN: Generated sha-1 does not match given: +03/07/2021 18:35:27: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 18:35:27: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 18:36:54: prof: WRN: Generated sha-1 does not match given: +03/07/2021 18:36:54: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 18:36:54: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 18:37:20: prof: ERR: IQ error received, id: ZjIwMDlkYmEtNjAwMy00Nzc5LTg0ZjktYWQ0NTk4NzgzODk0N2E2MjJiMzVjNWVjNzViZGYzMDNjNGEyYmM4MWY0YmY0Yjk1MWQzN2VlMWRjY2YzMzNmZDNiODYwYzYzNzhiNw==, error: Request has timed out +03/07/2021 18:37:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 18:40:00: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 18:40:19: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 18:41:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 18:41:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +03/07/2021 18:42:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 18:44:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +03/07/2021 18:49:10: prof: ERR: Message received without body for room: emacs@salas.suchat.org/wgreenhouse +03/07/2021 19:00:58: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:01:02: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:01:03: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:01:11: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:03:17: prof: WRN: Generated sha-1 does not match given: +03/07/2021 19:03:17: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 19:03:17: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 19:03:27: prof: ERR: IQ error received, id: MGRjN2UwZjAtNDBhMi00OWJiLWJlZDgtY2E2MWE2ZWNjODU5MDgxMmEyNjdiZWViMTNlNGU0MGU3ZWNmMzcyZmI3ZDY1YmViMmJlYmIxZDU1MDc2MDdjM2I0MTQzNTczZDk3YQ==, error: Request has timed out +03/07/2021 19:03:27: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 19:03:30: prof: WRN: Generated sha-1 does not match given: +03/07/2021 19:03:30: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 19:03:30: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 19:06:40: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:06:42: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:06:42: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:06:44: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:07:48: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 19:08:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 19:08:18: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:08:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:08:22: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:09:40: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:12:01: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 19:12:02: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 19:16:44: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:16:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:16:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:16:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 19:16:46: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:16:46: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 19:19:59: prof: ERR: IQ error received, id: OTljMjNjNjItZDYzMi00OTBhLWE5MzAtMWFmOTUzNTkxNDIxYzMwMDYxOTJhNTZlMTNiNWYwZjIwZDM1NDA1ZDBmOGE2ZmU2YTBhZTRiOWU1MWYyOWI0OGY5ZDA1ZjlkN2NlYQ==, error: Request has timed out +03/07/2021 19:19:59: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 19:21:19: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 19:22:40: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:22:58: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:23:05: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:23:09: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 19:23:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +03/07/2021 19:23:19: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:23:20: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:23:41: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:24:47: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn +03/07/2021 19:25:02: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 19:26:00: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 19:27:34: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 19:32:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 19:33:39: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 19:34:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 19:37:18: prof: ERR: IQ error received, id: OTc5YjU1ZTctZjI3MC00MjQ0LWFhNDQtNWNhYjZjMmViZjYwMzIzOGZiMGExMzQxZDFlMDEyMWNkNTc4NDQxNmM2YmM3ZTk4MmZkNjIyYTQ4MTYxNTNmNDU1NWUyNDNiMTMxZA==, error: Request has timed out +03/07/2021 19:37:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 19:43:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:43:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:45:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 19:46:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +03/07/2021 19:47:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:47:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 19:47:52: prof: WRN: Generated sha-1 does not match given: +03/07/2021 19:47:52: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 19:47:52: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 19:48:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:48:57: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:49:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:49:02: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 19:49:07: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 19:49:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:49:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 19:50:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 19:50:26: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 19:56:53: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 19:57:17: prof: ERR: IQ error received, id: OTJiNTRlZTgtMmYxMy00OTQ3LTljMmMtZTdmNTVjYmU2MGY0YWVlMmIyY2Y4MWQ3MDVjYTliMjRmNDdkMzBhNWJkNjg5NzA0MGJhM2Y2NWYyZjM5Mzg3NTA4ZDQ2Y2Q2ZjIwZA==, error: Request has timed out +03/07/2021 19:57:17: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 20:09:19: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:09:28: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:09:57: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:10:01: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:10:33: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:10:36: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:10:46: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/wurstsalat +03/07/2021 20:10:47: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +03/07/2021 20:10:48: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +03/07/2021 20:11:39: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:11:44: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:11:53: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:12:05: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:12:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +03/07/2021 20:12:18: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +03/07/2021 20:12:43: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:14:42: prof: ERR: IQ error received, id: ZTYxMjk2NTktNWYwOC00OTU3LTg1M2YtZTVjM2YxZGExYjNkYzQ0YzQ4NjRlY2VhZjllZWU2MmM1ODE0YTRkNmQyMjE3MGI4OTIyZDZiMGYwNGQzNjNhNDZlMDQ1NmZlYTA1Mg==, error: Request has timed out +03/07/2021 20:14:42: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 20:34:33: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:34:44: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:42:00: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 20:42:16: prof: ERR: IQ error received, id: NGUwNmMwYzUtYjEyZi00ZjEyLTllNDItMGRjZDllZDIxZjhkYWJlMTQ4MjFlOTg3N2JkOWE5N2U3M2ZjYjYwNmVmZWRiZjJiODEzN2NiOGQwYjQ4YWRmNWMyMTZiMmRjMmE0OQ==, error: Queries to the conference members are not allowed in this room +03/07/2021 20:42:16: prof: WRN: Error received for capabilities response from conversations-offtopic-reloaded@conference.trashserver.net/Agris: +03/07/2021 20:42:25: prof: WRN: Generated sha-1 does not match given: +03/07/2021 20:42:25: prof: WRN: Generated : mpjf9+07+HNoZ6+YxlqRhZDbiVs= +03/07/2021 20:42:25: prof: WRN: Given : l95JgiXsL86tDaMg2HTvl+0Ijb4= +03/07/2021 20:43:27: prof: WRN: Generated sha-1 does not match given: +03/07/2021 20:43:27: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +03/07/2021 20:43:27: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +03/07/2021 20:44:53: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 20:46:02: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +03/07/2021 20:46:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 20:46:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 20:46:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 20:46:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 20:46:43: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ +03/07/2021 20:46:55: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ +03/07/2021 20:47:24: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 20:47:59: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes +03/07/2021 20:48:01: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes +03/07/2021 20:48:36: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ +03/07/2021 20:48:41: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ +03/07/2021 20:48:54: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:48:55: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:48:57: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:49:01: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes +03/07/2021 20:49:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes +03/07/2021 20:49:09: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:49:15: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:49:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:49:24: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 20:50:52: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 20:52:41: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:56:26: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 20:56:39: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 21:01:23: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu +03/07/2021 21:07:25: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:08:04: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:08:22: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:08:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat +03/07/2021 21:09:24: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:09:33: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:14:18: prof: ERR: IQ error received, id: N2RkOGFkNzYtYjE5OC00MjhmLWE2MGYtNmQwOGI1YmJmYWUxNTkyMTNiNDEyZTUwOWM2YjRmZDVjMjdkMTA2ODc1YzhkOGNkNzM3M2QwY2NiMjdlMDgzMzczNGY5Mjc3NjM3Yw==, error: Request has timed out +03/07/2021 21:14:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 21:16:35: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 21:16:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 21:16:55: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 21:17:18: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +03/07/2021 21:17:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:17:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:18:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 21:18:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 21:21:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:22:03: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:22:14: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 21:22:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:23:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:23:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:25:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:25:47: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:25:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:25:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:26:24: prof: WRN: Generated sha-1 does not match given: +03/07/2021 21:26:24: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 21:26:24: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 21:26:44: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:27:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:27:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:27:45: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:28:43: prof: ERR: IQ error received, id: ZGZiMzBiMmYtM2MxYS00NDYxLWFhNzYtNTNmNWFhOWI1MTlkZWJhYTFiODk5YmM4YzcyMzljMGUyYzI4OTgxZDk4ZGFjNzBiNWNhNDYwYzc3ZWYyNzU1NTQzNjEyOWQ2ZDJkYw==, error: Request has timed out +03/07/2021 21:28:43: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 21:30:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 21:30:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:30:16: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:32:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:32:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:32:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:32:47: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:33:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:33:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:34:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:34:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:35:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:36:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:36:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:38:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:39:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:41:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:43:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:43:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:45:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:45:53: prof: ERR: IQ error received, id: NjU5ODI4ZDYtMTA2OC00MDAzLTg4MjgtMjVlZDZhMDZlZDUyOGM2YTQyNjZkOGQ2MDg2MDExMDhiNzUxZGYxNzU1NWFhMWRhNTAxZDQzYzEyOTM4MDMwODhhZDIyNjUyNzcyYQ==, error: Request has timed out +03/07/2021 21:45:53: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +03/07/2021 21:46:12: prof: WRN: Generated sha-1 does not match given: +03/07/2021 21:46:12: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 21:46:12: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 21:47:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:47:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:52:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:52:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:52:52: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:53:09: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:53:10: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:53:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:54:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:54:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +03/07/2021 21:54:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:54:48: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:54:49: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:54:54: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:54:56: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:55:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 21:55:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 21:56:19: prof: ERR: Message received without body for room: chat@dino.im/kaoka +03/07/2021 21:56:23: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:56:24: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 21:56:24: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 21:56:25: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 21:57:04: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:57:10: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 21:57:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:57:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:57:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 21:58:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 21:59:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 22:00:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 22:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 22:00:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 22:00:58: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 22:01:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 22:01:32: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:01:35: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:01:35: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:01:37: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:01:56: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 22:02:00: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +03/07/2021 22:02:58: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:03:08: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 22:03:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 22:03:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +03/07/2021 22:04:10: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 22:04:14: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 22:04:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 22:04:29: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +03/07/2021 22:05:25: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:05:40: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:05:41: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:05:41: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:05:42: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:05:44: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:05:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:06:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 22:07:10: prof: WRN: Generated sha-1 does not match given: +03/07/2021 22:07:10: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 22:07:10: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 22:07:14: prof: WRN: Generated sha-1 does not match given: +03/07/2021 22:07:14: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +03/07/2021 22:07:14: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +03/07/2021 22:08:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 22:08:31: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 22:09:20: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:09:21: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:09:23: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:09:24: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Link Mauve +03/07/2021 22:09:25: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:09:27: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:09:28: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:09:57: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Link Mauve +03/07/2021 22:12:16: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:12:21: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:13:13: prof: WRN: OMEMO: received a message with no corresponding key +03/07/2021 22:13:24: prof: ERR: IQ error received, id: NWQ5OGYyN2YtMzkzZi00NTJiLThlMDItYTVkODY0ODk3MjNjZDllNzk0MWFhMTkzNWI0YzZlZThkYmY2ZDQ2ZjlmOGEzNmE5OTE4MmUxOTg1YWRiYWVlYmY3YWM4MjNkNTQ3Ng==, error: feature-not-implemented +03/07/2021 22:13:24: prof: ERR: IQ error received, id: NGI4NGIxNzItMjNmNy00ZGEwLWFiNmEtZTYyNzFlM2Y1NjdkODM5ZmJiMGEyZDBiNWRjZmYwZTc3ZmI0NWNjNjUxN2UzYjJjNDFkZTdmM2I1OWJlYTEzM2YwODcwZGQ4ZDEwMw==, error: feature-not-implemented +03/07/2021 22:13:24: prof: ERR: IQ error received, id: M2FlZmUwMGEtZmJhYi00ZGU3LWI3MzQtMjRiOGM3NGQ0MWNkZjFkNTY1YjY2MmQyODE3OTA0NGM2MDIzNzdmOTc1YzczNDFjMDU5M2RhODY0ODY3MWYwYWFiMzQwMzI5YTlmNA==, error: feature-not-implemented +03/07/2021 22:13:25: prof: ERR: IQ error received, id: YTFjODQ1MjMtZGFmMC00MWFhLWE5ODUtNDU5MTQ4NGI1Yjk3MDU4NGIxNDUzOWQyZDA3MzIzZjM1MDcwMzA3ZWIxYzAwYTA4NTM0YWVjOGM2YmUxYWViYWE3MGU0ODQwNzhjYg==, error: feature-not-implemented +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1519741822 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 446279639 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1362339665 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1547501418 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 952095435 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 870832176 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 866731537 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1540261437 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 308556671 +03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1033627704 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1519741822 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 446279639 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1362339665 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1547501418 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 952095435 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 870832176 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 866731537 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1540261437 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 308556671 +03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1033627704 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1519741822 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 446279639 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1362339665 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1547501418 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 952095435 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 870832176 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 866731537 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 308556671 +03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1033627704 +03/07/2021 22:14:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 22:15:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 22:16:00: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:16:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 22:17:04: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:17:10: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:17:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +03/07/2021 22:17:29: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:22:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 22:22:46: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 22:23:30: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:23:31: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:23:32: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:23:33: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:23:34: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:23:35: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:29:55: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:30:01: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:30:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 22:30:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +03/07/2021 22:30:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 22:31:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +03/07/2021 22:31:26: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ +03/07/2021 22:31:55: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ +03/07/2021 22:33:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 22:34:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +03/07/2021 22:35:32: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:35:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:35:49: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:35:52: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:37:29: prof: WRN: Generated sha-1 does not match given: +03/07/2021 22:37:29: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 22:37:29: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 22:42:29: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:42:36: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:42:37: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:42:39: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:42:42: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:42:44: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:42:44: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:42:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:42:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff +03/07/2021 22:42:50: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +03/07/2021 22:45:17: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 22:45:25: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +03/07/2021 22:45:42: prof: WRN: Generated sha-1 does not match given: +03/07/2021 22:45:42: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 22:45:42: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 22:56:03: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke +03/07/2021 22:57:44: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke +03/07/2021 23:01:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris +03/07/2021 23:01:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 23:03:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris +03/07/2021 23:03:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +03/07/2021 23:09:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:09:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:10:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:11:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:11:54: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:14:21: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +03/07/2021 23:15:55: prof: WRN: Generated sha-1 does not match given: +03/07/2021 23:15:55: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 23:15:55: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 23:16:01: prof: WRN: Generated sha-1 does not match given: +03/07/2021 23:16:01: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 23:16:01: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 23:16:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:16:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:16:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:16:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:17:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:17:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:17:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:18:17: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:18:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:18:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:18:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:19:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:19:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:20:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:20:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:22:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:22:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +03/07/2021 23:24:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:24:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian +03/07/2021 23:27:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 23:28:53: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +03/07/2021 23:42:04: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/timothy +03/07/2021 23:44:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +03/07/2021 23:54:40: prof: WRN: Generated sha-1 does not match given: +03/07/2021 23:54:40: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 23:54:40: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 23:58:43: prof: WRN: Generated sha-1 does not match given: +03/07/2021 23:58:43: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 23:58:43: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +03/07/2021 23:59:19: prof: WRN: Generated sha-1 does not match given: +03/07/2021 23:59:19: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +03/07/2021 23:59:19: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +04/07/2021 00:01:49: prof: WRN: Generated sha-1 does not match given: +04/07/2021 00:01:49: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +04/07/2021 00:01:49: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +04/07/2021 00:02:41: prof: WRN: Generated sha-1 does not match given: +04/07/2021 00:02:41: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +04/07/2021 00:02:41: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +04/07/2021 00:07:13: prof: ERR: IQ error received, id: ODkyMzJjYTYtZDA4Ni00MmQ3LTliNzItZWI5NGI0YmE5MDZkYmZhMjI3ZjM1Nzc0ZTcwNzM1YmFkNWZjNWFiZWE1NWExNjg2MjRiNThjMjkwYjkyMjRjYzM3NTc1ZDQ0Y2NkYg==, error: Request has timed out +04/07/2021 00:07:13: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 00:09:28: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +04/07/2021 00:10:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 00:13:48: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon +04/07/2021 00:14:28: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke +04/07/2021 00:14:40: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke +04/07/2021 00:17:49: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 00:23:47: prof: ERR: IQ error received, id: N2VjYzkxMzYtZDg5MC00ODlkLThlN2QtZmUwMjFjOWQ1ZTBjNTJhYzk0N2VhMTg1OWU3M2ZkYzQ4MDEwZTVlMDg3YjhiYWFhNmZmY2JlNTA5MmMxMWM4NDU4ZDk1OGJhNGJkNQ==, error: Request has timed out +04/07/2021 00:23:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 00:24:53: prof: ERR: IQ error received, id: MDNkOWEwMTMtNTMyNy00ZDc2LTg4MWEtZGMzODNkYjRkZTQ1OTNlYjZiOTc3MWI0YjhhODljMmNmZGFmM2IxOGE5OTUyYjZmYWNhM2UzNWRhMDExYzQ0YzVkMGIzNjhkMzZjYw==, error: Request has timed out +04/07/2021 00:24:53: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 00:28:08: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou +04/07/2021 00:38:29: prof: ERR: IQ error received, id: OGY3ZTA0NmMtYjAwYS00MTI4LTg3YTktNDRlMzA4MDNhZmJkMDRiN2I2NjUwMjk4MjdjNGU1YTgyOTk0Yjc5MjMzYjUzMmFkNWU5ODZlZDY1OTMxNjNkOTNmZjVkYjU5NDI4ZA==, error: Request has timed out +04/07/2021 00:38:29: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 00:38:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 00:38:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 00:41:58: prof: ERR: IQ error received, id: NjU3Y2VlNDUtZjU5ZC00MDc3LTg4YzItMjMzNGYyZjY2YzdiNWI5MDlhZTI2YzViYjNkMmQ4YmMzOWRlN2VhMWU5ZWQ5NGU5MDRmOTc5OTZiMjgxYjAzNjkzNzk5NzIzY2U5NQ==, error: Request has timed out +04/07/2021 00:41:58: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 00:50:49: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +04/07/2021 00:50:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve +04/07/2021 01:00:46: prof: ERR: IQ error received, id: YTJiZmRjYmMtZWRmNy00ZDc2LWEyYWItM2E4MGI2ZGMxMDhjMjNjMWM5YjQ5MjBhMzQ2MGM0NjEzMGRiZWQ3ZDU3NDUxZTM0ZTFiZDFhNzQyZTI2MmRmYzQ3MThhZjJlMDc3ZA==, error: Request has timed out +04/07/2021 01:00:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/blumpkin: +04/07/2021 01:30:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 01:32:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 01:41:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 01:43:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 01:49:00: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio +04/07/2021 01:50:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 01:51:02: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio +04/07/2021 01:53:49: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio +04/07/2021 01:54:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 02:01:42: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio +04/07/2021 02:35:18: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 02:35:18: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 02:35:25: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +04/07/2021 02:38:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +04/07/2021 02:38:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +04/07/2021 02:57:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:02:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris +04/07/2021 03:04:17: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris +04/07/2021 03:13:48: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 03:13:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 03:18:12: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 03:19:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:19:16: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 03:20:15: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 03:20:16: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 03:22:00: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:33:39: prof: ERR: IQ error received, id: OTRjNmViNjctYTVmZi00NzQ2LWJiMTQtZTgyYzMwODU1ODg2OGE1MGUxN2E1NjlhNDY3ZTZjNmVkZWMxYmY3YjUzMDRhNzI3ZDVjODI2NTE0ODJjMjllOTA4YjYyZTk4NGNmYg==, error: Request has timed out +04/07/2021 03:33:39: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 03:40:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 03:43:39: prof: ERR: IQ error received, id: YTRmODg4MmMtOTI0Ni00OWJkLTgxMDMtNDMxNGVkYjUxMmU4MDNiNmZkNWU1NWIxNDk0ZGEyN2FmYzAzMGY3Yjc4ZTM1Mzg1MzA4MTFmNWNhZDZlNDM5MDA1NmQyYWQzMzY1Yw==, error: Request has timed out +04/07/2021 03:43:39: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 03:43:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:44:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:47:56: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 03:49:01: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 03:54:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:55:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 03:56:49: prof: ERR: IQ error received, id: OThkOTBlNzMtZjk0Mi00NmVlLThlMDYtNzhmYmU4NmY1NDliZjQ2NDUyNWM5OWY2ZDU0MWViYmY2M2U0ZTEwN2Q5ZDJiY2Y1NTZkZDI4MjExN2E0NWVhMDRlMTZjNmE2ZmQ5OQ==, error: Request has timed out +04/07/2021 03:56:49: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 03:57:08: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 03:58:57: prof: ERR: IQ error received, id: OGY3MzkwNWMtOTlhMC00MGJkLWIyYzgtZDU4ZmE2N2I1MGUwYWRlM2FlMmNkZDU4YzkyYTg1MjJhNTA4MDM3NmI3ZTBkM2EwOTk3ZmVhYjhiNjEyMTYzZTE3OWE1ZjhlMTRiZg==, error: Request has timed out +04/07/2021 03:58:57: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 04:00:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:02:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:03:04: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:08:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:11:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:14:54: prof: ERR: IQ error received, id: YjRkNDc1NzgtNDAzYy00MzdjLWFiNmUtOTQ4ZmI0NTNjNjZlYTNiZTQ1ZWI3ZDgwM2UyM2IxYTFlZTdiMjZmYWYyM2VhYTYwZGEzYTJmNTJlZTkyNGU5ZDNkMmYzMzkyYTVlYg==, error: Request has timed out +04/07/2021 04:14:54: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 04:15:06: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:15:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:15:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:15:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:21:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:22:09: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 04:22:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 04:22:13: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 04:23:24: prof: ERR: IQ error received, id: N2IzM2VjOWYtMGE5Ni00NDEyLThhNTMtNGU5ZTQ4ZWVlMGI1YjEzOTJhNjlkMGNlYTRlNzYwMWI2MTU5ODY0NjBkNDBjM2EzZDc4NjcxN2NkMzAzOTNlMWYxNDg1ZmRiNDA2Zg==, error: Request has timed out +04/07/2021 04:23:24: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 04:24:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:24:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:24:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:25:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:25:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:25:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:26:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:31:08: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 04:31:11: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 04:31:13: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 04:32:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 04:33:25: prof: ERR: IQ error received, id: M2UzMDY1ZmQtOWNjNS00ZjJjLTg5YjAtZDQ4MWE4NDZkMzI0Nzc2ZmE2NjIyMmQ3MDA1MjM0MDBhYzRmNWE2YjU4NzM4YzY2MWFlNjEzOTE0YTRhM2U1ZjcwNGM3MmNlNjJmZA==, error: Request has timed out +04/07/2021 04:33:25: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 04:36:46: prof: ERR: IQ error received, id: Yzg0OGI1YWQtMjU0Mi00YTNhLTg0MDctNDhiMmE0MmIyYjI0Y2ZlOTZlOTliZDQ4MjhmNGIzYzhiNzFjNTg2MjBjZTA1NGY4MWYwY2Q0NGJjZWU3ZDdlY2NhMTNiNmMxMmVkMg==, error: Request has timed out +04/07/2021 04:36:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 04:57:49: prof: ERR: IQ error received, id: MjAxMmNhNjMtZDJmYi00YjkxLWEwMmItNWVlNGM3OTFkNzA2ZTBiYTVjOWY4Yzc5M2VlYTFhMzBhMGJmNjA1NmEzMDU0NDBlNTVmZjBhNjgyODU1N2YwMGM0MGUwNmUyNjc0MQ==, error: Request has timed out +04/07/2021 04:57:49: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 05:01:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 05:03:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 05:06:01: prof: ERR: IQ error received, id: MmQ2MDI1ODItMjYzOC00MjUwLWIwOTMtNzI1YTg1OTY0Mjg0OTUyMzUxZDk0YTVmOTE5ZDA1ODc1MGM3NmU3YTI3ZGQ5NTNlNzVlMjhkNjU2YzU1ZTgwOTAzNzE0Zjk0NTIxYg==, error: Request has timed out +04/07/2021 05:06:01: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 05:09:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 05:14:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 05:14:46: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 05:23:09: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:23:30: prof: WRN: Generated sha-1 does not match given: +04/07/2021 05:23:30: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +04/07/2021 05:23:30: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +04/07/2021 05:24:32: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:26:17: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:27:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:29:10: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:30:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:32:31: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:33:23: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 05:33:57: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:34:46: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:34:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 05:34:56: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:34:58: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:34:59: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:35:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 05:36:51: prof: WRN: Generated sha-1 does not match given: +04/07/2021 05:36:51: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +04/07/2021 05:36:51: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +04/07/2021 05:37:06: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:37:06: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:37:07: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:37:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 05:39:50: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:40:46: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:41:11: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:43:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:44:01: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:44:24: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:44:51: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:45:10: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:46:17: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:48:20: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:48:22: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/komp +04/07/2021 05:49:00: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:50:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +04/07/2021 05:50:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce +04/07/2021 05:50:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 05:51:39: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 05:52:09: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:55:33: prof: WRN: Generated sha-1 does not match given: +04/07/2021 05:55:33: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +04/07/2021 05:55:33: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +04/07/2021 05:55:35: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:57:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:57:17: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 05:57:42: prof: ERR: IQ error received, id: ZmMxNmY3YTktMmEzZC00YjkzLWFhNGMtY2M4Y2NmNTQ3NDRkM2NmMzNiNmEyOTAxMmQ4YzcwZmFiYjk2OWMxMGIwMzg4NjBkNTUyY2IzMWI2NTY2YzNmYTI4NjcxN2ViZTg2Yg==, error: Request has timed out +04/07/2021 05:57:42: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 06:01:56: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 06:03:54: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Axel +04/07/2021 06:04:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Axel +04/07/2021 06:04:50: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 06:07:43: prof: ERR: IQ error received, id: ODljOGZiMDAtYTJkYi00YTNkLThjNDAtNDMxZTI5NDhmZmI4NWFiYzc4ZDgyMzUyYTExNjEzYTQwNzk5MzE4NGYzNDgwZTcyOGM5YzVjMzEyYmU4MGM0NzgxYTI2MzczYjk3YQ==, error: Request has timed out +04/07/2021 06:07:43: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 06:07:44: prof: ERR: Message received without body for room: en@chat.404.city/alhimia +04/07/2021 06:15:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 06:17:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 06:26:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 06:26:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 06:27:43: prof: ERR: IQ error received, id: NTZhMGExODktMjcxNy00N2E2LWFkMDctODg3NWU5NDc0MWYzNWRlMDRiNjNjNmE1OGNiOWVjODU4MzU0OWJlMTQ0YjJjNGI4NDdmYWU3YjgzY2JjZTFkYmFmYmUwY2MyNzFlZA==, error: Request has timed out +04/07/2021 06:27:43: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 06:27:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 06:32:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 06:34:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 07:38:54: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/werdan +04/07/2021 07:39:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/werdan +04/07/2021 07:47:46: prof: ERR: Message received without body for room: movim@conference.movim.eu/werdan +04/07/2021 07:58:59: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 08:00:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 08:00:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 08:00:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 08:00:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 08:01:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG +04/07/2021 08:01:41: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 08:02:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 08:07:21: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 08:11:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 08:15:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 08:30:12: prof: ERR: IQ error received, id: NDUwNGVhN2EtNjk1YS00NjViLTkxNzUtMzgwOTRkYTA0Nzc1NThjNDA0ODA2MDE3YThhMDExMjNlZWRjMTZlYjE0ZjZiZjBiZjk5Y2U0ZDE1MDU0MWZiYjZiMjBhMzdiMGI2OQ==, error: Request has timed out +04/07/2021 08:30:12: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 08:30:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 08:32:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +04/07/2021 08:32:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 08:35:21: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 08:35:41: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 08:40:12: prof: ERR: IQ error received, id: Y2MwY2JiMTgtM2QwZS00MGUyLWEyYzgtMTBjMWVjMjQxMzAyYWQ0NmVhYjg1MzY0YTc4NmUwNWMyNDViOTJiMWEwM2E0ZWQwMzNhYjIzNDUzOTEyYzZhZjZhZDE5MTc4MmRiMw==, error: Request has timed out +04/07/2021 08:40:12: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 08:43:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 08:45:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 08:48:51: prof: WRN: Generated sha-1 does not match given: +04/07/2021 08:48:51: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 08:48:51: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 08:49:07: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve +04/07/2021 09:08:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:08:43: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:09:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:09:07: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +04/07/2021 09:09:08: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +04/07/2021 09:09:09: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +04/07/2021 09:09:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:09:23: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +04/07/2021 09:09:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:09:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:09:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:09:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:10:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:10:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:10:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:10:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:10:09: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:10:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:10:32: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:10:34: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:10:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:10:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:24:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 09:25:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:25:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 09:31:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:33:28: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:34:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:35:52: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:41:07: prof: ERR: IQ error received, id: N2YyODNhMmQtNTQyMi00ZmU3LWE3ZjktMjg1YTBkNzE3ZGMxMjlmYTU3YWJmMWZhMDA1OGE3YWFlZWJkMmU4MjBhMjkzZGVlN2M3YWE3YTgwNjUwMzQ4ODdiMDlhNDE2NTdkZQ==, error: Request has timed out +04/07/2021 09:41:07: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 09:41:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:41:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:41:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:01: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:06: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:22: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:28: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:42:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:43:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:43:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:43:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:43:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:43:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:43:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:44:52: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:45:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:45:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:45:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:45:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:45:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:45:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:46:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:46:22: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:47:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:49:36: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:49:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:49:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:49:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:49:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:50:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:50:14: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:50:24: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:50:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:51:09: prof: ERR: IQ error received, id: ZWMwZmViZmUtNDM0OC00ODYwLWFjYTEtY2VkZmVkODc0M2UzOTAwNTQzM2Y4ZTJmMDk0ZDViNjQ4YzJhMmIyZGU5MGZkODIwNWE3NTFkMmY2MmViM2ZmZDZjNDM1NjQwMDUyNw==, error: Request has timed out +04/07/2021 09:51:09: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 09:51:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:51:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:51:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:51:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:52:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:52:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:52:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:52:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:53:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:54:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:54:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:54:20: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij +04/07/2021 09:54:20: prof: ERR: Message received without body for room: chat@dino.im/ij +04/07/2021 09:54:20: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij +04/07/2021 09:54:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij +04/07/2021 09:54:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:54:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:54:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:55:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:55:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:55:49: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij +04/07/2021 09:55:49: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij +04/07/2021 09:55:49: prof: ERR: Message received without body for room: chat@dino.im/ij +04/07/2021 09:55:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij +04/07/2021 09:57:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 09:57:09: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Étienne +04/07/2021 09:57:17: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Étienne +04/07/2021 09:58:14: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij +04/07/2021 09:58:14: prof: ERR: Message received without body for room: chat@dino.im/ij +04/07/2021 09:58:14: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij +04/07/2021 09:58:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij +04/07/2021 09:58:44: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij +04/07/2021 09:58:44: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij +04/07/2021 09:58:44: prof: ERR: Message received without body for room: chat@dino.im/ij +04/07/2021 09:58:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij +04/07/2021 09:58:58: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij +04/07/2021 09:58:58: prof: ERR: Message received without body for room: chat@dino.im/ij +04/07/2021 09:58:58: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij +04/07/2021 09:58:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij +04/07/2021 09:59:30: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:00:31: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:00:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:00:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:00:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:01:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:01:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:01:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:01:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:01:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:02:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:02:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:02:33: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:02:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:02:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:02:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:03:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:03:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:03:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:03:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:03:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:04:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:04:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:04:30: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:06:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:06:36: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:06:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:11:09: prof: ERR: IQ error received, id: OTU3ZWI5N2UtYzNkMi00Mzc2LWFiOGItYzQ2MGUxN2Q0OTBjNDNmMzFlZjFmNjJkZDRiYWU1OTU3ZDEwMTVjMjVlYWE0NDM1Y2E1YTQ4NWQ2ZGU0ZmU4YThhZjA2YmQ5ZGM0MQ==, error: Request has timed out +04/07/2021 10:11:09: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 10:24:11: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 10:24:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 10:24:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 10:24:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:26:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:26:33: prof: WRN: Generated sha-1 does not match given: +04/07/2021 10:26:33: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 10:26:33: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 10:26:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:27:14: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:27:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:27:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:27:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:27:26: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:28:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 10:28:03: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 10:28:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:28:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:29:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:29:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:29:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:29:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:30:17: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat +04/07/2021 10:30:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:30:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat +04/07/2021 10:32:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:32:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:32:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:32:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:33:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:33:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ +04/07/2021 10:34:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:35:01: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:35:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:35:22: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ +04/07/2021 10:36:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:37:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:38:30: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:39:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:41:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:41:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ +04/07/2021 10:41:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ +04/07/2021 10:42:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:42:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:45:20: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 10:46:33: prof: WRN: Generated sha-1 does not match given: +04/07/2021 10:46:33: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 10:46:33: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 10:47:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:47:31: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +04/07/2021 10:48:24: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:48:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:48:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:48:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:48:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:49:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 10:58:33: prof: WRN: Generated sha-1 does not match given: +04/07/2021 10:58:33: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 10:58:33: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 11:01:43: prof: ERR: IQ error received, id: ZmQ3YThiNjUtN2JlZC00ZDcwLTgyMTktOGVhMGYxMmM3ZDNjYTUzMGE0NWQ0YTY2NWMzNmRjMmUxMzA3ZWY5OWE3MTRkNzgwMGM0YjI3ZjZhYTk1ODMzYjBjNDBkMmRlZDE1Mw==, error: Queries to the conference members are not allowed in this room +04/07/2021 11:01:43: prof: WRN: Error received for capabilities response from conversations-offtopic-reloaded@conference.trashserver.net/mazyani: +04/07/2021 11:01:53: prof: ERR: IQ error received, id: YTA3ZmY4NWEtODc3ZC00ZGY5LWI1YjMtYWE0OTRlYTMwYmNkMGRkOGI3NjBjMjhhYjQ2MzA0MDg4MTdkNTQyZDlkZjI3MzM4ZTI2Y2ZlNzhlZDJmOWQ3YTgyM2E1MjU3Y2ZkZQ==, error: Request has timed out +04/07/2021 11:01:53: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Baba: +04/07/2021 11:12:15: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:12:50: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:13:18: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:14:56: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:15:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:15:13: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:15:19: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:16:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:17:19: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve +04/07/2021 11:19:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 11:20:31: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:20:33: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:20:59: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 11:21:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +04/07/2021 11:21:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 +04/07/2021 11:25:20: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:25:29: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:25:40: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 11:25:42: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 11:25:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:25:59: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:26:04: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:27:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:27:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +04/07/2021 11:27:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +04/07/2021 11:27:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve +04/07/2021 11:28:08: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:30:13: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:30:18: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:30:18: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:30:30: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:30:55: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:30:58: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:31:04: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:31:09: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:31:27: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:31:41: prof: ERR: Message received without body for room: movim@conference.movim.eu/Link Mauve +04/07/2021 11:31:42: prof: ERR: Message received without body for room: movim@conference.movim.eu/Link Mauve +04/07/2021 11:31:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 11:31:47: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 11:31:55: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 11:31:56: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 11:35:26: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 11:35:29: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 11:37:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 11:37:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 11:37:20: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +04/07/2021 11:37:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +04/07/2021 11:37:52: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +04/07/2021 11:38:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 11:38:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve +04/07/2021 11:38:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 11:38:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 11:41:04: prof: ERR: Message received without body for room: hmm@conference.hmm.st/g1n +04/07/2021 11:41:36: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +04/07/2021 11:41:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias +04/07/2021 11:42:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 11:42:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 11:42:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 11:42:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 11:44:57: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:05: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:07: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:07: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:22: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:33: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:39: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:40: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:45:48: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:46:19: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:46:51: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:48:38: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:48:41: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:48:43: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:48:51: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:51:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:51:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 11:51:14: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:51:15: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:52:00: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:52:03: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:53:08: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:53:12: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:53:42: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:53:47: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:55:18: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:55:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:55:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:55:34: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:55:35: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:55:41: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:55:43: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:56:03: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:56:09: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:56:15: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:56:25: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:56:28: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve +04/07/2021 11:56:28: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve +04/07/2021 11:56:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:56:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve +04/07/2021 11:56:42: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 11:56:43: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu +04/07/2021 11:56:45: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 11:57:17: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve +04/07/2021 11:58:33: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve +04/07/2021 12:00:12: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:01:17: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:01:21: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:01:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:01:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:02:27: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:04:31: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:05:31: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:07:50: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:08:56: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:09:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/southerntofu +04/07/2021 12:09:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/southerntofu +04/07/2021 12:09:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou +04/07/2021 12:10:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:10:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:11:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:12:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:14:00: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] +04/07/2021 12:14:00: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] +04/07/2021 12:14:00: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien +04/07/2021 12:16:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:19:25: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin +04/07/2021 12:21:12: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin +04/07/2021 12:22:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/vm +04/07/2021 12:22:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:25:31: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +04/07/2021 12:25:35: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +04/07/2021 12:26:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:26:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:27:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:27:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:29:34: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:30:34: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:32:31: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:33:32: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 12:38:24: prof: ERR: Message received without body for room: support@room.pix-art.de/yvo +04/07/2021 12:40:36: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:45:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:45:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve +04/07/2021 12:46:07: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:46:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:46:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:51:01: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:52:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:52:13: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:52:14: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:53:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:53:26: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:54:08: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:55:50: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:55:55: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:56:19: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:56:26: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:56:40: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:57:03: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:57:20: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:57:23: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:57:30: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:57:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 12:57:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:57:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 12:57:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 12:57:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:57:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:57:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:58:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 12:58:31: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:58:39: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:58:43: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 12:58:53: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 12:58:54: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 12:59:05: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 12:59:30: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:59:30: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:59:34: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 12:59:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:59:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 12:59:57: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:00:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 13:00:12: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:00:18: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 13:00:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 13:00:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 13:01:17: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 13:01:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 13:01:50: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:01:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:01:55: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:02:04: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:02:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:02:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:02:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:02:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:02:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:02:31: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:03:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 13:03:27: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:03:43: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:04:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:04:16: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:04:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:05:37: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 13:05:48: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 13:06:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:06:09: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:06:16: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:06:23: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:06:30: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:06:33: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:06:41: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:06:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:08:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:09:21: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:11:02: prof: ERR: IQ error received, id: ZTQxY2JlOTQtMTY5Ni00Y2UxLWI2ZmMtY2Q2NDMwNGQ5NjIxZjNlMTk0OWY3Njg3ZDZmOWYzNzc3OWU0NjAwNDZmMDE2MWEwMGRhNGZmYTU1YTY4ZTY1NWFmM2YxMmFjOWI2Nw==, error: Request has timed out +04/07/2021 13:11:02: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 13:11:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:11:12: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:11:14: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:11:49: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:11:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:12:21: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:13:22: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:14:00: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:14:20: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:14:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:14:46: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:14:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:15:05: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:16:03: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:16:16: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:16:41: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:17:03: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 13:17:03: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 13:17:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:17:25: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:17:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:17:40: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 13:17:42: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- +04/07/2021 13:17:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:17:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:18:00: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:18:03: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:18:03: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:18:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:18:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 13:19:12: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:21:02: prof: ERR: IQ error received, id: MjIwNDJkMzctZjY1NS00ZjUwLWE5OTUtMDIwNzk5MTIzNjhhMjFlZGI0ZGY5ZWRkNzg1OTI4MDBmNDhmOGVmNmI2ZTQzY2ZhMzUxMzk4NGRlMmNhNDBhZWE5ODljOGU4NmIxZg==, error: Request has timed out +04/07/2021 13:21:02: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 13:21:03: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:21:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 13:21:37: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:21:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 13:21:38: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:21:39: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:21:54: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:22:01: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:22:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:22:14: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 13:22:40: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:22:58: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:23:09: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:23:10: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:23:25: prof: WRN: Generated sha-1 does not match given: +04/07/2021 13:23:25: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 13:23:25: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 13:24:10: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:24:25: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:24:49: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:24:55: prof: WRN: Generated sha-1 does not match given: +04/07/2021 13:24:55: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 13:24:55: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 13:25:10: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:25:12: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 13:26:42: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:26:53: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:27:56: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:29:39: prof: ERR: IQ error received, id: M2Q5ODg3NGItNjBiMS00MmQ3LWFkZTctYmJlYzJlZWMxYmM4ZGMzYWU0YjE3MWY5MGRhZTA2MGM5NGNlOGQ4ZTkzZDNjMDhmY2U1YWU5OGQyZGNhNmFmMDMyNzljYjAzNDhjYw==, error: Request has timed out +04/07/2021 13:29:39: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 13:31:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:37:27: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:37:43: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:37:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:41:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:41:33: prof: ERR: IQ error received, id: ODIyYmU0NWQtNDk1ZC00MWE5LWFlNTAtNWE3NjM0MGVmZDA5MWI3MGNjZWM2Njk2ZGY2NTRlNTVkMzIxYTZjMmJmMzE0YTJkNjE3ZDE5Y2JlNTYzMGVmYzI2ODljZmM5OTc5Yw==, error: Request has timed out +04/07/2021 13:41:33: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 13:41:42: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:41:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:42:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:44:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:47:16: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk +04/07/2021 13:53:56: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:54:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 13:54:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 13:55:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 13:55:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 13:55:38: prof: WRN: Generated sha-1 does not match given: +04/07/2021 13:55:38: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +04/07/2021 13:55:38: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +04/07/2021 13:57:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 13:57:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 13:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 13:59:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 13:59:38: prof: ERR: IQ error received, id: OGJjMGQ2OTAtOWYyMC00MzJiLWI1NjEtNzVlNTExMWQyZDM5YzE4YzY2M2Y4YTJjMWRkNGE4YzBmM2NiMzBkZGE1N2U2M2FhYjk4ZmZkODhmYjcyZmRmNTQ5ZWQ3OWJkNGUyZg==, error: Request has timed out +04/07/2021 13:59:38: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 13:59:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 13:59:55: prof: WRN: Generated sha-1 does not match given: +04/07/2021 13:59:55: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 13:59:55: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 14:00:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:00:28: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 14:00:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:00:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:01:00: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 14:02:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 14:02:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 14:02:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 14:02:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 14:05:12: prof: WRN: Generated sha-1 does not match given: +04/07/2021 14:05:12: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= +04/07/2021 14:05:12: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= +04/07/2021 14:09:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 14:11:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 14:11:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 14:11:59: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 14:12:20: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 14:14:34: prof: ERR: Message received without body for room: support@room.pix-art.de/emus +04/07/2021 14:14:35: prof: ERR: Message received without body for room: support@room.pix-art.de/emus +04/07/2021 14:15:03: prof: ERR: Message received without body for room: support@room.pix-art.de/emus +04/07/2021 14:20:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:23:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:23:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:23:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:23:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:23:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:24:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:25:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:25:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:25:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:26:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:27:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:27:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:27:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:27:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:27:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:30:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:32:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:51:34: prof: ERR: Message received without body for room: support@room.pix-art.de/yvo +04/07/2021 14:51:49: prof: ERR: Message received without body for room: support@room.pix-art.de/yvo +04/07/2021 14:52:20: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +04/07/2021 14:53:03: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:53:34: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:53:45: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:54:06: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:54:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:54:36: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:54:39: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:54:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian +04/07/2021 14:55:33: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:55:56: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:55:57: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:56:46: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:57:06: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:57:35: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:57:42: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +04/07/2021 14:58:43: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* +04/07/2021 14:58:43: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +04/07/2021 14:59:17: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +04/07/2021 15:06:20: prof: ERR: Message received without body for room: hmm@conference.hmm.st/wgreenhouse +04/07/2021 15:12:09: prof: ERR: Message received without body for room: movim@conference.movim.eu/eyome +04/07/2021 15:16:09: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 15:23:19: prof: ERR: IQ error received, id: ZDRjMTNlMjQtOWU4Zi00YTU0LTllZGYtYzI4NjUyMDE5MjZlN2E5ODI5NTI1MTkwNjUxNjAyODI3ZDZmMzNjNTE3OThlYjhkNzIxM2EzMWFkOGVkZTdmZDQ2NjY1MWVhZTFlZg==, error: Conference room does not exist +04/07/2021 15:23:19: prof: ERR: IQ error received, id: NzNlOWZkMTYtNDE2Mi00MWI5LTk2MGYtMGQzZjZjYTQ1NDcyZjIwODY3NDUxOTg5ZjdiMmU1MWExNGExMWZiZTE1MzVlYTNmYjA1ZWFjNWNlMThkMmRhYjIwM2QzY2EwNDI0NA==, error: Conference room does not exist +04/07/2021 15:23:19: prof: ERR: IQ error received, id: OGNjMTcyNzUtNzU3ZS00YmZiLWE1MDItM2IyOGJkMzc2OTZiMWIyMTVjMmMyM2RkNWY1ZTczMTgzNjE1Y2Q2OTM1NDNiOTg3NDBiYWM0YmE5NGE1NzlkOGMzNjA0ZWRlNzk5Zg==, error: Conference room does not exist +04/07/2021 15:26:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/404.city +04/07/2021 15:31:48: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:31:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:32:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 15:32:36: prof: ERR: IQ error received, id: OGUwZDI1YWUtYTcwZi00NTNhLWEyY2QtNmRjODQwNjdjNzRjMTFjZWQxYjZjZTYyMTliNjNmMmI1ZTk4NWZkMDM1MzVmMmEzNGNiMDU3M2ZjNzhiYWMxNzJmMDVmNzIyMjI5NA==, error: Request has timed out +04/07/2021 15:32:36: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 15:32:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 15:32:50: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 15:32:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 15:33:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 15:33:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 15:33:43: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 15:37:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:38:42: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:41:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 15:41:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 15:42:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 15:42:23: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 15:42:47: prof: ERR: IQ error received, id: YjBlOTY5YTQtMTRkMi00MGJkLTk3MWEtNjc1ODIwYTYxMTFjODRiMDU4M2QyMjE2YTc0N2ZkOGM4MWM2ZDliY2IyZWY0NzdlNjBiYjIwZjNkZjRiZTU1Y2RjYzY0MDhkNDhhZA==, error: Request has timed out +04/07/2021 15:42:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 15:43:35: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:44:36: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:45:12: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +04/07/2021 15:45:14: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +04/07/2021 15:46:08: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion +04/07/2021 15:46:26: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:46:28: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:46:41: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:46:46: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:47:02: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:47:32: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:49:32: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 15:49:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 15:49:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 15:49:39: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 15:49:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 15:49:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 15:49:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 15:50:04: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 15:52:14: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 15:52:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 15:52:25: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 15:56:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:57:40: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 15:58:29: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 15:59:50: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 15:59:51: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 16:00:06: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 16:00:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 16:00:18: prof: ERR: IQ error received, id: ZjQzYTBmMmMtMmJmYi00MTM0LTgyNzctMTA2Y2EzNzZhM2FkNmJhZjI5ZWJjYzgzYTkzNDM2NTg2ODY4Mjk0OGQwNDMwYjMyMzEzODNjODdhOTYyZDgzNTNlMDFjMWFiZmExNw==, error: Request has timed out +04/07/2021 16:00:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 16:00:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 16:03:19: prof: ERR: Message received without body for room: en@chat.404.city/support +04/07/2021 16:10:20: prof: ERR: IQ error received, id: ZWRlNDA1ZmYtZWM0Yy00ZTQ2LTgyMDctZThhMmU1NGQ0OTRjOGJhNzFkOTViNzJmOWVkODFhNmYxMDA4MmE4YmMxNmQ1ZWJjNTk0MWY0NjFiNTViNGE3YzQ1NzJhMTVhZjMxOA==, error: Request has timed out +04/07/2021 16:10:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 16:15:00: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 16:15:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 16:17:32: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 16:19:28: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 16:29:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 16:30:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 16:30:19: prof: ERR: IQ error received, id: YzQ0ZDkxZWUtZjdhOC00ODIxLTgxYzctMDJiMGU4NWZkOTliYzFmNzNkZDE5ZDhiNGZmMDhiNWZlNTg2MWMwMDQ1YTkwM2IxMjIzNDhmYzIyMmNlZmQ3NzAzM2FhNmUzYzI2Yg==, error: Request has timed out +04/07/2021 16:30:19: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 16:30:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 16:30:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 16:31:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 16:31:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 16:38:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian +04/07/2021 16:38:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian +04/07/2021 16:42:42: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 16:42:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 16:45:25: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 16:49:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +04/07/2021 16:49:31: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey +04/07/2021 16:52:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie +04/07/2021 16:52:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +04/07/2021 17:00:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:00:39: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:01:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:01:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 17:01:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:01:42: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 17:01:42: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 17:01:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 17:01:50: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:02:08: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:02:14: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:02:15: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:06:21: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +04/07/2021 17:07:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:07:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:07:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 17:07:44: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 17:07:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 17:07:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 17:07:49: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:09:32: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 17:09:32: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 17:11:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:11:30: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:13:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata +04/07/2021 17:13:21: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:13:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:14:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:15:45: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:16:14: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 17:16:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 17:17:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 17:32:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:32:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:32:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:32:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 17:34:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:35:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:40:52: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 17:41:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 17:44:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:45:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:46:41: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +04/07/2021 17:46:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:47:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:47:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian +04/07/2021 17:47:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian +04/07/2021 17:53:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 17:53:57: prof: ERR: Message received without body for room: en@chat.404.city/kraver +04/07/2021 17:54:46: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 17:55:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:55:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 17:55:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ +04/07/2021 17:55:17: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 17:55:33: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 17:55:34: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 17:55:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:55:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:55:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:56:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:57:37: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 17:57:40: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error +04/07/2021 17:58:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:58:29: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:58:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:58:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 17:59:03: prof: WRN: Generated sha-1 does not match given: +04/07/2021 17:59:03: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= +04/07/2021 17:59:03: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= +04/07/2021 18:00:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 18:00:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 18:01:03: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 18:01:03: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 18:01:21: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 18:01:21: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 18:02:08: prof: ERR: IQ error received, id: YTdmMTRkN2UtYWUxNi00NWRlLTg4YzYtYzI1ZGFiNmM1N2M5NTU2NGRmYjFiZDg5MjU3NWZhZGZiZWUyMjI4MjIzMzZiNWFkYWY4ZDFiNmEzZDJlNmVlYWU2YmRkY2U4ODYxMQ==, error: Request has timed out +04/07/2021 18:02:08: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 18:02:37: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 18:03:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 18:03:24: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 18:04:27: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 18:04:27: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 18:05:41: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +04/07/2021 18:06:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy +04/07/2021 18:08:05: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 18:08:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. +04/07/2021 18:09:03: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 18:09:24: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 18:11:14: prof: ERR: IQ error received, id: MDlhMWU4YWQtZjY0MC00YzFkLTk1ZWMtZmExZGI0OGU1M2I1NGNjNjdkNDJhNzY2YTljZGEwOWViMDA1ODQwNjBlNGRkNWQ3NjBlOGMwZTU2MjJjNDNmMjQyNjAyNTBmYTgyNQ==, error: Request has timed out +04/07/2021 18:11:14: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 18:17:42: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +04/07/2021 18:17:42: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ +04/07/2021 18:17:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 18:17:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 18:17:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 18:18:56: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:19:57: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 18:21:18: prof: ERR: IQ error received, id: NThjZjk0MjEtMzVjNC00ZjkzLThhNjEtMjAyZGFlNDA3NzA5ZGJkYTIwMjViZTNlODEyYjI3N2VmNmM1NjQ4YjEwOGUzMDg4ZThjOGYxNzg3MmY4YTI2ZTA0ZGViMWExMWE3Zg==, error: Request has timed out +04/07/2021 18:21:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 18:22:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] +04/07/2021 18:23:20: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:23:20: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:23:20: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:23:24: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:23:24: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:23:24: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:23:28: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:23:28: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:23:28: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:23:47: prof: ERR: IQ error received, id: MGMyNzgxODUtNjUwOS00YWIyLTlmZjMtOGJkYjA3ZDM4ZDNmZThhMWEwOTg1NWY1Y2ZkM2NhNWQ5NGRkYWIzY2UyNDZmMjY3ZDI2ZTM1OGE5Mjg5ZDgyM2M2M2MzMWZmNWQ3Yw==, error: Request has timed out +04/07/2021 18:23:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: +04/07/2021 18:23:57: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:23:57: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:23:57: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:24:40: prof: ERR: IQ error received, id: YWJhNWI5ODMtMmZhNy00MzFjLWE2OTEtODU2ZTljZGNlMzg2MWZmOWJhNDQ5NTBlNWI2YTUwMmJiMzIyYzc2MjA5NDIyNDlmYzNiNTA1OTMyMzY0MzQzMTE1ODMxM2Q3NDgxMg==, error: User session terminated +04/07/2021 18:24:53: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:24:53: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:24:53: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:24:53: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:24:53: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:24:53: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:24:53: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:24:53: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:24:53: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:24:59: prof: WRN: Generated sha-1 does not match given: +04/07/2021 18:24:59: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= +04/07/2021 18:24:59: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= +04/07/2021 18:25:16: prof: ERR: IQ error received, id: MTI5MDFmZjEtMzQ4NC00N2JmLThiMDQtMmIzYWI1OTVmZDY4YmRjOTEzYmIxMzE2ZDVhZjg4Njg2YTI4MWRjM2QxNWNiMDlkNDg2OTAzNzg4Yjc5NDY4MWI5NGY0MmE2Yzk5Yg==, error: Request has timed out +04/07/2021 18:25:16: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: +04/07/2021 18:26:01: prof: ERR: IQ error received, id: OWRhZDY3N2UtZjI4OC00ZmQ4LTk3MTgtYTBiNGZjOTk0MGQ0MTY5ZjAzM2UxY2NiZjRjNGFhMDdiNmVmZmQ1MGE1MWRlZmY2YjA1NjIzODA5MjNlZTEyOTk2YTJjNTY4NDUwYQ==, error: Request has timed out +04/07/2021 18:26:01: prof: WRN: Error received for capabilities response from en@chat.404.city/sander: +04/07/2021 18:26:01: prof: ERR: IQ error received, id: NTYwNzMwMWEtZDMyNC00MzkyLTk3MGYtZTUxZTczOTUwNmY4MDhmNmE0MTA2OWQxYTlkMDdlYmJkMWU1MmNkZTc0NDUzM2UxNmNhMzIxNjdhZTFhN2E5ZmM4M2IzZjIxOWY4MA==, error: Request has timed out +04/07/2021 18:26:01: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 18:26:01: prof: ERR: IQ error received, id: NTk2MTZjYzUtZjE2ZS00ZDllLWJjZTctMWZkYmJiNzMwZWNkZjA4MjQyMzExNjEzNmRkMWQwOTZiY2JhNDFhYzAzYTJlNjM1MjYzMjQyZGNjOWFhZDQ4MWIxNTIyMDU1MjM2YQ==, error: Request has timed out +04/07/2021 18:26:01: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: +04/07/2021 18:26:24: prof: ERR: IQ error received, id: NGJhYzhkNTEtYTE4NC00NDNlLWI1NGQtM2VmMGVkYmRiZTVkM2U4MTYyZDE5OTUzZWU1NGIxMWQyNTU1OTg3OGU1ZTEzOWIxZTdiNzMzNTRjYzYxMzI3MTc0NDEzOTk4NTQ0Yw==, error: Request has timed out +04/07/2021 18:26:24: prof: WRN: Error received for capabilities response from en@chat.404.city/sander: +04/07/2021 18:26:24: prof: ERR: IQ error received, id: NjVkOTkwOGQtMWY4Zi00ZDFkLTgyOTEtNWQwYjJkMWIxYTFlODQ4NTNmZDNkMjk4MGU0MjI5NzEyMzE2YWI1MTBjNmFjMDQ4MWQwODNhZThiMWVlOTBlMDU0NDkzNjE4YmJjNg==, error: Request has timed out +04/07/2021 18:26:24: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: +04/07/2021 18:26:25: prof: ERR: IQ error received, id: ZjFhNjYxYWItZDIxMy00MTUzLWFiZDMtZWQ5OTgxODMxNTdiMDVkNDU2ZmIyYWM5MzNhYzM2ODNkZWM5MmY2ZjFjMjc5ZGNhNDdmZjVlZDVhY2E4YmE1Y2ZmOGFkMGE0Y2U0Nw==, error: Request has timed out +04/07/2021 18:26:25: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 18:27:11: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice +04/07/2021 18:28:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:28:36: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:28:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:28:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:30:09: prof: ERR: IQ error received, id: N2FlMTAyMGQtNGRkYi00NTI5LWI2MjQtM2IzYmZlYTJkZjFhZmM0OWZhOTc0YjE2Yzk4ODg2ZDY3NWE5MWIyZWI2Y2EwN2Y1Y2Q5NTU2MDliYjY4ZDY1Y2ZiYzMwMTI4MThhZA==, error: User session terminated +04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 18:30:09: prof: ERR: IQ error received, id: MmU4M2I4YTQtNjNjMi00NjkwLWE2OTctZDQ2Mjc5YmFhNDRhNjFjMzVmMDBjYjgzOWJlZmY5YjEwYjIzYmM1ODYxYWI1MGRkMjYwZTYyOGQwMWFhZTUwMGVlMmJlZmE3ZWEwYw==, error: User session terminated +04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 18:30:09: prof: ERR: IQ error received, id: YzVmOWJmMTItMjYxMy00OGU1LWIzYzctNDkxYmJlYTAxYjBlZjgyMjgwYzQwMjBjZTVmYzE2ODNlNDI5NjU0OTU3ZGFiOWZlMDkwZmQ2Y2VhNmVhNzJhMzFkZGRjZDNkYzk5Yw==, error: User session terminated +04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from operators@muc.xmpp.org/sander: +04/07/2021 18:30:09: prof: ERR: IQ error received, id: ZjgzZDZiZDUtMzUxNS00MTI4LTk3MzUtMzFmMzY1MTBlNTQwYWI2M2JmYThmZWIxMzJiNTU1OTJiYWRjY2ZlODEyZTAzNTliZjU0ZDg4MmNlMTNjZTg1MDM5YzEzM2JmOTA0Mg==, error: User session terminated +04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from operators@muc.xmpp.org/sander: +04/07/2021 18:30:35: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:30:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv +04/07/2021 18:32:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:32:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:33:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:33:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:33:30: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:33:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:33:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:34:01: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:34:09: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:34:14: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:34:24: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:34:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:34:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:34:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:35:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:38:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:38:58: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:39:03: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:39:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:39:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:40:23: prof: ERR: IQ error received, id: NjRkYTEwYTYtMzU1YS00ZWNlLTgzZjAtZTVhZjM4NjJhNjg0NzRjNjliOTFiMTM3NWM0YmNlYjEzZWNjNDk2ZDYxM2U0YTM2MDVkNzFlZGQwMTMyMzY1ZDMzMWI4OWE3ZGI4YQ==, error: Request has timed out +04/07/2021 18:40:23: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 18:40:34: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:40:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:41:13: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:44:02: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:44:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:44:57: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:45:51: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 18:51:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 18:51:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:51:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:51:22: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:51:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:51:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:51:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:51:59: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice +04/07/2021 18:52:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:52:28: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:52:32: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 18:53:20: prof: ERR: IQ error received, id: M2JjN2ZkMWEtZWQwNy00NTU2LWIxZGItODc5YTUzM2FlY2MyYmU5ODI0OGE5NDg2ZTQ5MjcyMjRiOWI4MjllZjIzNzg1N2VhNmJmZGY1ZTkxZDBjMGQ1Y2ZmZTdmNGZjNDA2NQ==, error: Request has timed out +04/07/2021 18:53:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 18:55:12: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:02:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:02:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:03:18: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:03:58: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:04:00: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:04:41: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:05:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice +04/07/2021 19:05:56: prof: ERR: IQ error received, id: ZTU5NGQ2ZDItOWMxNy00ODc3LTk0ZjItMGFkMWM0YjU4Y2NjMTI3ZjUzYThiNGEwMDYzMGUwNWUyOThjMzI2ZGIxZGU2OTc1YzE0Y2YwZTlmYjcwYTQyYjY2MGZiOGY5ZmVmYQ==, error: Request has timed out +04/07/2021 19:05:56: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 19:06:22: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:06:22: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 19:06:22: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 19:06:22: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:06:24: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:06:46: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 19:06:46: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:07:22: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:07:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:07:35: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:07:36: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:07:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:07:43: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 19:07:44: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:07:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:08:01: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:08:02: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:08:11: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:08:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:08:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:08:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:08:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:09:25: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice +04/07/2021 19:09:32: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:09:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:09:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:09:55: prof: ERR: Message received without body for room: en@chat.404.city/support +04/07/2021 19:09:58: prof: ERR: Message received without body for room: operators@muc.xmpp.org/404.city +04/07/2021 19:10:01: prof: ERR: Message received without body for room: operators@muc.xmpp.org/404.city +04/07/2021 19:10:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:10:17: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:10:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:10:27: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:10:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:10:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:10:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:12:00: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:12:14: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:12:41: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:12:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:12:46: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:12:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:13:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:13:44: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:13:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:13:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:13:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:14:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:15:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:15:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:15:20: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:15:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:15:40: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:15:51: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:16:06: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:16:06: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 19:16:10: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:16:19: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:17:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:17:23: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:17:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:17:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:20:16: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:20:22: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 19:20:22: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:20:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:21:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:21:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:21:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:21:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:21:46: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +04/07/2021 19:21:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:22:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:22:24: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:22:35: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:22:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:22:47: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:23:03: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:23:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:23:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:24:12: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:24:15: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:24:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:24:31: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:24:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:24:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:24:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:24:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:24:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:24:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:25:04: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:25:04: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 19:25:11: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:25:13: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:25:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:26:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:26:12: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +04/07/2021 19:26:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:26:47: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:26:57: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:27:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:27:08: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:27:22: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:27:30: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:27:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:27:42: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij +04/07/2021 19:27:42: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij +04/07/2021 19:27:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:27:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:27:49: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:27:57: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:27:58: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:28:01: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:28:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:28:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:28:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:28:51: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:28:53: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:28:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:29:14: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:29:15: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:29:17: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:29:25: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi +04/07/2021 19:29:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:30:37: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy +04/07/2021 19:30:55: prof: ERR: IQ error received, id: MmIyMzc1ZGItZTg0NS00MDdhLThjMzktYzVjYzM4MTI0OTA1YmE5NjkyN2JkYjNkNTA2OWRlMjU5Y2VhZmIyMjU2ODA4NTkzN2IwMDMwYzJkN2Y4YWJmNjMxMTg3MGNlNWNiMg==, error: User session not found +04/07/2021 19:30:55: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 19:30:56: prof: ERR: IQ error received, id: NmE2NDRjMTItYTU3Mi00MzkzLTlkN2UtY2IxODQ0ODlhOGM1YjlhNTYwYTE0MjVmMDc0NTRlMTIxYTY1YmU5OTBiMmNhNDAyYTgxZjJjZWQyMzE2YTQzNDQ4ZDJmYzNhOTExOQ==, error: User session not found +04/07/2021 19:30:56: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 19:31:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:31:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:31:35: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:31:44: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:31:53: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:32:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:32:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:32:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:32:36: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:32:37: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 +04/07/2021 19:33:10: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:33:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:33:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:33:37: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:33:40: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk +04/07/2021 19:34:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:35:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +04/07/2021 19:36:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:41:31: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:41:35: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:42:22: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:42:32: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:42:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:43:39: prof: ERR: IQ error received, id: ZWQzNjE5YWYtYzZjNS00ODA2LTg4OWEtOGE4MDkzNTBlNzQwMjVhY2ZkOWJhNTI3MTNmNGFmYmM2MzUxNjFkMGYxNTYyN2M1MGUxNjA4OTRjOTQ1OWFiMDViZWE2OTI5Yjc5Ng==, error: User session not found +04/07/2021 19:43:39: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 19:43:46: prof: ERR: IQ error received, id: ZTgyNmZjYmUtZmY2MS00Y2M1LTliNDMtYzFjZjhhMDlhZGZlM2M5OTA1M2FiNzE4MzA5MjI0MWRlNWE5ZjMwMmQ4MTE1MmViNTUxNDhlMzQyNjA3ODNiOTJhNDcyZDVhN2ExZA==, error: Request has timed out +04/07/2021 19:43:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 19:44:00: prof: ERR: IQ error received, id: NDNhYTc1NzQtYWEzMC00ODU3LTk3YzQtN2ZlM2M5MWE2YWUzMzcyODg4NTRjOWZiMzI4ZTNiMDliNDhkMjEyNDUyYzk0MjkxNTQ5MWZiODUyYzNlMjY3ODgxYjI0YWVjNzI5MQ==, error: User session not found +04/07/2021 19:44:00: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 19:44:09: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice +04/07/2021 19:44:10: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice +04/07/2021 19:44:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:44:39: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:44:42: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:45:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:45:48: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:45:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:45:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:46:58: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:46:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:46:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:47:03: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:47:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:47:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:48:07: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 +04/07/2021 19:48:40: prof: ERR: IQ error received, id: YjA4ZGQ3NDItZWFkYy00ODY5LWI5NzAtZWM3YTNmODhmYjlmOTgyZDcyM2I4ZmU5YzA5YWVlNGFjMzdjY2Y0MDI0Mjc1ZGFhMTI0NTQzZTZjYjY5ZDllMGY5MzliODIyNWIwNA==, error: User session not found +04/07/2021 19:48:40: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 19:48:40: prof: ERR: IQ error received, id: OTczNTgxOTItZTkxMC00NzE3LThhOWItN2U3YjBlM2FhZGUwYTFlZTU5ZGRhMDBhNTA2ZWZkNzczOWIwYjYxNjE3ZWE1NzU5MWIyNDAwZWYxYjI5OGI2YzNkYmMyYTgwNDY2Nw==, error: User session not found +04/07/2021 19:48:40: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 19:53:29: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:53:41: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:53:43: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:53:44: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:53:47: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:54:29: prof: ERR: IQ error received, id: N2NlZmNkMjMtNWZlYS00YWU5LTgxNmEtZjc5NGFlOWU4MzgzYmYwMDJlOWJjNjI0YTJlZWNjMjZmMTQyNmNkMjkxYmU3YmQ5MTI4OWFiYWIwNzM5OTY2NzM0N2VlNmQ1YWU3YQ==, error: User session not found +04/07/2021 19:54:29: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 19:54:29: prof: ERR: IQ error received, id: MmFmYTQ2YTktMGJjNi00ZWRkLWEyMDItM2IxNTVmYmUyNjE4Y2U2OTUxYzdkZWIwMGRmZDNmZDJjZTNhNzMzMGE0ZTEzN2I1NjFhNjNkYTcyZjkwZDU4MWM4MTIzMjJiNjAzNA==, error: User session not found +04/07/2021 19:54:29: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 19:55:13: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 19:55:13: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:55:15: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 19:55:15: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:55:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 19:56:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 19:56:37: prof: ERR: IQ error received, id: ZTJmMDkwNTAtZjljNi00MDE1LWIxNWMtOWVkNDA1ZjE0ZDhjNzcwMmYzY2U3Y2VhMjQ4Y2ZlZjdhNzJlYjE1ZTM3Njc1YzE2NDcxZDkzODNjOWI4YzBlOTQwY2ZlNmMxODUzNQ==, error: User session not found +04/07/2021 19:56:37: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 19:56:37: prof: ERR: IQ error received, id: YTJjZmFhNmEtNTgyMi00Y2FlLTkzNWQtMWU5ODJlYjZjNGJjZjAxZjE1ODZhNTZiYWNmM2ZkMDZhNzY0MDg1MjRkZDhiZDEzMmJmODEyMTE1NWQ5ZjUzYWZkMDY0NGFlY2FkYQ==, error: User session not found +04/07/2021 19:56:37: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 19:56:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:56:45: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:56:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:56:57: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:57:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:57:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:57:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:57:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 19:57:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:57:50: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:57:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:57:55: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:57:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:58:00: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:01: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:58:04: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:13: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 19:58:19: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:20: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:21: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:24: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 19:58:24: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:58:37: prof: ERR: IQ error received, id: ZmI0ZmRlNmEtNWY2OC00ZjNlLTgxYTItOTdiYzgwZWYwNzg1MjU3NjNmMmVmOTgwZGM1ZTgxNTJlMzQ5YTM5N2MwMDI1MDAyNmQ5MWYzMTMzY2Y2MjRkZGNkZDc0ZmVmNzcwMw==, error: Request has timed out +04/07/2021 19:58:37: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 19:59:00: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:59:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 19:59:07: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:59:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 19:59:33: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:59:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:59:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 19:59:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 19:59:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 19:59:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:00:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:00:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:00:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:00:19: prof: ERR: IQ error received, id: ZWZiZmUwMjMtZDlmNi00MGE4LTllNWUtYTlmZDY0ZDdjNjUyZGRiOWRlOTYyYjIxMWYzZWJhZGQ4NDAwMjE1MDRmZWFkYzlkY2FhZGQ1MTEzZjM3ODhmOWJiNTk0YmRjMzRlYQ==, error: User session not found +04/07/2021 20:00:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:00:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:00:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:00:49: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 20:00:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:00:50: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/lovetox +04/07/2021 20:00:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 20:00:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:02:03: prof: ERR: IQ error received, id: MTQ1N2ZkZmItNmQ4Mi00Y2U4LThlMGItMzJiZmE3MjYwNzU2ODI5MmQ5YTIxZmNhYzkzZjA5M2UyZjVjNWQzNTY3MWFjM2E3NWQzNGRkOGY3MzRjYThiM2NkZWM5ZWQwZTc5Ng==, error: User session not found +04/07/2021 20:02:03: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 20:02:03: prof: ERR: IQ error received, id: OGRjNjU2NzMtNDM2NS00NTJlLWIxNGMtNjY3NjViN2JmYTcwYWU3NTZlZjZlZTg2ZWY1ZWFjMjZjNWQzZDkxY2YxMjIyZWQ2ODFhNjM5MDFlY2E1YzI3NTc1ZDNiZGZlOTRlMg==, error: User session not found +04/07/2021 20:02:03: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:02:15: prof: ERR: IQ error received, id: YjBiZGQ2YTItYTE2Zi00OWM1LWI2YWUtZjc4MjUxZGFjZDE1MjU4ZWVmYTJjOWNhZmQwZTkyYTk3MzhhNWUzMThhZTBhMjIyNzRiNjA3NDcxYzA4MWIzOGU4ZGE2ODEyMGQ3MQ==, error: User session not found +04/07/2021 20:02:15: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: +04/07/2021 20:02:15: prof: ERR: IQ error received, id: ZGJlN2RmMzYtZDc4Yy00YTFhLWE3NmItYzMyNjU0OTc1OTUyNWU5OWRiMzVhNTgyYjkzOTkxMGMxMTg0OGVkNjE3YzA5ZDcyZWExYjYzY2I2ZGRjODk4MTczY2U1MDA5MDEzYg==, error: User session not found +04/07/2021 20:02:15: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:03:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:03:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mirux +04/07/2021 20:03:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:04:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:04:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:04:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:04:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:05:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:05:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:05:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:05:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:05:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:05:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:06:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:06:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:07:21: prof: ERR: IQ error received, id: NTEyYzVlZTAtMjM3YS00ZTg1LWIxNTEtM2YyNDllZjUwZWY3MzU3MTFjNzExOTdkNmI4YTIwNDM4ZGQwZDU5ZGY0ZDE0OGMzOWVhOTk2ZTYyYmRmYjk0N2MwNWZlNGI5MjQxNA==, error: User session not found +04/07/2021 20:07:21: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:08:34: prof: ERR: IQ error received, id: YmU4NWFhNjUtYjRjNy00ZTJkLWE5ZWQtNzRhMGQxOTcwNDRlZWJhN2EwYzJjNDIwZDgyNDAzMTJhZmEzOTE2Yjg4NWM1YzU3MWU1MmU5NzJjMjk5NWUyM2Y2ZTExMDZjMjFjZQ==, error: Request has timed out +04/07/2021 20:08:34: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 20:09:36: prof: ERR: IQ error received, id: ZjgzYWMyMGItMjllOC00Yzk5LTlhZjAtZmZmMzQyNGI2OTFkNWU2MGY2ZTQyMWU2MTMxYTA5YzlkODcxMzIwNDdmNzZhNWFiN2YxMjI5MGJkZTdhZTE5OGRhMTYyMTFlZTM5Nw==, error: User session not found +04/07/2021 20:09:36: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:10:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:10:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:10:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:11:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:11:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:13:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:14:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:15:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:15:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:16:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:16:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:16:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:16:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:16:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:16:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:17:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck +04/07/2021 20:17:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lemoldu +04/07/2021 20:17:04: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lemoldu +04/07/2021 20:17:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:17:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:17:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:17:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:18:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:18:37: prof: ERR: IQ error received, id: ZjM0MTYzNWYtNjA1Ni00MTU2LTg4ZTktNGI3ZWQwZWJhN2I5NDNiMjViNjE5ODQ1MjgwZWQxZWIyMWMyNDIyMDAxZDUwNzFhMDY2NWY0YTlhOGIyM2NkMzc1NTE1ZmI0NzAxMQ==, error: Request has timed out +04/07/2021 20:18:37: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 20:19:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:19:16: prof: ERR: IQ error received, id: MTRjMjIzNzktODRjMS00NzU5LTg3NWItZTA2M2ZiY2UwNTdiYTNjOGEwZDFiYTNlOTdjZDVmOWZmODEyM2ZjYzA0NDBiZmMzYjRjZWJkMzNiOWE1MmM2MDM5YmJlNDhjZDA4MQ==, error: User session not found +04/07/2021 20:19:16: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:19:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:20:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mirux +04/07/2021 20:20:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:21:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:24:23: prof: ERR: IQ error received, id: ZmFkODI5YjMtNjBlNi00ZjdmLTllZTEtOTYyYWEzNjQ1NzMwZjA4NWJhNjJhZGZjM2Q2NDA1YTliZWYwMTljYzhlNjRkYjNiNGFhMjgzMmZjYzlkYzUyMzhiNTQyYWEzMWVmNQ==, error: User session not found +04/07/2021 20:24:23: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:26:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 20:26:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mirux +04/07/2021 20:28:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:29:24: prof: ERR: IQ error received, id: ZDc5ZmQyMzgtZTBhNy00NTgyLThlOTYtNzA0Y2E4OWJiM2I3Zjc0N2UwZjA5NDBjYTQ4MWI0Y2U2ZjFjMDFlZjQwYmNhZDY2ZDk5YjU5NGI4ZmNiODQyNTQyNDAyYTAyYWYzNg==, error: User session not found +04/07/2021 20:29:24: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:30:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:34:34: prof: ERR: IQ error received, id: YzMzOGM4ZTctZTQzZi00MjQ4LThjMDgtNWUzODc3ZmEyNzQ3ZDY4MmJlYmYyMDUxNzVmMTNjNWQyNTY1NTFlMzk0OGU4ZTA3NzJhNGVmM2RmNzdiYjEyZjQ2NGI2ODYzMjlmOA==, error: User session not found +04/07/2021 20:34:34: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 20:40:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:40:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:40:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:41:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:41:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:41:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:41:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:43:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 20:48:06: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 20:48:08: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 20:51:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 20:51:11: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ +04/07/2021 20:51:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:51:59: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 20:51:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 20:55:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 20:55:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 20:55:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat +04/07/2021 20:56:33: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 20:56:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 20:56:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 20:56:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 21:01:18: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 21:01:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 21:01:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 21:01:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 21:02:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 21:02:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 21:04:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 21:08:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo +04/07/2021 21:08:19: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo +04/07/2021 21:08:20: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo +04/07/2021 21:08:34: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo +04/07/2021 21:11:29: prof: WRN: Generated sha-1 does not match given: +04/07/2021 21:11:29: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +04/07/2021 21:11:29: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +04/07/2021 21:11:34: prof: WRN: Generated sha-1 does not match given: +04/07/2021 21:11:34: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +04/07/2021 21:11:34: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +04/07/2021 21:14:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:14:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:14:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:15:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:15:54: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:16:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:16:13: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:16:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:16:19: prof: ERR: IQ error received, id: ZjczNWRlODctMGUwMi00MjQyLTkzYjYtZWQ1M2M1MWJmODg5NThjYjlkMmUyOTM0OWUyMTI4YmNiNDQzNjczZmMwNTdjNzVkMWUzMGQ0ODQwNTNiMTg1ZDJiMmJiOWNmOTQ1MQ==, error: User session not found +04/07/2021 21:16:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 21:16:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:16:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:16:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:17:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander +04/07/2021 21:17:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:17:28: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander +04/07/2021 21:18:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:18:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander +04/07/2021 21:18:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 21:22:10: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:22:21: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 +04/07/2021 21:22:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:24:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:25:20: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:25:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:25:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:25:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:25:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:25:59: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:28:08: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:28:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander +04/07/2021 21:30:02: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:30:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox +04/07/2021 21:31:51: prof: ERR: IQ error received, id: NGYxNGNhZDYtYzQ5NS00Yjc5LWE1Y2YtM2MzYjMxNDIzYTNjYWM3NTc4OTdlMGY5Nzk1ZGZmMzgzMjg0NjNmOTg5ZjQ0ZmRkYzgzZmQ1NDRhOTM0ZTdiMDZkYzZiMDQyOGM2ZA==, error: Queries to the conference members are not allowed in this room +04/07/2021 21:31:51: prof: WRN: Error received for capabilities response from conversations-offtopic-reloaded@conference.trashserver.net/dvorak: +04/07/2021 21:32:14: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:33:16: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:33:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat +04/07/2021 21:37:17: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander +04/07/2021 21:39:25: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:39:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck +04/07/2021 21:40:23: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck +04/07/2021 21:40:26: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:40:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:40:48: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck +04/07/2021 21:40:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck +04/07/2021 21:41:40: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:41:50: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck +04/07/2021 21:41:53: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck +04/07/2021 21:42:06: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:42:11: prof: ERR: IQ error received, id: MGNlMDgyOTgtOGFhYi00ZmE4LWE1MjEtOTVkMzdkNjc0ZGFjNWFmYzgzZjI0NmFjYzE0Mzg3OTNjMjc0MzQxOTM5NDBlYWUyNDI5NjU0MzExNDc1MWI2NzM3YTllMTRkMjRjMA==, error: Request has timed out +04/07/2021 21:42:11: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/latino: +04/07/2021 21:45:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:46:53: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:47:54: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:48:04: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:49:22: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:50:31: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 21:50:41: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:51:01: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:51:01: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 21:51:12: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 21:51:54: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:52:28: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:52:28: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:52:31: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:52:37: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:52:51: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 21:52:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin +04/07/2021 21:53:11: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:54:10: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin +04/07/2021 21:54:36: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:54:42: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin +04/07/2021 21:54:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin +04/07/2021 21:54:58: prof: ERR: IQ error received, id: MTdlYmEwN2QtMzRiNi00NzRkLTg3YzAtZDUyZDk1MTkzY2E1OGNiNmE1ZjlhNDJmNjA5ZjM1YjQwNWY2NGE1MzQ0ZjdhZmYzY2EyYTQxMGIzZmZlNTk2NzM2NGE2OWVhZTExNw==, error: User session not found +04/07/2021 21:54:58: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 21:56:14: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:57:14: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:58:37: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 21:59:23: prof: ERR: Message received without body for room: floss@rooms.dismail.de/klausmcm +04/07/2021 21:59:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:00:03: prof: ERR: IQ error received, id: MmQzMzZjMjYtNzM2OC00YzcxLTkyMjItMTUwNjQ0MDRjNGU2MTY3N2UyNzg5MDc4ZWMxNzg4ZDYzZGVjMTM1MmE3M2MxYjhkYWJiYTg0ZDRjMWM1MGU5MDY0MmM4MjZkOTRhYw==, error: Request has timed out +04/07/2021 22:00:03: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/dev: +04/07/2021 22:00:43: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:01:19: prof: ERR: Message received without body for room: en@chat.404.city/poggerino +04/07/2021 22:01:44: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:01:58: prof: ERR: IQ error received, id: MGMzYTUyNGUtNjEzMy00ZmFiLTg0NzgtZTJkNGMxNTY3OGZjODZmZGFlYzAxMDUzZjJmMDM5ZWUzNmNkZGI4NjhmZTYzOGI4MzJiMWU5NjFkZDcwNTRkZWI3MTRiYjUzOTllNQ==, error: User session not found +04/07/2021 22:01:58: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:03:38: prof: ERR: Message received without body for room: en@chat.404.city/poggerino +04/07/2021 22:03:43: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:04:43: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 22:04:45: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city +04/07/2021 22:05:16: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:06:02: prof: ERR: IQ error received, id: ZDJlYjBiNGUtZDc3Zi00ODA0LWI5NmEtODc4OGI2MzBjMjAzZmIwYzkwODMwYzg5NGYwMDgxMmExMWYwZjc1NThjNTJkYmIzOGQ5MDM0M2RkNDE0NDk1OTExMTE5ZDI2MWMyNA==, error: User session not found +04/07/2021 22:06:02: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:06:21: prof: ERR: Message received without body for room: en@chat.404.city/a +04/07/2021 22:09:22: prof: ERR: IQ error received, id: M2UyOGZiM2QtMWNjMC00YjJlLWE1NmUtOGY1MDc1OWU1ZmQ2YzI2ZGQwNzUyMTA3MTIyMDA1M2VlOTI3M2ZlMTViMmU0YzE0ZTNkYTY4MjVkNjVhYjIzZmE2OWU5ZWEzNDhlMQ==, error: Request has timed out +04/07/2021 22:09:22: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 22:10:02: prof: ERR: IQ error received, id: NDNmODNkNzAtN2ZiYy00OTRmLWJiNWItNTI5NmE5MTExMTRiNzhjZWQ5ZDJiOGE2YTU2YzU1YTk5NTZhZmZmZDUwMGM0N2I4NGQ1MTdkNGZhYmZmY2EwYzNiNDU3ZTViZTViZQ==, error: User session not found +04/07/2021 22:10:02: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:10:20: prof: ERR: IQ error received, id: ZDllODgwYzYtZjY4Yy00OTdhLTkyYzEtMDBjNGYzOGNhYjhhZjkwZTRiZWQ3NjA1Y2VhMzI5OGQ3M2U1NzRhYzcwNDRmNWE1ZTE0MWMzNTZjZTNiYjQxZmM3Yzk5N2U2YzU5Zg==, error: User session not found +04/07/2021 22:10:20: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:12:25: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 22:12:36: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 22:12:42: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 22:12:44: prof: ERR: Message received without body for room: chat@dino.im/wkg +04/07/2021 22:19:22: prof: ERR: IQ error received, id: NjZiZGUwNDEtYWJkZS00NDk0LWI5NWUtZjQ5NTc2MTg4N2QyMTk1ZTM5MmM1MTg1N2M4ZDYyNjBlZjM1NWI3YWYyOGM2NzE2NDljNjlhZjcyYWY2MjhlMDM3NjBhMjVlOWU5Ng==, error: Request has timed out +04/07/2021 22:19:22: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 22:20:19: prof: ERR: IQ error received, id: ZTZiZDdiMjktY2E0Mi00M2I1LWEzOTctNjI3NTBlNjZhNGJiMmI5OGE5YzdkZWI5NzY2MjRhYjJmMTU3NGIwOTRiY2RkOGI3NmZiYjJmMWIwMDYxNjY5MTY1ZTM1NmZmM2Y4Yw==, error: User session not found +04/07/2021 22:20:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:21:04: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:21:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 22:21:24: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ +04/07/2021 22:24:34: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 22:24:35: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 22:25:13: prof: ERR: IQ error received, id: NDFjNWI1MGEtZTk5MC00MzQzLWE5ZTgtZjI3ZDEwNzQxMmViOTI5NTI2MzhlYjkzZjU1N2E3NWMyYjA2Mzg0NWVhMDQ1MmEzNmViNTU2Yzg3ZDkwZjQyN2ZjODgyMTBjNmY3Zg==, error: User session not found +04/07/2021 22:25:13: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:25:14: prof: ERR: IQ error received, id: M2QzMjgyNjItYzMwNi00YjliLWExZDctOGJjMDdhMjlmMmNhZThmZDgyNTNlOWUyZDQwZGRiZWNmZDY4MmQwZWQyZDkyZjc0MzM1OTQxYzc1NDdlMDRiZjE5MWMwZTMzYzExZQ==, error: User session not found +04/07/2021 22:25:14: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:26:10: prof: ERR: IQ error received, id: ODFkNTAyOWMtYThhZS00ZTQ0LTkzZjctNjRkZDRmNmY0NzNmODg5ZGM4MTRjOTk4ZTFiY2I3MGRlNTc2NmMxMjVmMjc5ZjE1NDkwNDUxYjE1NzlkN2YzYWI0YWUyMzcyZTkzMw==, error: User session not found +04/07/2021 22:26:10: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:26:41: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:26:57: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:26:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:27:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:27:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:27:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:27:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:27:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:28:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:28:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:28:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:28:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux +04/07/2021 22:28:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:28:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:29:24: prof: ERR: IQ error received, id: MzhkZjc2YWUtN2I0NC00MTM2LTg1NjktMmM1N2E0MDk0ZDU1ZjY5ZTJkOWQ1MzdhODdlZWY5ZTg0MzMxNGM4ZmFhZjkxYzY1MjdhYzMzMDA1MTRlY2Q2Njk3MTc1OGEzZWIwMQ==, error: User session not found +04/07/2021 22:29:24: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:29:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:29:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:29:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:29:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:30:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:30:17: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] +04/07/2021 22:30:17: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] +04/07/2021 22:30:17: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien +04/07/2021 22:30:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:30:44: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:30:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:30:52: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:30:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:31:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:31:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:32:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:32:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:32:37: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:32:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:34:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:08: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:34:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:34:59: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:34:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ +04/07/2021 22:39:22: prof: ERR: IQ error received, id: ODE1NDI0YzYtYjQxYy00ODcyLTliZGYtNDc1N2E5NTM2NWI1Yjg0MGVhMTg2YjFkYjUyMDFiNDg4YzI0ZTQ0YjQ2MWQ3OWQ3MWVjYjA0MTNiNzY5MDFhY2UxODdkMTIzNzlkMg==, error: Request has timed out +04/07/2021 22:39:22: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 22:40:20: prof: ERR: IQ error received, id: NzViM2FmN2EtOGRhNy00MmNjLWEyYzUtYjk1YWRlMGNkNjNkZTA4YzZiZTliMWU1NGIxNDVhM2Y3MTEzYTZhZDkwODk3ODgzMmIzOTI4ODZlMzhjYjhkYTExMGE0NzQ3ZDJkYQ==, error: User session not found +04/07/2021 22:40:20: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:41:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 +04/07/2021 22:41:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:41:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:44:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:45:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:45:31: prof: ERR: IQ error received, id: ZTFiM2EzMGYtOTVmYy00OGZkLWE5OTEtNjNjOTk0Zjg1OGU2NDA3MWRmYzZjYWZmYjBmNWJjNDRkYjJkY2FkYjVjMWExZTdhZjQyZGNjMzBlYjM1YzA1NmVlNzgzNWU4MmRiMA==, error: User session not found +04/07/2021 22:45:31: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:48:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 22:50:19: prof: ERR: IQ error received, id: YzUxZTlhNTktZWEwZi00YWRiLWE0YjgtZThkOWJlODEwODM0Y2UzYjQ4ZmEyMDZhOTdiMzBjODJlY2VjZGZkMTFjYWRiZDRiMTYxMDAxMWZjZjBmNWZjNmU3MjI5YTQ3NmMxOA==, error: User session not found +04/07/2021 22:50:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:50:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:51:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ +04/07/2021 22:52:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:52:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:52:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:52:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:52:56: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:53:58: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:54:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:56:07: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:56:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:57:26: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:58:03: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:59:04: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 22:59:48: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:00:50: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 23:01:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:01:46: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 23:03:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:03:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:03:36: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +04/07/2021 23:03:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:04:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:04:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:04:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:05:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:05:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:05:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:05:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:06:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 +04/07/2021 23:06:54: prof: WRN: Generated sha-1 does not match given: +04/07/2021 23:06:54: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= +04/07/2021 23:06:54: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= +04/07/2021 23:07:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:07:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re +04/07/2021 23:10:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:11:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:12:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:13:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:14:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:14:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine +04/07/2021 23:16:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:16:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine +04/07/2021 23:17:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:17:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:18:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:18:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:18:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:18:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:18:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:18:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine +04/07/2021 23:19:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:19:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:19:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:19:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:19:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o +04/07/2021 23:19:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine +04/07/2021 23:21:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:25:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:26:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:27:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 +04/07/2021 23:27:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:27:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:28:05: prof: ERR: IQ error received, id: YzEwYjRkMTQtMzQ1ZC00ZGM5LTk4ZDctOWZmNzVhZmE3MzkzMDU0OWMwMDk2YzQzYmUzMDk5NzU0MWE3MDUwNDViOGJlYWE4ODVmMTdjNjdmNDkzOGM0MzYxZjUzOGFhNTgyMQ==, error: Request has timed out +04/07/2021 23:28:05: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 23:29:15: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 23:29:24: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff +04/07/2021 23:29:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +04/07/2021 23:38:06: prof: ERR: IQ error received, id: YzE2YTA0ZDItMTBjNy00NzY2LTg1NDQtYWM4MTExN2EwYjgyNWEwYmVhMGJhNTAxMDIwOWMzYjExMmViMmI4YjI5OTk1NzIzYzBiOGU1YzAzZmE2MzJmOThhZmFjYzYxNDNjZQ==, error: Request has timed out +04/07/2021 23:38:06: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 23:40:01: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:40:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/chunk9 +04/07/2021 23:40:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/chunk +04/07/2021 23:40:34: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:40:44: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:40:52: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:41:02: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:41:05: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:43:32: prof: ERR: IQ error received, id: NWQ3ZjAzMDktYTAyYS00MWMyLWE1MTUtYWJjZGViMzQ4ZTNkNmZkNzQ2M2U1MjYzYzJkNDIzMjVjNWQxYjhkZTIxMmU3ZTNjZWRiN2JmYWE0Y2FjYjU3NzdhNzM1YjRhODU1Mw==, error: Request has timed out +04/07/2021 23:43:32: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 23:43:41: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:47:20: prof: ERR: Message received without body for room: en@chat.404.city/jordyn +04/07/2021 23:50:12: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +04/07/2021 23:50:23: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +04/07/2021 23:50:32: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +04/07/2021 23:53:33: prof: ERR: IQ error received, id: Y2YxNWZjZDAtNDhlOC00OTkwLWE3YzktMjk3NzJhYjNkZDA2NWI5YmE4ZWIyMDA0MmM5MmFiODIyNDY4ZmViYjA2OTc5ZWU4Mzg4N2U0MTBmMmI3M2NkNjEyZWI5NGE3NjRlOQ==, error: Request has timed out +04/07/2021 23:53:33: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +04/07/2021 23:53:42: prof: ERR: Message received without body for room: hmm@conference.hmm.st/wgreenhouse +04/07/2021 23:59:25: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +04/07/2021 23:59:35: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +04/07/2021 23:59:36: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +04/07/2021 23:59:46: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +05/07/2021 00:00:10: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +05/07/2021 00:00:21: prof: ERR: IQ error received, id: MTNhZDIwZDQtZTdiNC00M2Y0LWI3MTgtODBjYTQyN2U5OTBmMmQ3NjY1Y2Y2NWVjNzJkZjIyODFiYjQ1ZjgzYjEyNDRjNDhhMzdiZjYxYjlhNjQzNDUwMzBmYjdhMjRmYzBkYg==, error: User session not found +05/07/2021 00:00:21: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +05/07/2021 00:00:47: prof: ERR: IQ error received, id: MmZlYmIxMjUtNjJhMy00Y2E1LTkyZTEtZDZhMjFmNTg5YjAzMTJkZDMwNDY4OGE0ZDU1Y2QxYzYyZDA4YjM4NTg4M2E5MDNhNzcxMjAzNDQxYmQzYzBkYTU5NzE5MWYwNzZkMQ==, error: Request has timed out +05/07/2021 00:00:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +05/07/2021 00:01:17: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn +05/07/2021 00:05:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +05/07/2021 00:07:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +05/07/2021 00:08:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +05/07/2021 00:08:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +05/07/2021 00:11:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +05/07/2021 00:11:16: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann +05/07/2021 00:20:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +05/07/2021 00:20:20: prof: ERR: IQ error received, id: Y2I5NzNmNmItZmNhZi00ZWNhLTk3MDktMTgyMDgxOWViMDg5YjM5M2M5NDhiMWJhNjcxMDQzNmUyMGFhYzljNDk5M2UyYzkzN2ZlOWY4YWYyZDBlZmZjYmQ2NGYzYmQ2ZjVmMg==, error: User session not found +05/07/2021 00:20:20: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +05/07/2021 00:22:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom +05/07/2021 00:30:46: prof: ERR: IQ error received, id: NjMxNjhkNjQtNDg1NC00NzYwLWJkMWYtNTQ5ZjM4NjczZWY4ZTM0ZmQ1NTQ5YTEyNjlhZjZkOWY2YWFlZjQ0MzMyZmVhYjUxYzI5ZjQwODgzZTA3ZDlhMjBiMDc1YzNiN2QxNQ==, error: Request has timed out +05/07/2021 00:30:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: +05/07/2021 00:35:22: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +05/07/2021 00:35:55: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +05/07/2021 00:36:18: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk +05/07/2021 00:39:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 00:40:39: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +05/07/2021 00:40:41: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz +05/07/2021 00:41:11: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 00:47:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 00:51:30: prof: ERR: IQ error received, id: MWNhZTE4ZjUtZGYwNi00YzQ0LThlMjYtNDE3MmI0MDMxZTkzNTk1NzE0NmMxMWEyYmYzYTg1YWFiMDBiMGI4MjQ3MzUzNWI0ZmUzZTUyY2IxYjQ3ZmRmMWEzMDk3MjZkNDU1YQ==, error: User session not found +05/07/2021 00:51:30: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: +05/07/2021 00:54:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 00:59:00: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:06:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:06:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:06:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:06:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:06:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:06:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:07:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:07:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:07:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:07:35: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:07:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:07:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:08:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:08:08: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:08:38: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:08:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:08:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:10:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:11:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:11:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:11:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:11:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv +05/07/2021 01:11:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:11:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:13:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:13:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:14:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:14:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:16:12: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +05/07/2021 01:16:18: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +05/07/2021 01:16:20: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +05/07/2021 01:16:25: prof: ERR: Message received without body for room: en@chat.404.city/alex11 +05/07/2021 01:16:25: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 +05/07/2021 01:17:28: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 +05/07/2021 01:19:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:19:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:21:37: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:25:43: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 +05/07/2021 01:25:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie +05/07/2021 01:26:46: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 diff --git a/result b/result new file mode 120000 index 0000000..28f4fce --- /dev/null +++ b/result @@ -0,0 +1 @@ +/nix/store/0nlcxz4fp2zhpjm67wng1g05vv37xiwk-catt-0.12.1 \ No newline at end of file diff --git a/xmpp/presence.c b/xmpp/presence.c new file mode 100644 index 0000000..94a367d --- /dev/null +++ b/xmpp/presence.c @@ -0,0 +1,48 @@ +// 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 + +xmpp_stanza_t *stanza__presence(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, char *ns, + char *from, char *to, char *type) +{ + xmpp_stanza_t *parent = base ? base : xmpp_presence_new(context); + xmpp_stanza_t **child = children; + + if (ns) + { + xmpp_stanza_set_ns(parent, ns); + free(ns); + } + + if (from) + { + xmpp_stanza_set_from(parent, from); + free(from); + } + + if (to) + { + xmpp_stanza_set_to(parent, to); + free(to); + } + + if (type) + { + xmpp_stanza_set_attribute(parent, "type", type); + free(type); + } + + while (*child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child); + + ++child; + } + + return parent; +} diff --git a/xmpp/stanza.h b/xmpp/stanza.h new file mode 100644 index 0000000..7273024 --- /dev/null +++ b/xmpp/stanza.h @@ -0,0 +1,12 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_STANZA_H_ +#define _WEECHAT_XMPP_STANZA_H_ + +xmpp_stanza_t *stanza__presence(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, const char *ns, + const char *from, const char *to, const char *type); + +#endif /*WEECHAT_XMPP_STANZA_H*/ From 668eb4ace1d243621a45c3bf0a791ab7ae38fc63 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 5 Jul 2021 17:33:26 +0100 Subject: [PATCH 098/118] readme and keepalives --- README.org | 5 +++++ account.h | 18 +++++++++++------- connection.c | 9 ++++++++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.org b/README.org index 1392315..e9a615f 100644 --- a/README.org +++ b/README.org @@ -94,6 +94,7 @@ * [X] Allow /close without crashing * [ ] [#B] Handle wide errors gracefully * [ ] [#B] Event-driven MUC entrance + * [ ] Pings * [ ] MUCs * [X] Opening (/enter) * [ ] Leave on /close @@ -127,6 +128,10 @@ Please submit a pull request or create an issue to add a new or missing feature. +* Testemonials + + "Weechat-Strophe - for the discerning dual IRCer XMPPer" -- [[github.com/janicez][Ellenor et al Bjornsdottir]] + * License weechat-xmpp is licensed under the Mozilla Public diff --git a/account.h b/account.h index 8fff73c..9ca38a8 100644 --- a/account.h +++ b/account.h @@ -31,14 +31,18 @@ enum t_account_option weechat_config_option_set(account->options[option], value, 1) #define account_jid(account) \ - weechat_config_string(account->options[ACCOUNT_OPTION_JID]) + 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) \ - 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") + 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) \ diff --git a/connection.c b/connection.c index d224586..7010a36 100644 --- a/connection.c +++ b/connection.c @@ -460,7 +460,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, omemo__init(account); } else { - //xmpp_stop(account->context); + account__disconnect(account, 1); + //xmpp_stop(account->context); //keep context? } } @@ -482,7 +483,13 @@ char* connection__rand_string(int length) int connection__connect(struct t_account *account, xmpp_conn_t **connection, const char* jid, const char* password, int tls) { + static const unsigned ka_timeout_sec = 60; + static const unsigned ka_timeout_ivl = 1; + *connection = xmpp_conn_new(account->context); + + xmpp_conn_set_keepalive(*connection, ka_timeout_sec, ka_timeout_ivl); + const char *resource = account_resource(account); if (!(resource && strlen(resource))) { From 24e1df64b0ac7489a5cb33706986e77ca7bd2070 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 5 Jul 2021 22:50:38 +0100 Subject: [PATCH 099/118] edits and highlights! --- .dir-locals.el | 2 +- Makefile | 1 + README.org | 20 +- account.h | 2 + channel.c | 28 +- command.c | 82 +- connection.c | 61 +- profanity | 3790 ------------------------------------------------ result | 1 - xmpp/iq.c | 102 ++ xmpp/stanza.h | 11 +- 11 files changed, 272 insertions(+), 3828 deletions(-) delete mode 100644 profanity delete mode 120000 result create mode 100644 xmpp/iq.c diff --git a/.dir-locals.el b/.dir-locals.el index 671bf21..178235e 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -14,7 +14,7 @@ "-ex 'handle SIGPIPE nostop noprint pass'" ,(concat "--args weechat -a -P 'alias,buflist,exec,irc' -r '/plugin load " (expand-file-name "xmpp.so" (projectile-project-root)) - "'")) + "'; /debug tags")) " "))) (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) (flycheck-clang-language-standard . "gnu99") diff --git a/Makefile b/Makefile index 0fa960d..8023aa7 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ SRCS=plugin.c \ omemo.c \ user.c \ xmpp/presence.c \ + xmpp/iq.c \ DEPS=axc/build/libaxc.a OBJS=$(subst .c,.o,$(SRCS)) diff --git a/README.org b/README.org index e9a615f..8d1fc0b 100644 --- a/README.org +++ b/README.org @@ -94,13 +94,18 @@ * [X] Allow /close without crashing * [ ] [#B] Handle wide errors gracefully * [ ] [#B] Event-driven MUC entrance - * [ ] Pings + * [ ] [#C] XMPP Ping (xep-199) + * [X] [#A] Highlight * [ ] MUCs * [X] Opening (/enter) - * [ ] Leave on /close + * [ ] [#B] Leave on /close * [X] Receiving * [X] Sending + * [X] With /msg * [ ] [#B] Edits + * [X] [#B] Displaying + * [X] [#B] Tagging + * [ ] [#B] Making * [ ] [#B] Handle errors gracefully * [X] [#B] Presence/nicklist * [X] [#B] Enters @@ -111,11 +116,14 @@ * [ ] Presence * [X] Disco * [ ] Disco response + * [ ] Key Generation / storage (secured_data?) * [ ] Messages - * [ ] MUC PMs - * [ ] Send typing notifications - * [ ] Recv typing notifications - * [ ] Read receipts + * [ ] [#C] MUC PMs + * [ ] [#A] Send typing notifications + * [ ] [#A] Recv typing notifications + * [ ] [#C] Read receipts + * [ ] Service Disco + * [ ] Bookmarks / Roster * [ ] OTR (libotr) * [ ] PGP (libgpgme) ** TODO [#C] Implement completion engine (milestone v0.3) diff --git a/account.h b/account.h index 9ca38a8..dd196be 100644 --- a/account.h +++ b/account.h @@ -74,6 +74,8 @@ struct t_account struct t_gui_buffer *buffer; char *buffer_as_string; + //struct t_device *devices; + //struct t_device *last_device; struct t_user *users; struct t_user *last_user; struct t_channel *channels; diff --git a/channel.c b/channel.c index 4732b98..5803a7e 100644 --- a/channel.c +++ b/channel.c @@ -605,14 +605,14 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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(channel->buffer, "%s%s entered", - weechat_prefix("join"), - jid_resource); + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s entered", + weechat_prefix("join"), + jid_resource); else - weechat_printf(channel->buffer, "%s%s (%s) entered", - weechat_prefix("join"), - xmpp_jid_bare(account->context, user->id), - xmpp_jid_resource(account->context, user->id)); + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) entered", + weechat_prefix("join"), + xmpp_jid_bare(account->context, user->id), + xmpp_jid_resource(account->context, user->id)); return member; } @@ -654,14 +654,14 @@ struct t_channel_member *channel__remove_member(struct t_account *account, 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(channel->buffer, "%s%s left", - weechat_prefix("quit"), - jid_resource); + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s left", + weechat_prefix("quit"), + jid_resource); else - weechat_printf(channel->buffer, "%s%s (%s) left", - weechat_prefix("quit"), - xmpp_jid_bare(account->context, user->id), - xmpp_jid_resource(account->context, user->id)); + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) left", + weechat_prefix("quit"), + xmpp_jid_bare(account->context, user->id), + xmpp_jid_resource(account->context, user->id)); return member; } diff --git a/command.c b/command.c index 47547db..ccd9fa8 100644 --- a/command.c +++ b/command.c @@ -544,9 +544,64 @@ int command__open(const void *pointer, void *data, return WEECHAT_RC_OK; } +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; + xmpp_stanza_t *message; + char *text; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_channel) + { + weechat_printf ( + ptr_account->buffer, + _("%s%s: \"%s\" command can not be executed on a account buffer"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "msg"); + return WEECHAT_RC_OK; + } + + if (!ptr_account->is_connected) + { + weechat_printf(buffer, + _("%s%s: you are not connected to server"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + text = argv_eol[1]; + + message = xmpp_message_new(ptr_account->context, + ptr_channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", + ptr_channel->name, NULL); + xmpp_message_set_body(message, text); + xmpp_send(ptr_account->connection, message); + xmpp_stanza_release(message); + if (ptr_channel->type != CHANNEL_TYPE_MUC) + weechat_printf_date_tags(ptr_channel->buffer, 0, + "xmpp_message,message,private,notify_none,self_msg,log1", + "%s%s", + user__as_prefix_raw(ptr_account, account_jid(ptr_account)), text); + } + + return WEECHAT_RC_OK; +} + int command__me(const void *pointer, void *data, - struct t_gui_buffer *buffer, int argc, - char **argv, char **argv_eol) + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) { struct t_account *ptr_account = NULL; struct t_channel *ptr_channel = NULL; @@ -583,14 +638,18 @@ int command__me(const void *pointer, void *data, { text = argv_eol[0]; - message = xmpp_message_new(ptr_account->context, "chat", ptr_channel->name, NULL); + message = xmpp_message_new(ptr_account->context, + ptr_channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", + ptr_channel->name, NULL); xmpp_message_set_body(message, text); xmpp_send(ptr_account->connection, message); xmpp_stanza_release(message); if (ptr_channel->type != CHANNEL_TYPE_MUC) - weechat_printf(ptr_channel->buffer, "%s%s %s", - weechat_prefix("action"), account_jid(ptr_account), - text); + weechat_printf_date_tags(ptr_channel->buffer, 0, + "xmpp_message,message,action,private,notify_none,self_msg,log1", + "%s%s %s", + weechat_prefix("action"), account_jid(ptr_account), + text); } return WEECHAT_RC_OK; @@ -679,9 +738,18 @@ void command__init() if (!hook) weechat_printf(NULL, "Failed to setup command /open"); + hook = weechat_hook_command( + "msg", + N_("send a xmpp message to the current buffer"), + N_(""), + N_("message: message to send"), + NULL, &command__msg, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /msg"); + hook = weechat_hook_command( "me", - N_("send a xmpp action to the current channel"), + N_("send a xmpp action to the current buffer"), N_(""), N_("message: message to send"), NULL, &command__me, NULL, NULL); diff --git a/connection.c b/connection.c index 7010a36..dafaf5b 100644 --- a/connection.c +++ b/connection.c @@ -125,8 +125,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * struct t_account *account = (struct t_account *)userdata; struct t_channel *channel; - xmpp_stanza_t *body, *delay, *topic; - const char *type, *from, *from_bare, *to, *timestamp = 0; + xmpp_stanza_t *body, *delay, *topic, *replace; + const char *type, *from, *from_bare, *to, *id, *replace_id, *timestamp; char *intext; struct tm time = {0}; time_t date = 0; @@ -159,6 +159,9 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * return 1; from_bare = xmpp_jid_bare(account->context, from); to = xmpp_stanza_get_to(stanza); + id = xmpp_stanza_get_id(stanza); + replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", "urn:xmpp:message-correct:0"); + replace_id = replace ? xmpp_stanza_get_id(replace) : NULL; intext = xmpp_stanza_get_text(body); @@ -182,19 +185,46 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * date = mktime(&time); } + char **dyn_tags = weechat_string_dyn_alloc(1); + weechat_string_dyn_concat(dyn_tags, "xmpp_message,message", -1); + if (id) + { + weechat_string_dyn_concat(dyn_tags, ",id_", -1); + weechat_string_dyn_concat(dyn_tags, id, -1); + } + if (strcmp(to, channel->id) == 0) - weechat_printf_date_tags(channel->buffer, date, NULL, "%s[to %s]: %s", - user__as_prefix_raw(account, from), + weechat_string_dyn_concat(dyn_tags, ",private", -1); + if (weechat_string_match(intext, "/me *", 0)) + weechat_string_dyn_concat(dyn_tags, ",action", -1); + if (replace) + { + weechat_string_dyn_concat(dyn_tags, ",edit", -1); + weechat_string_dyn_concat(dyn_tags, ",replace_", -1); + weechat_string_dyn_concat(dyn_tags, replace_id, -1); + } + + if (date != 0) + weechat_string_dyn_concat(dyn_tags, ",notify_none", -1); + else + weechat_string_dyn_concat(dyn_tags, ",log1", -1); + + const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly + if (strcmp(to, channel->id) == 0) + weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s[to %s]: %s", + edit, user__as_prefix_raw(account, from), to, intext ? intext : ""); else if (weechat_string_match(intext, "/me *", 0)) - weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s %s", - weechat_prefix("action"), from, + weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s %s", + edit, weechat_prefix("action"), from, intext ? intext+4 : ""); else - weechat_printf_date_tags(channel->buffer, date, NULL, "%s%s", - user__as_prefix_raw(account, from), + weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s", + edit, user__as_prefix_raw(account, from), intext ? intext : ""); + weechat_string_dyn_free(dyn_tags, 1); + if (intext) xmpp_free(account->context, intext); @@ -458,6 +488,21 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); + children[1] = NULL; + children[0] = + stanza__iq_pubsub_items(account->context, NULL, + strdup("eu.siacs.conversations.axolotl.devicelist")); + children[0] = + stanza__iq_pubsub(account->context, NULL, children, + strdup("http://jabber.org/protocol/pubsub")); + children[0] = + stanza__iq(account->context, NULL, children, NULL, strdup("fetch1"), + strdup(account_jid(account)), strdup(account_jid(account)), + strdup("get")); + + xmpp_send(conn, children[0]); + xmpp_stanza_release(children[0]); + omemo__init(account); } else { account__disconnect(account, 1); diff --git a/profanity b/profanity deleted file mode 100644 index 1f43cca..0000000 --- a/profanity +++ /dev/null @@ -1,3790 +0,0 @@ -02/07/2021 22:30:43: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -02/07/2021 22:30:43: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -02/07/2021 22:31:56: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -02/07/2021 22:32:10: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:32:10: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:32:24: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -02/07/2021 22:32:56: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:32:57: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:33:10: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:33:12: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:33:12: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:33:14: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:33:17: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:33:20: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:33:20: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:33:29: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:33:41: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:33:44: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:33:44: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:33:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -02/07/2021 22:34:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:34:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:34:31: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -02/07/2021 22:34:33: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:34:33: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:34:36: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:34:38: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:34:38: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:35:14: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:35:16: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:35:16: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:35:18: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:35:21: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -02/07/2021 22:35:21: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -02/07/2021 22:38:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/ellenor@umbrellix.net -02/07/2021 22:38:29: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/ellenor@umbrellix.net -02/07/2021 22:38:54: prof: WRN: Generated sha-1 does not match given: -02/07/2021 22:38:54: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -02/07/2021 22:38:54: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -02/07/2021 22:39:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/ellenor@umbrellix.net -02/07/2021 22:39:44: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:39:53: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:39:57: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/Sarah Malik -02/07/2021 22:40:05: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/Sarah Malik -02/07/2021 22:46:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:46:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:46:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:46:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:46:10: prof: ERR: Message received without body for room: hmm@conference.hmm.st/qy -02/07/2021 22:46:51: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:47:05: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:47:10: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:47:20: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:47:37: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:47:50: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:48:09: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:49:08: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:49:28: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:49:48: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:50:32: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:54:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -02/07/2021 22:55:15: prof: ERR: IQ error received, id: NmIzOTExNmUtMzk0Yy00YjVlLWEwMjEtYjYzNzBmODhkYzI0ZDlmYTMxMmYzMDZjN2U1MTY1ODY2Yzk0YjA5OGU3NDhmNDM4MjBhOTNjYjliNDlhYjFhY2Q3ZWNhYTc5OTQ0ZA==, error: Request has timed out -02/07/2021 22:55:15: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -02/07/2021 22:56:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/qy -02/07/2021 22:57:01: prof: ERR: Message received without body for room: hmm@conference.hmm.st/acdw -02/07/2021 22:57:46: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:58:10: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:58:15: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:58:18: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:58:32: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:58:33: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:58:48: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -02/07/2021 22:58:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -02/07/2021 22:58:57: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:59:23: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 22:59:40: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:05: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:19: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:21: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:27: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:38: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:48: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:53: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:00:56: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:01:12: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:01:27: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:01:36: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:02:12: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:02:15: prof: ERR: Message received without body for room: hmm@conference.hmm.st/wgreenhouse -02/07/2021 23:02:23: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:02:54: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:03:01: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:03:44: prof: ERR: IQ error received, id: MmJhNmE2MWUtNzQzNi00MGNjLWI4MGYtZTIwMWNiYjhmYjk0NTdlYWI3NTQ1MTUyMmMwOGQ1NTA4OTM3OTcyM2FiM2I5ZmI2ZjVjYzE5NTlhOWYzZTFkNzllMjVkMGMxMDlhYg==, error: Request has timed out -02/07/2021 23:03:44: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -02/07/2021 23:03:45: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:04:03: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:04:22: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:04:26: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:04:35: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:04:46: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:05:04: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:05:43: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:05:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/elfchen -02/07/2021 23:05:59: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:06:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/elfchen -02/07/2021 23:06:06: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:06:22: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:06:44: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:06:46: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:06:55: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:07:00: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:07:04: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:07:13: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:07:35: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:07:44: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:07:52: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -02/07/2021 23:08:01: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:08:23: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:08:27: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:08:31: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:09:07: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:10:51: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:10:52: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:11:18: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:11:27: prof: ERR: Message received without body for room: chat@dino.im/512bit -02/07/2021 23:11:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit -02/07/2021 23:11:32: prof: ERR: Message received without body for room: chat@dino.im/512bit -02/07/2021 23:11:32: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit -02/07/2021 23:11:46: prof: ERR: Message received without body for room: chat@dino.im/512bit -02/07/2021 23:11:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit -02/07/2021 23:12:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:12:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:12:18: prof: ERR: Message received without body for room: chat@dino.im/512bit -02/07/2021 23:12:18: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit -02/07/2021 23:12:19: prof: ERR: Message received without body for room: chat@dino.im/512bit -02/07/2021 23:12:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit -02/07/2021 23:12:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:12:42: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:13:11: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:13:15: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:13:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:13:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -02/07/2021 23:13:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -02/07/2021 23:13:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:13:40: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:13:53: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:13:57: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:13:57: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:14:00: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:14:07: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -02/07/2021 23:14:07: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:14:10: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -02/07/2021 23:14:38: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:14:41: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:14:42: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:14:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:14:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:15:19: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:15:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:15:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:16:11: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:16:15: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:16:29: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:16:37: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:16:50: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:16:57: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:17:06: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:17:30: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:17:58: prof: WRN: Generated sha-1 does not match given: -02/07/2021 23:17:58: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -02/07/2021 23:17:58: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -02/07/2021 23:20:55: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:22:47: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:23:46: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:23:49: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:24:35: prof: ERR: IQ error received, id: ODE1ZWRmM2EtYjBhNi00M2M0LWFjYzctMjMwMmVhYTVmMzY3NzMyMGY1NjBjYjBiNzRkMWI2NGRhOTA3MmY0ZmUxNWQyY2Q4MWY2ZmZjNmI4NTdjOGZiZTAzYTEzNmFjN2UzYQ==, error: Request has timed out -02/07/2021 23:24:35: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -02/07/2021 23:26:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:26:10: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:26:11: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:26:17: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:27:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:27:55: prof: WRN: Generated sha-1 does not match given: -02/07/2021 23:27:55: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -02/07/2021 23:27:55: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -02/07/2021 23:29:08: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:30:35: prof: WRN: Generated sha-1 does not match given: -02/07/2021 23:30:35: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -02/07/2021 23:30:35: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -02/07/2021 23:32:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:38:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:38:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:43:26: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:45:43: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani -02/07/2021 23:45:51: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani -02/07/2021 23:45:57: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani -02/07/2021 23:46:11: prof: ERR: Message received without body for room: hmm@conference.hmm.st/kani -02/07/2021 23:46:32: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:46:49: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:46:56: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:50:44: prof: ERR: IQ error received, id: MWIwOWRhZDItNjZlYy00OTRmLWIyMzktNzIwNTYyMWRiZjhiNDMzYTg2MmFiZGE0NjNkODIyNGEzZWFkMGE0ZTIyNTY4MTQwMzdjODMzNDAxZDI3YzIzMWY3YTcwMjI0NDIxOA==, error: Request has timed out -02/07/2021 23:50:44: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -02/07/2021 23:51:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:51:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:52:17: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:52:53: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:52:55: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:52:59: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:53:16: prof: WRN: OMEMO: received a message with no corresponding key -02/07/2021 23:53:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:54:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:54:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:56:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:56:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:56:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:56:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:57:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:57:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:57:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:58:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:58:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:58:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:59:03: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:59:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:59:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -02/07/2021 23:59:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:00:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:00:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:00:10: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:00:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:00:43: prof: WRN: Generated sha-1 does not match given: -03/07/2021 00:00:43: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 00:00:43: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 00:00:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:00:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:01:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:01:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:01:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:01:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:12:58: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 00:13:04: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 00:13:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 00:14:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:14:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:14:26: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 00:14:31: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:14:32: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:14:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:14:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:15:41: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:15:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:19:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:20:44: prof: WRN: Generated sha-1 does not match given: -03/07/2021 00:20:44: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 00:20:44: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 00:33:17: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:33:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -03/07/2021 00:35:31: prof: ERR: IQ error received, id: Mjk0NWVmMjktNTgxZC00ZGExLWJkMjMtN2FkMWQzZDBhMDY1MDY3YjZkMmFiNjJkMmJkY2EyYTEwMjg1MTljM2MyYjRiZWUwYmYxYTFhYmZiNjY5N2M0MmY0NzY2MTE2YjEwMw==, error: Request has timed out -03/07/2021 00:35:31: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 00:40:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 00:55:31: prof: ERR: IQ error received, id: ZWM3NjA3NmMtMjgwNi00NDgzLWFmMTItYjFiYzY1NzM3ODAyZjZhYzYzOGZmZmVhODg5ZjMyOWI5ZmIwYWFmNmNiMGM3OTQ1YzQwOGQ3ZmIzYTcxZTI0NDAxN2U1MDA1Zjg1NQ==, error: Request has timed out -03/07/2021 00:55:31: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 01:01:38: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:03:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:03:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:03:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:04:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:04:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:10:14: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -03/07/2021 01:11:18: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -03/07/2021 01:15:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/qy -03/07/2021 01:20:30: prof: ERR: IQ error received, id: MTBkOTFmYzUtNzAwZi00MDFjLWFlNTUtNTlkNWI3Zjk0Nzk2OTk5MjQwMzQyZWE0NDkzZGRhYTc4YzRlNWEzOGQ2OGQ1MWQ1YmRkNTk4YjU5MTlhZmY3ZGM4ODYyNzJhZTFlZg==, error: Request has timed out -03/07/2021 01:20:30: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 01:31:05: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:31:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:32:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:33:04: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:34:09: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:34:28: prof: ERR: Message received without body for room: chat@dino.im/512bit -03/07/2021 01:34:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/512bit -03/07/2021 01:36:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:36:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:37:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:37:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:38:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/jcarloss -03/07/2021 01:38:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:39:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:39:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:39:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:39:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:44:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:44:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:44:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:44:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:45:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:45:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 01:51:25: prof: ERR: Message received without body for room: hmm@conference.hmm.st/ben -03/07/2021 01:52:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -03/07/2021 01:52:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 01:52:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 01:52:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 01:54:59: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 01:55:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 01:55:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 02:01:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 02:01:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 02:09:28: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris -03/07/2021 02:11:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris -03/07/2021 02:23:53: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -03/07/2021 02:23:55: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -03/07/2021 02:34:07: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:34:14: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:34:16: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:34:19: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:34:20: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:34:32: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:34:36: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 02:56:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 02:58:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 02:58:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 02:58:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:08:26: prof: WRN: Generated sha-1 does not match given: -03/07/2021 03:08:26: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 03:08:26: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 03:08:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:08:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:09:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:09:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:09:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:09:59: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 03:26:03: prof: ERR: IQ error received, id: YmIxMWEwODgtNjZkYS00ZmFjLWI1NWUtYTBiMTg3NjE0ZjkyMjg5MmE0ODM3YmY1ZjJiMTI1MzU5ZWVmMTc0ZDFhMjRhNjBmNTljMzNmOGE4OWNkNmVkYWNmNWFkNWVmNzY2Ng==, error: Request has timed out -03/07/2021 03:26:03: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 03:39:28: prof: WRN: Generated sha-1 does not match given: -03/07/2021 03:39:28: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 03:39:28: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 03:50:34: prof: ERR: IQ error received, id: OGIwZDY5NTYtNTc5NC00MDdiLTkzZTItNWIwYTdmNWFkNWYxZGUyZWEzMzU4NTZhZjc3MDcxYzU5YWZjNWY4YTc2MTljZWU1ZWMyYjYzMTJmZDUwMWY2NGI5YmI0NjRlNjI2NQ==, error: Request has timed out -03/07/2021 03:50:34: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 03:59:27: prof: WRN: Generated sha-1 does not match given: -03/07/2021 03:59:27: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 03:59:27: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 04:17:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:21:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:22:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:24:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:28:17: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/timothy -03/07/2021 04:30:39: prof: WRN: Generated sha-1 does not match given: -03/07/2021 04:30:39: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 04:30:39: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 04:37:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:38:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:38:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:38:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:38:35: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:46:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou -03/07/2021 04:46:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:49:24: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 -03/07/2021 04:49:25: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -03/07/2021 04:49:25: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 -03/07/2021 04:50:42: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -03/07/2021 04:50:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:50:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 04:51:17: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -03/07/2021 04:53:20: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -03/07/2021 04:53:54: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -03/07/2021 04:54:54: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -03/07/2021 05:09:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:10:09: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:10:09: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Ge0rG -03/07/2021 05:10:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:10:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:10:31: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:10:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:11:04: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:11:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:11:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:11:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:12:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:12:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:12:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:13:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:13:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:14:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:15:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:18:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:18:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:18:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:18:59: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:19:10: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:19:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Ge0rG -03/07/2021 05:20:09: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:20:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:22:38: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:22:42: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:23:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:23:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:23:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:24:24: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:24:28: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:29:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:32:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:37:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 05:38:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 05:39:09: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 05:44:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Axel -03/07/2021 05:49:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:49:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:50:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 05:53:04: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 05:53:52: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 05:53:58: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 05:54:00: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 05:54:26: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 05:54:49: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 05:55:30: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:08:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 06:09:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 06:09:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 06:09:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 06:09:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 06:10:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -03/07/2021 06:29:08: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:29:08: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:29:10: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:29:29: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:29:32: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:29:46: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:29:54: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:30:11: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:30:14: prof: ERR: Message received without body for room: support@room.pix-art.de/strar -03/07/2021 06:47:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:47:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:47:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:48:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:48:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:48:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:48:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:51:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 06:52:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:52:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:52:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:52:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:52:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 06:53:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 06:56:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 07:07:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 07:09:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:09:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:09:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:10:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:10:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:10:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:10:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:12:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:14:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:19:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:25:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:25:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:26:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:26:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:26:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:27:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:28:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:28:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:28:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:29:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:30:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 07:30:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:30:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:30:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:31:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:31:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:31:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:31:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:32:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:32:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 07:33:19: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn -03/07/2021 07:36:43: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn -03/07/2021 07:36:44: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn -03/07/2021 07:37:41: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn -03/07/2021 07:37:41: prof: ERR: Message received without body for room: en@chat.404.city/mukaltinn -03/07/2021 07:37:49: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -03/07/2021 07:37:55: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -03/07/2021 07:41:19: prof: WRN: Generated sha-1 does not match given: -03/07/2021 07:41:19: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 07:41:19: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 07:47:11: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -03/07/2021 07:48:25: prof: ERR: Message received without body for room: support@room.pix-art.de/Chris -03/07/2021 07:49:37: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -03/07/2021 07:49:51: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -03/07/2021 07:50:19: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -03/07/2021 08:00:50: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke -03/07/2021 08:01:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:01:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:01:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:04:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:07:05: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 08:07:06: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 08:07:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 08:09:06: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 08:10:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:10:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:10:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:10:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:10:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 08:10:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:10:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:10:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:10:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 08:10:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 08:10:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 08:10:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 08:10:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 08:11:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 08:11:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:11:21: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 08:11:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:11:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:11:23: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -03/07/2021 08:11:28: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -03/07/2021 08:17:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:17:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:17:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:20:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:20:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:21:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:21:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:21:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:21:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:21:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:21:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:22:05: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 08:22:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 08:22:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:22:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:23:54: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 08:23:54: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 08:24:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:24:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:25:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:25:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:25:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mathieui -03/07/2021 08:25:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:25:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:26:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:26:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:26:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:26:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:26:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:26:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:26:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:26:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:26:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:26:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:27:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:27:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:27:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:27:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:27:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:27:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:27:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:27:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:27:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:27:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:27:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:28:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:28:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:28:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:28:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:28:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:28:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:28:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:28:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:29:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:29:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:29:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:29:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:29:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:29:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:29:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:29:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:29:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:30:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:30:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:30:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:30:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:31:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:31:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:31:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:32:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:32:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:32:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:32:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:32:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:32:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:32:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:32:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:32:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:34:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:34:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:34:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:34:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:34:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:34:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 08:35:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:35:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:36:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:37:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:37:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:38:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:38:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:38:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:38:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:38:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:39:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:39:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:39:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:39:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:39:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 08:39:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:40:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:43:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:43:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:43:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:43:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:46:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:46:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:46:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:46:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:46:46: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 08:46:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:46:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 08:47:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:47:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:47:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:48:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:48:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 08:51:07: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -03/07/2021 08:53:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:54:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 08:54:47: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:54:56: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:55:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:55:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:55:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 08:56:43: prof: WRN: Generated sha-1 does not match given: -03/07/2021 08:56:43: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 08:56:43: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 08:56:53: prof: WRN: Generated sha-1 does not match given: -03/07/2021 08:56:53: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 08:56:53: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 09:00:29: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/werdan -03/07/2021 09:01:20: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lemoldu -03/07/2021 09:01:20: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lemoldu -03/07/2021 09:01:24: prof: WRN: Generated sha-1 does not match given: -03/07/2021 09:01:24: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 09:01:24: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 09:07:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 09:07:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 09:09:25: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 09:26:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 09:26:51: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 09:26:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 09:26:55: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 09:27:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 09:27:46: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -03/07/2021 09:27:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 09:27:49: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -03/07/2021 09:27:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 09:43:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 09:45:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 09:47:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -03/07/2021 09:52:19: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -03/07/2021 09:55:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 09:55:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 09:55:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 09:57:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 09:58:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 09:58:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 09:58:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:00:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:02:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:02:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:02:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:02:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:03:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:03:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:03:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:04:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:04:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:04:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:04:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:05:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:05:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:05:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:06:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:06:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:06:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:07:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:07:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:07:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:07:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:07:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:07:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:07:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:07:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:08:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:08:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:08:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:08:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:08:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:08:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:08:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:08:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:09:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:09:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:09:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:09:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:09:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:09:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:10:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:10:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:10:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:10:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:10:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:10:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:10:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:10:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:10:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:10:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:10:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:10:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:11:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:11:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:12:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:12:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:12:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:12:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:12:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:12:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:12:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:13:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:13:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:13:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:13:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:13:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:13:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:13:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:13:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:13:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:14:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:14:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:15:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:17:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:17:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:18:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:20:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:21:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:21:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:22:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:22:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:22:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:22:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:23:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:23:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:23:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/bronko -03/07/2021 10:23:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:23:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:23:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:23:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:23:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:23:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/bronko -03/07/2021 10:23:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/bronko -03/07/2021 10:23:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:23:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:23:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:24:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:24:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:24:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:25:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:25:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:25:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:25:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:25:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:25:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:25:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:26:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:26:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:26:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:26:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:26:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:26:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:27:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:27:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:27:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:27:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:27:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:27:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/matkor -03/07/2021 10:27:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:27:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/matkor -03/07/2021 10:27:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/matkor -03/07/2021 10:27:41: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/matkor -03/07/2021 10:28:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:28:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:30:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:32:36: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 10:32:39: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 10:33:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:34:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:34:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou -03/07/2021 10:35:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:35:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:36:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:36:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:36:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:37:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:37:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 10:37:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 10:37:12: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 10:37:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:37:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:37:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:37:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:38:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:38:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:38:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:38:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:38:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:38:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:38:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:40:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:40:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:40:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:41:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:41:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:42:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:42:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:42:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:42:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:43:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:44:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:44:15: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:44:17: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:20: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:26: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke -03/07/2021 10:44:27: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:32: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:35: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:35: prof: ERR: Message received without body for room: en@chat.404.city/BDFL -03/07/2021 10:44:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:45:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:46:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:46:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:46:31: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:46:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:46:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:46:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:46:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:47:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 10:47:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:48:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:48:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:48:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:48:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:48:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:48:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:48:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:49:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:49:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:49:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:49:51: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:50:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 10:50:56: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:51:02: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:51:40: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:51:42: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:51:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:51:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/hidden-r3d -03/07/2021 10:52:20: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:54:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:55:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:55:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:55:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 10:56:48: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 10:58:22: prof: ERR: Message received without body for room: support@room.pix-art.de/Chris -03/07/2021 11:00:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 11:01:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:02:35: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:02:36: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:05:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 11:07:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 11:16:45: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:18:05: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 11:18:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 11:19:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:31:29: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 11:31:33: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 11:35:33: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:35:37: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:38:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:38:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:38:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:39:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:39:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:40:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:41:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:41:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:41:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:41:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:41:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:42:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:42:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:42:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:42:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:42:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:42:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:44:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:44:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:44:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:45:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:45:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:45:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:45:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:45:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:45:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:45:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:45:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:46:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:46:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:46:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:46:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:46:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:46:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:46:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:47:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:47:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -03/07/2021 11:47:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 11:47:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 11:47:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:47:31: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 11:47:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 11:47:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 11:47:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 11:47:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:48:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 11:48:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 11:48:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 11:48:31: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:48:41: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:48:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:48:47: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:24: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:40: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 11:49:41: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 11:49:43: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:44: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:49:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:50:18: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:50:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:54:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 11:54:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 11:55:23: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 11:55:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 11:55:34: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 11:55:45: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 11:56:16: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 11:56:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 12:00:36: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 12:00:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 12:02:17: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 12:02:21: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 12:02:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:02:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 12:04:22: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 12:04:24: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 12:04:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 12:07:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 12:09:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 12:10:48: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:11:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:11:56: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:13:05: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:16:51: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:17:03: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:17:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:18:14: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:18:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:18:34: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:18:36: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:18:36: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:18:38: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:18:38: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:18:41: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:18:44: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:18:47: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:18:49: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:18:54: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:18:58: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:19:04: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:19:22: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:19:36: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:19:41: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:19:48: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:19:53: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:19:57: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:20:02: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:20:08: prof: ERR: Message received without body for room: support@room.pix-art.de/nonion -03/07/2021 12:21:23: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:22:09: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:22:53: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 12:28:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:28:30: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:28:31: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 12:28:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:28:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:28:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:30:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 12:36:21: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 12:36:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 12:36:22: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 12:36:23: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 12:36:23: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 12:36:24: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 12:47:31: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] -03/07/2021 12:47:31: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] -03/07/2021 12:47:31: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien -03/07/2021 12:53:37: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] -03/07/2021 12:53:38: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] -03/07/2021 12:53:38: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien -03/07/2021 12:54:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 12:54:10: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 12:57:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 13:05:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/dedd -03/07/2021 13:08:43: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:09:07: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:14:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin -03/07/2021 13:14:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:14:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:14:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:14:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:14:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:15:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:15:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:16:01: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:16:11: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:16:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:16:59: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:17:21: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:17:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:17:21: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:17:29: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:17:44: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:17:59: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:18:37: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:19:03: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:19:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:19:28: prof: WRN: Generated sha-1 does not match given: -03/07/2021 13:19:28: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 13:19:28: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 13:19:38: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:20:02: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:20:21: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:20:26: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:20:31: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:20:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:20:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:21:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:21:09: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:21:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:21:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:22:26: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:22:38: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:23:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:23:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Iiro Laiho -03/07/2021 13:24:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin -03/07/2021 13:24:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin -03/07/2021 13:24:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin -03/07/2021 13:24:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/ilmaisin -03/07/2021 13:24:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:24:40: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:24:43: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:25:11: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:25:12: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:25:16: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:26:50: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:26:52: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:26:52: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:26:59: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:27:20: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:27:25: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:27:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:27:29: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:27:34: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:27:39: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:28:04: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:28:08: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:28:22: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:28:41: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:28:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 13:28:48: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:28:53: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 13:29:15: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:29:36: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:30:07: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:30:30: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:30:48: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:33:26: prof: WRN: Generated sha-1 does not match given: -03/07/2021 13:33:26: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 13:33:26: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 13:43:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:43:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:44:43: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:45:01: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:45:16: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:45:19: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:45:43: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:45:47: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:46:02: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:46:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 13:46:23: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 13:46:31: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:46:53: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:47:23: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:47:58: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:48:11: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:49:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:49:15: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:49:33: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 13:49:37: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:49:40: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 13:49:59: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:50:06: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:52:11: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:52:31: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:54:19: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:57:37: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:57:47: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:58:02: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 13:58:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 13:58:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 13:58:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 13:58:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 13:58:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 13:59:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:00:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:01:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:01:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:02:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:02:26: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:02:35: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/nonion -03/07/2021 14:03:00: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 14:03:10: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 14:03:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:03:20: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:03:20: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:03:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:03:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:03:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:03:29: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:03:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:04:09: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 14:05:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:05:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:05:31: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:05:43: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:05:51: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:06:04: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:06:40: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 14:07:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 14:09:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:09:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:09:38: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:09:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:11:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:12:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:12:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:12:32: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:12:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:12:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:12:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:12:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:13:47: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 14:14:34: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:14:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:16:42: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 14:18:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:18:44: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:19:28: prof: WRN: Generated sha-1 does not match given: -03/07/2021 14:19:28: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 14:19:28: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 14:19:32: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 14:19:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -03/07/2021 14:20:01: prof: WRN: Generated sha-1 does not match given: -03/07/2021 14:20:01: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 14:20:01: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 14:20:35: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:20:42: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:20:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:20:48: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:22:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine -03/07/2021 14:23:13: prof: WRN: Generated sha-1 does not match given: -03/07/2021 14:23:13: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 14:23:13: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 14:24:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 14:24:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 14:28:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:28:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 14:34:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 14:36:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne -03/07/2021 14:36:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne -03/07/2021 14:37:30: prof: WRN: Generated sha-1 does not match given: -03/07/2021 14:37:30: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 14:37:30: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 14:41:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:41:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:41:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 14:42:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:42:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 14:42:44: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:42:52: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 14:42:52: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 14:43:34: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 14:43:37: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 14:44:35: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 14:44:37: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 14:44:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:44:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:45:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:45:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:49:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:49:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:49:58: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:50:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:50:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:50:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:50:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 14:50:42: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 14:50:43: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 14:51:50: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 14:52:31: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 14:52:53: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 14:54:41: prof: WRN: Generated sha-1 does not match given: -03/07/2021 14:54:41: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 14:54:41: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 14:54:46: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:55:31: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:55:59: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:56:13: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:56:22: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:56:39: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:56:55: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:57:30: prof: WRN: Generated sha-1 does not match given: -03/07/2021 14:57:30: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 14:57:30: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 14:58:03: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:59:25: prof: ERR: Message received without body for room: operators@muc.xmpp.org/melvo -03/07/2021 14:59:45: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 14:59:47: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 15:00:22: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 15:01:03: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 15:01:11: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 15:08:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:08:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 15:08:30: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:08:38: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 15:09:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:09:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -03/07/2021 15:09:40: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 15:14:28: prof: WRN: Generated sha-1 does not match given: -03/07/2021 15:14:28: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 15:14:28: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 15:14:41: prof: WRN: Generated sha-1 does not match given: -03/07/2021 15:14:41: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 15:14:41: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 15:17:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 15:17:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 15:17:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:19:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:20:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:21:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:24:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -03/07/2021 15:25:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -03/07/2021 15:25:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -03/07/2021 15:27:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 15:27:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 15:28:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:28:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:30:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:30:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 15:30:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 15:30:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 15:31:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 15:31:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 15:38:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 15:38:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 15:38:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 15:43:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:44:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:44:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 15:45:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:45:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:45:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:45:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:45:25: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:45:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:45:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:46:13: prof: WRN: Generated sha-1 does not match given: -03/07/2021 15:46:13: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 15:46:13: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 15:46:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:47:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:47:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:47:56: prof: ERR: Message received without body for room: emacs@salas.suchat.org/pranavats -03/07/2021 15:48:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:48:41: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:48:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:49:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:49:32: prof: WRN: Generated sha-1 does not match given: -03/07/2021 15:49:32: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 15:49:32: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 15:49:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:49:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:49:50: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 15:49:59: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 15:49:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:54:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 15:54:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 15:54:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 15:55:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 15:55:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 15:55:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 15:55:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:56:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 15:58:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 15:58:13: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 15:58:16: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:00:53: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:01:51: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:01:51: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:01:54: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:01:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:01:55: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:01:59: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:02:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 16:02:02: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 16:02:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 16:02:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 16:02:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 16:02:42: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -03/07/2021 16:03:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -03/07/2021 16:04:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 16:04:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -03/07/2021 16:07:30: prof: ERR: IQ error received, id: ZTg3Y2QyOTctOGZkNS00NTY4LTliN2UtNTExMzlhNjA5ZmJjNTAyZGVjNDMxZTA4NzFhZTc1NGUzMzkxMDJiOTYzZjgyNjQ1OGFiMWVjYjEwMDE0OTkwNDgyMGZmNDU4ODc4Ng==, error: Request has timed out -03/07/2021 16:07:30: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Locness3: -03/07/2021 16:16:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 16:16:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 16:16:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda_ -03/07/2021 16:16:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 16:16:38: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 16:16:51: prof: WRN: Generated sha-1 does not match given: -03/07/2021 16:16:51: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 16:16:51: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 16:19:56: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:19:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:21:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:21:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:22:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:22:29: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 16:24:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -03/07/2021 16:24:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -03/07/2021 16:33:34: prof: WRN: Generated sha-1 does not match given: -03/07/2021 16:33:34: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 16:33:34: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 16:36:17: prof: WRN: Generated sha-1 does not match given: -03/07/2021 16:36:17: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 16:36:17: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 16:38:46: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 16:38:46: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 16:40:15: prof: WRN: Generated sha-1 does not match given: -03/07/2021 16:40:15: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 16:40:15: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 16:41:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat -03/07/2021 16:44:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:44:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:45:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:45:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:46:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:49:01: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:49:33: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:51:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:51:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:54:45: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:55:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 16:56:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/BDFL -03/07/2021 17:05:53: prof: ERR: Message received without body for room: en@chat.404.city/a -03/07/2021 17:05:53: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -03/07/2021 17:07:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 17:07:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 17:09:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -03/07/2021 17:10:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -03/07/2021 17:11:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne -03/07/2021 17:11:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Étienne -03/07/2021 17:11:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 17:11:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 17:14:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 17:16:20: prof: ERR: IQ error received, id: NmNkMTIxNTQtN2NkOS00OTc1LTg4NzUtNTAzYmQxN2U1NGQ4ZGJlNTFmZjZjMjRiNTQ0M2Q3MGZhMzFhNGM3YmQ3MzA1ZDRhYTI4N2JiMDEyYTcxYWQ4NWFjZDE0NzkyYjExMw==, error: Request has timed out -03/07/2021 17:16:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 17:19:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 17:23:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 17:29:46: prof: ERR: IQ error received, id: M2NjMjIwOTItZTFlNC00OGUwLWJiNTMtODNjYWI0NDY3MDNlOWFjOWUxOTJkZWRhOGZlNmYzNTRhNDk2YTUyZTc0NTJkM2FkZGQ1ZjMzMzZkZTRiOTM5YmJiM2U2NjM3YWYyYg==, error: Request has timed out -03/07/2021 17:29:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 17:35:47: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 17:37:23: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -03/07/2021 17:40:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 17:42:11: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 17:43:30: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 17:55:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -03/07/2021 17:55:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -03/07/2021 17:58:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -03/07/2021 17:59:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lep -03/07/2021 18:00:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lep -03/07/2021 18:15:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 18:16:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 18:16:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 18:17:20: prof: ERR: IQ error received, id: ZDA5Y2I3ZWItYmEzOS00MDEyLThiN2YtODEzZmIwMWVkMGM3Y2ViZTNlZDg5NzNmMmYxNjI1Mjk4N2EyYmExMWNkMDMxOWYxZmM1YWIwZGRkMmI1MzE1NTZiNzVmMjU1Nzk0YQ==, error: Request has timed out -03/07/2021 18:17:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 18:20:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:20:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:21:33: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:22:14: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:22:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:22:44: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:23:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:23:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:23:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:23:49: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:30:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 18:30:26: prof: ERR: Message received without body for room: emacs@salas.suchat.org/qy -03/07/2021 18:30:26: prof: ERR: Message received without body for room: emacs@salas.suchat.org/qy -03/07/2021 18:30:43: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -03/07/2021 18:31:08: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:32:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:33:01: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:33:02: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:33:40: prof: ERR: IQ error received, id: ZmE2NjE1OWUtZTU3MC00ZjQzLWI1YzEtYzVmM2UxNjhmMmM3MjlmMjg0Yjk0MzUxODQ2OTliNjU3ODFhYTllM2E0YTkwMjk4NjcwOTYyOWU3ODcyOGZiMWJmYzVlZmZiOTlkNA==, error: Request has timed out -03/07/2021 18:33:40: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 18:34:38: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:34:40: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:34:42: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:34:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:34:43: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:34:54: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:34:54: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 18:34:57: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 18:35:27: prof: WRN: Generated sha-1 does not match given: -03/07/2021 18:35:27: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 18:35:27: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 18:36:54: prof: WRN: Generated sha-1 does not match given: -03/07/2021 18:36:54: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 18:36:54: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 18:37:20: prof: ERR: IQ error received, id: ZjIwMDlkYmEtNjAwMy00Nzc5LTg0ZjktYWQ0NTk4NzgzODk0N2E2MjJiMzVjNWVjNzViZGYzMDNjNGEyYmM4MWY0YmY0Yjk1MWQzN2VlMWRjY2YzMzNmZDNiODYwYzYzNzhiNw==, error: Request has timed out -03/07/2021 18:37:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 18:40:00: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 18:40:19: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 18:41:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 18:41:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -03/07/2021 18:42:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 18:44:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -03/07/2021 18:49:10: prof: ERR: Message received without body for room: emacs@salas.suchat.org/wgreenhouse -03/07/2021 19:00:58: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:01:02: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:01:03: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:01:11: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:03:17: prof: WRN: Generated sha-1 does not match given: -03/07/2021 19:03:17: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 19:03:17: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 19:03:27: prof: ERR: IQ error received, id: MGRjN2UwZjAtNDBhMi00OWJiLWJlZDgtY2E2MWE2ZWNjODU5MDgxMmEyNjdiZWViMTNlNGU0MGU3ZWNmMzcyZmI3ZDY1YmViMmJlYmIxZDU1MDc2MDdjM2I0MTQzNTczZDk3YQ==, error: Request has timed out -03/07/2021 19:03:27: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 19:03:30: prof: WRN: Generated sha-1 does not match given: -03/07/2021 19:03:30: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 19:03:30: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 19:06:40: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:06:42: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:06:42: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:06:44: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:07:48: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 19:08:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 19:08:18: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:08:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:08:22: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:09:40: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:12:01: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 19:12:02: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 19:16:44: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:16:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:16:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:16:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 19:16:46: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:16:46: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 19:19:59: prof: ERR: IQ error received, id: OTljMjNjNjItZDYzMi00OTBhLWE5MzAtMWFmOTUzNTkxNDIxYzMwMDYxOTJhNTZlMTNiNWYwZjIwZDM1NDA1ZDBmOGE2ZmU2YTBhZTRiOWU1MWYyOWI0OGY5ZDA1ZjlkN2NlYQ==, error: Request has timed out -03/07/2021 19:19:59: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 19:21:19: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 19:22:40: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:22:58: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:23:05: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:23:09: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 19:23:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -03/07/2021 19:23:19: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:23:20: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:23:41: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:24:47: prof: ERR: Message received without body for room: support@room.pix-art.de/HeatfanJohn -03/07/2021 19:25:02: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 19:26:00: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 19:27:34: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 19:32:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 19:33:39: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 19:34:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 19:37:18: prof: ERR: IQ error received, id: OTc5YjU1ZTctZjI3MC00MjQ0LWFhNDQtNWNhYjZjMmViZjYwMzIzOGZiMGExMzQxZDFlMDEyMWNkNTc4NDQxNmM2YmM3ZTk4MmZkNjIyYTQ4MTYxNTNmNDU1NWUyNDNiMTMxZA==, error: Request has timed out -03/07/2021 19:37:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 19:43:28: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:43:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:45:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 19:46:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -03/07/2021 19:47:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:47:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 19:47:52: prof: WRN: Generated sha-1 does not match given: -03/07/2021 19:47:52: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 19:47:52: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 19:48:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:48:57: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:49:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:49:02: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 19:49:07: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 19:49:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:49:11: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 19:50:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 19:50:26: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 19:56:53: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 19:57:17: prof: ERR: IQ error received, id: OTJiNTRlZTgtMmYxMy00OTQ3LTljMmMtZTdmNTVjYmU2MGY0YWVlMmIyY2Y4MWQ3MDVjYTliMjRmNDdkMzBhNWJkNjg5NzA0MGJhM2Y2NWYyZjM5Mzg3NTA4ZDQ2Y2Q2ZjIwZA==, error: Request has timed out -03/07/2021 19:57:17: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 20:09:19: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:09:28: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:09:57: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:10:01: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:10:33: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:10:36: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:10:46: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/wurstsalat -03/07/2021 20:10:47: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -03/07/2021 20:10:48: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -03/07/2021 20:11:39: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:11:44: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:11:53: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:12:05: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:12:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -03/07/2021 20:12:18: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -03/07/2021 20:12:43: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:14:42: prof: ERR: IQ error received, id: ZTYxMjk2NTktNWYwOC00OTU3LTg1M2YtZTVjM2YxZGExYjNkYzQ0YzQ4NjRlY2VhZjllZWU2MmM1ODE0YTRkNmQyMjE3MGI4OTIyZDZiMGYwNGQzNjNhNDZlMDQ1NmZlYTA1Mg==, error: Request has timed out -03/07/2021 20:14:42: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 20:34:33: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:34:44: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:42:00: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 20:42:16: prof: ERR: IQ error received, id: NGUwNmMwYzUtYjEyZi00ZjEyLTllNDItMGRjZDllZDIxZjhkYWJlMTQ4MjFlOTg3N2JkOWE5N2U3M2ZjYjYwNmVmZWRiZjJiODEzN2NiOGQwYjQ4YWRmNWMyMTZiMmRjMmE0OQ==, error: Queries to the conference members are not allowed in this room -03/07/2021 20:42:16: prof: WRN: Error received for capabilities response from conversations-offtopic-reloaded@conference.trashserver.net/Agris: -03/07/2021 20:42:25: prof: WRN: Generated sha-1 does not match given: -03/07/2021 20:42:25: prof: WRN: Generated : mpjf9+07+HNoZ6+YxlqRhZDbiVs= -03/07/2021 20:42:25: prof: WRN: Given : l95JgiXsL86tDaMg2HTvl+0Ijb4= -03/07/2021 20:43:27: prof: WRN: Generated sha-1 does not match given: -03/07/2021 20:43:27: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -03/07/2021 20:43:27: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -03/07/2021 20:44:53: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 20:46:02: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -03/07/2021 20:46:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 20:46:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 20:46:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 20:46:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 20:46:43: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ -03/07/2021 20:46:55: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ -03/07/2021 20:47:24: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 20:47:59: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes -03/07/2021 20:48:01: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes -03/07/2021 20:48:36: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ -03/07/2021 20:48:41: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ -03/07/2021 20:48:54: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:48:55: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:48:57: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:49:01: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes -03/07/2021 20:49:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Samanto Hermes -03/07/2021 20:49:09: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:49:15: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:49:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:49:24: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 20:50:52: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 20:52:41: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:56:26: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 20:56:39: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 21:01:23: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/southerntofu -03/07/2021 21:07:25: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:08:04: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:08:22: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:08:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat -03/07/2021 21:09:24: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:09:33: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:14:18: prof: ERR: IQ error received, id: N2RkOGFkNzYtYjE5OC00MjhmLWE2MGYtNmQwOGI1YmJmYWUxNTkyMTNiNDEyZTUwOWM2YjRmZDVjMjdkMTA2ODc1YzhkOGNkNzM3M2QwY2NiMjdlMDgzMzczNGY5Mjc3NjM3Yw==, error: Request has timed out -03/07/2021 21:14:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 21:16:35: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 21:16:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 21:16:55: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 21:17:18: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -03/07/2021 21:17:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:17:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:18:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 21:18:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 21:21:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:22:03: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:22:14: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 21:22:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:23:13: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:23:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:25:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:25:47: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:25:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:25:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:26:24: prof: WRN: Generated sha-1 does not match given: -03/07/2021 21:26:24: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 21:26:24: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 21:26:44: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:27:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:27:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:27:45: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:28:43: prof: ERR: IQ error received, id: ZGZiMzBiMmYtM2MxYS00NDYxLWFhNzYtNTNmNWFhOWI1MTlkZWJhYTFiODk5YmM4YzcyMzljMGUyYzI4OTgxZDk4ZGFjNzBiNWNhNDYwYzc3ZWYyNzU1NTQzNjEyOWQ2ZDJkYw==, error: Request has timed out -03/07/2021 21:28:43: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 21:30:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 21:30:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:30:16: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:32:18: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:32:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:32:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:32:32: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:32:47: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:33:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:33:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:34:01: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:34:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:35:49: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:36:52: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:36:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:38:42: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:39:59: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:41:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:43:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:43:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:45:28: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:45:53: prof: ERR: IQ error received, id: NjU5ODI4ZDYtMTA2OC00MDAzLTg4MjgtMjVlZDZhMDZlZDUyOGM2YTQyNjZkOGQ2MDg2MDExMDhiNzUxZGYxNzU1NWFhMWRhNTAxZDQzYzEyOTM4MDMwODhhZDIyNjUyNzcyYQ==, error: Request has timed out -03/07/2021 21:45:53: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -03/07/2021 21:46:12: prof: WRN: Generated sha-1 does not match given: -03/07/2021 21:46:12: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 21:46:12: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 21:47:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:47:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:52:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:52:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:52:52: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:53:09: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:53:10: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:53:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:54:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:54:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -03/07/2021 21:54:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:54:48: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:54:49: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:54:54: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:54:56: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:55:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 21:55:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 21:56:19: prof: ERR: Message received without body for room: chat@dino.im/kaoka -03/07/2021 21:56:23: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:56:24: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 21:56:24: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 21:56:25: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 21:57:04: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:57:10: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 21:57:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:57:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:57:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 21:58:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 21:59:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 22:00:10: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 22:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 22:00:14: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 22:00:58: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 22:01:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 22:01:32: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:01:35: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:01:35: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:01:37: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:01:56: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 22:02:00: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -03/07/2021 22:02:58: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:03:08: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 22:03:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 22:03:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -03/07/2021 22:04:10: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 22:04:14: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 22:04:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 22:04:29: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -03/07/2021 22:05:25: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:05:40: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:05:41: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:05:41: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:05:42: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:05:44: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:05:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:06:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 22:07:10: prof: WRN: Generated sha-1 does not match given: -03/07/2021 22:07:10: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 22:07:10: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 22:07:14: prof: WRN: Generated sha-1 does not match given: -03/07/2021 22:07:14: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -03/07/2021 22:07:14: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -03/07/2021 22:08:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 22:08:31: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 22:09:20: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:09:21: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:09:23: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:09:24: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Link Mauve -03/07/2021 22:09:25: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:09:27: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:09:28: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:09:57: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Link Mauve -03/07/2021 22:12:16: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:12:21: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:13:13: prof: WRN: OMEMO: received a message with no corresponding key -03/07/2021 22:13:24: prof: ERR: IQ error received, id: NWQ5OGYyN2YtMzkzZi00NTJiLThlMDItYTVkODY0ODk3MjNjZDllNzk0MWFhMTkzNWI0YzZlZThkYmY2ZDQ2ZjlmOGEzNmE5OTE4MmUxOTg1YWRiYWVlYmY3YWM4MjNkNTQ3Ng==, error: feature-not-implemented -03/07/2021 22:13:24: prof: ERR: IQ error received, id: NGI4NGIxNzItMjNmNy00ZGEwLWFiNmEtZTYyNzFlM2Y1NjdkODM5ZmJiMGEyZDBiNWRjZmYwZTc3ZmI0NWNjNjUxN2UzYjJjNDFkZTdmM2I1OWJlYTEzM2YwODcwZGQ4ZDEwMw==, error: feature-not-implemented -03/07/2021 22:13:24: prof: ERR: IQ error received, id: M2FlZmUwMGEtZmJhYi00ZGU3LWI3MzQtMjRiOGM3NGQ0MWNkZjFkNTY1YjY2MmQyODE3OTA0NGM2MDIzNzdmOTc1YzczNDFjMDU5M2RhODY0ODY3MWYwYWFiMzQwMzI5YTlmNA==, error: feature-not-implemented -03/07/2021 22:13:25: prof: ERR: IQ error received, id: YTFjODQ1MjMtZGFmMC00MWFhLWE5ODUtNDU5MTQ4NGI1Yjk3MDU4NGIxNDUzOWQyZDA3MzIzZjM1MDcwMzA3ZWIxYzAwYTA4NTM0YWVjOGM2YmUxYWViYWE3MGU0ODQwNzhjYg==, error: feature-not-implemented -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1519741822 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 446279639 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1362339665 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1547501418 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 952095435 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 870832176 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 866731537 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1540261437 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 308556671 -03/07/2021 22:13:31: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1033627704 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1519741822 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 446279639 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1362339665 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1547501418 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 952095435 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 870832176 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 866731537 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1540261437 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 308556671 -03/07/2021 22:13:49: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1033627704 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1519741822 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 446279639 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for aro@jix.im device id 1362339665 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1547501418 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 952095435 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 870832176 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 866731537 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 308556671 -03/07/2021 22:14:02: prof: ERR: OMEMO: cannot encrypt key for qy@xa0.uk device id 1033627704 -03/07/2021 22:14:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 22:15:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 22:16:00: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:16:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 22:17:04: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:17:10: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:17:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -03/07/2021 22:17:29: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:22:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 22:22:46: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 22:23:30: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:23:31: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:23:32: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:23:33: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:23:34: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:23:35: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:29:55: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:30:01: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:30:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 22:30:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -03/07/2021 22:30:33: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 22:31:08: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -03/07/2021 22:31:26: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ -03/07/2021 22:31:55: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/MattJ -03/07/2021 22:33:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 22:34:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -03/07/2021 22:35:32: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:35:49: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:35:49: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:35:52: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:37:29: prof: WRN: Generated sha-1 does not match given: -03/07/2021 22:37:29: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 22:37:29: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 22:42:29: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:42:36: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:42:37: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:42:39: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:42:42: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:42:44: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:42:44: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:42:45: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:42:45: prof: ERR: Message received without body for room: emacs@salas.suchat.org/Eff -03/07/2021 22:42:50: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -03/07/2021 22:45:17: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 22:45:25: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -03/07/2021 22:45:42: prof: WRN: Generated sha-1 does not match given: -03/07/2021 22:45:42: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 22:45:42: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 22:56:03: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke -03/07/2021 22:57:44: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke -03/07/2021 23:01:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris -03/07/2021 23:01:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 23:03:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris -03/07/2021 23:03:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -03/07/2021 23:09:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:09:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:10:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:11:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:11:54: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:14:21: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -03/07/2021 23:15:55: prof: WRN: Generated sha-1 does not match given: -03/07/2021 23:15:55: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 23:15:55: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 23:16:01: prof: WRN: Generated sha-1 does not match given: -03/07/2021 23:16:01: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 23:16:01: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 23:16:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:16:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:16:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:16:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:17:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:17:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:17:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:18:17: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:18:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:18:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:18:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:19:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:19:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:20:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:20:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:22:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:22:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -03/07/2021 23:24:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:24:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/christian -03/07/2021 23:27:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 23:28:53: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -03/07/2021 23:42:04: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/timothy -03/07/2021 23:44:15: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -03/07/2021 23:54:40: prof: WRN: Generated sha-1 does not match given: -03/07/2021 23:54:40: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 23:54:40: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 23:58:43: prof: WRN: Generated sha-1 does not match given: -03/07/2021 23:58:43: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 23:58:43: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -03/07/2021 23:59:19: prof: WRN: Generated sha-1 does not match given: -03/07/2021 23:59:19: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -03/07/2021 23:59:19: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -04/07/2021 00:01:49: prof: WRN: Generated sha-1 does not match given: -04/07/2021 00:01:49: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -04/07/2021 00:01:49: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -04/07/2021 00:02:41: prof: WRN: Generated sha-1 does not match given: -04/07/2021 00:02:41: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -04/07/2021 00:02:41: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -04/07/2021 00:07:13: prof: ERR: IQ error received, id: ODkyMzJjYTYtZDA4Ni00MmQ3LTliNzItZWI5NGI0YmE5MDZkYmZhMjI3ZjM1Nzc0ZTcwNzM1YmFkNWZjNWFiZWE1NWExNjg2MjRiNThjMjkwYjkyMjRjYzM3NTc1ZDQ0Y2NkYg==, error: Request has timed out -04/07/2021 00:07:13: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 00:09:28: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -04/07/2021 00:10:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 00:13:48: prof: ERR: Message received without body for room: en@chat.404.city/bog_demon -04/07/2021 00:14:28: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke -04/07/2021 00:14:40: prof: ERR: Message received without body for room: support@room.pix-art.de/blitzgedanke -04/07/2021 00:17:49: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 00:23:47: prof: ERR: IQ error received, id: N2VjYzkxMzYtZDg5MC00ODlkLThlN2QtZmUwMjFjOWQ1ZTBjNTJhYzk0N2VhMTg1OWU3M2ZkYzQ4MDEwZTVlMDg3YjhiYWFhNmZmY2JlNTA5MmMxMWM4NDU4ZDk1OGJhNGJkNQ==, error: Request has timed out -04/07/2021 00:23:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 00:24:53: prof: ERR: IQ error received, id: MDNkOWEwMTMtNTMyNy00ZDc2LTg4MWEtZGMzODNkYjRkZTQ1OTNlYjZiOTc3MWI0YjhhODljMmNmZGFmM2IxOGE5OTUyYjZmYWNhM2UzNWRhMDExYzQ0YzVkMGIzNjhkMzZjYw==, error: Request has timed out -04/07/2021 00:24:53: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 00:28:08: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou -04/07/2021 00:38:29: prof: ERR: IQ error received, id: OGY3ZTA0NmMtYjAwYS00MTI4LTg3YTktNDRlMzA4MDNhZmJkMDRiN2I2NjUwMjk4MjdjNGU1YTgyOTk0Yjc5MjMzYjUzMmFkNWU5ODZlZDY1OTMxNjNkOTNmZjVkYjU5NDI4ZA==, error: Request has timed out -04/07/2021 00:38:29: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 00:38:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 00:38:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 00:41:58: prof: ERR: IQ error received, id: NjU3Y2VlNDUtZjU5ZC00MDc3LTg4YzItMjMzNGYyZjY2YzdiNWI5MDlhZTI2YzViYjNkMmQ4YmMzOWRlN2VhMWU5ZWQ5NGU5MDRmOTc5OTZiMjgxYjAzNjkzNzk5NzIzY2U5NQ==, error: Request has timed out -04/07/2021 00:41:58: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 00:50:49: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -04/07/2021 00:50:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Link Mauve -04/07/2021 01:00:46: prof: ERR: IQ error received, id: YTJiZmRjYmMtZWRmNy00ZDc2LWEyYWItM2E4MGI2ZGMxMDhjMjNjMWM5YjQ5MjBhMzQ2MGM0NjEzMGRiZWQ3ZDU3NDUxZTM0ZTFiZDFhNzQyZTI2MmRmYzQ3MThhZjJlMDc3ZA==, error: Request has timed out -04/07/2021 01:00:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/blumpkin: -04/07/2021 01:30:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 01:32:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 01:41:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 01:43:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 01:49:00: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio -04/07/2021 01:50:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 01:51:02: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio -04/07/2021 01:53:49: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio -04/07/2021 01:54:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 02:01:42: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/Mio -04/07/2021 02:35:18: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 02:35:18: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 02:35:25: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -04/07/2021 02:38:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -04/07/2021 02:38:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -04/07/2021 02:57:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:02:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris -04/07/2021 03:04:17: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/Agris -04/07/2021 03:13:48: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 03:13:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 03:18:12: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 03:19:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:19:16: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 03:20:15: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 03:20:16: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 03:22:00: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:33:39: prof: ERR: IQ error received, id: OTRjNmViNjctYTVmZi00NzQ2LWJiMTQtZTgyYzMwODU1ODg2OGE1MGUxN2E1NjlhNDY3ZTZjNmVkZWMxYmY3YjUzMDRhNzI3ZDVjODI2NTE0ODJjMjllOTA4YjYyZTk4NGNmYg==, error: Request has timed out -04/07/2021 03:33:39: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 03:40:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 03:43:39: prof: ERR: IQ error received, id: YTRmODg4MmMtOTI0Ni00OWJkLTgxMDMtNDMxNGVkYjUxMmU4MDNiNmZkNWU1NWIxNDk0ZGEyN2FmYzAzMGY3Yjc4ZTM1Mzg1MzA4MTFmNWNhZDZlNDM5MDA1NmQyYWQzMzY1Yw==, error: Request has timed out -04/07/2021 03:43:39: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 03:43:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:44:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:47:56: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 03:49:01: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 03:54:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:55:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 03:56:49: prof: ERR: IQ error received, id: OThkOTBlNzMtZjk0Mi00NmVlLThlMDYtNzhmYmU4NmY1NDliZjQ2NDUyNWM5OWY2ZDU0MWViYmY2M2U0ZTEwN2Q5ZDJiY2Y1NTZkZDI4MjExN2E0NWVhMDRlMTZjNmE2ZmQ5OQ==, error: Request has timed out -04/07/2021 03:56:49: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 03:57:08: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 03:58:57: prof: ERR: IQ error received, id: OGY3MzkwNWMtOTlhMC00MGJkLWIyYzgtZDU4ZmE2N2I1MGUwYWRlM2FlMmNkZDU4YzkyYTg1MjJhNTA4MDM3NmI3ZTBkM2EwOTk3ZmVhYjhiNjEyMTYzZTE3OWE1ZjhlMTRiZg==, error: Request has timed out -04/07/2021 03:58:57: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 04:00:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:02:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:03:04: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:08:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:11:16: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:14:54: prof: ERR: IQ error received, id: YjRkNDc1NzgtNDAzYy00MzdjLWFiNmUtOTQ4ZmI0NTNjNjZlYTNiZTQ1ZWI3ZDgwM2UyM2IxYTFlZTdiMjZmYWYyM2VhYTYwZGEzYTJmNTJlZTkyNGU5ZDNkMmYzMzkyYTVlYg==, error: Request has timed out -04/07/2021 04:14:54: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 04:15:06: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:15:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:15:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:15:36: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:21:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:22:09: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 04:22:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 04:22:13: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 04:23:24: prof: ERR: IQ error received, id: N2IzM2VjOWYtMGE5Ni00NDEyLThhNTMtNGU5ZTQ4ZWVlMGI1YjEzOTJhNjlkMGNlYTRlNzYwMWI2MTU5ODY0NjBkNDBjM2EzZDc4NjcxN2NkMzAzOTNlMWYxNDg1ZmRiNDA2Zg==, error: Request has timed out -04/07/2021 04:23:24: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 04:24:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:24:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:24:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:25:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:25:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:25:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:26:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:31:08: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 04:31:11: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 04:31:13: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 04:32:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 04:33:25: prof: ERR: IQ error received, id: M2UzMDY1ZmQtOWNjNS00ZjJjLTg5YjAtZDQ4MWE4NDZkMzI0Nzc2ZmE2NjIyMmQ3MDA1MjM0MDBhYzRmNWE2YjU4NzM4YzY2MWFlNjEzOTE0YTRhM2U1ZjcwNGM3MmNlNjJmZA==, error: Request has timed out -04/07/2021 04:33:25: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 04:36:46: prof: ERR: IQ error received, id: Yzg0OGI1YWQtMjU0Mi00YTNhLTg0MDctNDhiMmE0MmIyYjI0Y2ZlOTZlOTliZDQ4MjhmNGIzYzhiNzFjNTg2MjBjZTA1NGY4MWYwY2Q0NGJjZWU3ZDdlY2NhMTNiNmMxMmVkMg==, error: Request has timed out -04/07/2021 04:36:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 04:57:49: prof: ERR: IQ error received, id: MjAxMmNhNjMtZDJmYi00YjkxLWEwMmItNWVlNGM3OTFkNzA2ZTBiYTVjOWY4Yzc5M2VlYTFhMzBhMGJmNjA1NmEzMDU0NDBlNTVmZjBhNjgyODU1N2YwMGM0MGUwNmUyNjc0MQ==, error: Request has timed out -04/07/2021 04:57:49: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 05:01:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 05:03:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 05:06:01: prof: ERR: IQ error received, id: MmQ2MDI1ODItMjYzOC00MjUwLWIwOTMtNzI1YTg1OTY0Mjg0OTUyMzUxZDk0YTVmOTE5ZDA1ODc1MGM3NmU3YTI3ZGQ5NTNlNzVlMjhkNjU2YzU1ZTgwOTAzNzE0Zjk0NTIxYg==, error: Request has timed out -04/07/2021 05:06:01: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 05:09:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 05:14:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 05:14:46: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 05:23:09: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:23:30: prof: WRN: Generated sha-1 does not match given: -04/07/2021 05:23:30: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -04/07/2021 05:23:30: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -04/07/2021 05:24:32: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:26:17: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:27:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:29:10: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:30:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:32:31: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:33:23: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 05:33:57: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:34:46: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:34:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 05:34:56: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:34:58: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:34:59: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:35:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 05:36:51: prof: WRN: Generated sha-1 does not match given: -04/07/2021 05:36:51: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -04/07/2021 05:36:51: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -04/07/2021 05:37:06: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:37:06: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:37:07: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:37:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 05:39:50: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:40:46: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:41:11: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:43:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:44:01: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:44:24: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:44:51: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:45:10: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:46:17: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:48:20: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:48:22: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/komp -04/07/2021 05:49:00: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:50:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -04/07/2021 05:50:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Bruce -04/07/2021 05:50:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 05:51:39: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 05:52:09: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:55:33: prof: WRN: Generated sha-1 does not match given: -04/07/2021 05:55:33: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -04/07/2021 05:55:33: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -04/07/2021 05:55:35: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:57:14: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:57:17: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 05:57:42: prof: ERR: IQ error received, id: ZmMxNmY3YTktMmEzZC00YjkzLWFhNGMtY2M4Y2NmNTQ3NDRkM2NmMzNiNmEyOTAxMmQ4YzcwZmFiYjk2OWMxMGIwMzg4NjBkNTUyY2IzMWI2NTY2YzNmYTI4NjcxN2ViZTg2Yg==, error: Request has timed out -04/07/2021 05:57:42: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 06:01:56: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 06:03:54: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Axel -04/07/2021 06:04:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/Axel -04/07/2021 06:04:50: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 06:07:43: prof: ERR: IQ error received, id: ODljOGZiMDAtYTJkYi00YTNkLThjNDAtNDMxZTI5NDhmZmI4NWFiYzc4ZDgyMzUyYTExNjEzYTQwNzk5MzE4NGYzNDgwZTcyOGM5YzVjMzEyYmU4MGM0NzgxYTI2MzczYjk3YQ==, error: Request has timed out -04/07/2021 06:07:43: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 06:07:44: prof: ERR: Message received without body for room: en@chat.404.city/alhimia -04/07/2021 06:15:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 06:17:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 06:26:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 06:26:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 06:27:43: prof: ERR: IQ error received, id: NTZhMGExODktMjcxNy00N2E2LWFkMDctODg3NWU5NDc0MWYzNWRlMDRiNjNjNmE1OGNiOWVjODU4MzU0OWJlMTQ0YjJjNGI4NDdmYWU3YjgzY2JjZTFkYmFmYmUwY2MyNzFlZA==, error: Request has timed out -04/07/2021 06:27:43: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 06:27:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 06:32:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 06:34:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 07:38:54: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/werdan -04/07/2021 07:39:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/werdan -04/07/2021 07:47:46: prof: ERR: Message received without body for room: movim@conference.movim.eu/werdan -04/07/2021 07:58:59: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 08:00:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 08:00:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 08:00:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 08:00:50: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 08:01:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Ge0rG -04/07/2021 08:01:41: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 08:02:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 08:07:21: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 08:11:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 08:15:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 08:30:12: prof: ERR: IQ error received, id: NDUwNGVhN2EtNjk1YS00NjViLTkxNzUtMzgwOTRkYTA0Nzc1NThjNDA0ODA2MDE3YThhMDExMjNlZWRjMTZlYjE0ZjZiZjBiZjk5Y2U0ZDE1MDU0MWZiYjZiMjBhMzdiMGI2OQ==, error: Request has timed out -04/07/2021 08:30:12: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 08:30:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 08:32:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -04/07/2021 08:32:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 08:35:21: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 08:35:41: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 08:40:12: prof: ERR: IQ error received, id: Y2MwY2JiMTgtM2QwZS00MGUyLWEyYzgtMTBjMWVjMjQxMzAyYWQ0NmVhYjg1MzY0YTc4NmUwNWMyNDViOTJiMWEwM2E0ZWQwMzNhYjIzNDUzOTEyYzZhZjZhZDE5MTc4MmRiMw==, error: Request has timed out -04/07/2021 08:40:12: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 08:43:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 08:45:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 08:48:51: prof: WRN: Generated sha-1 does not match given: -04/07/2021 08:48:51: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 08:48:51: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 08:49:07: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve -04/07/2021 09:08:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:08:43: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:09:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:09:07: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -04/07/2021 09:09:08: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -04/07/2021 09:09:09: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -04/07/2021 09:09:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:09:23: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -04/07/2021 09:09:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:09:24: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:09:27: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:09:46: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:10:05: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:10:06: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:10:06: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:10:07: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:10:09: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:10:19: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:10:32: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:10:34: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:10:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:10:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:24:36: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 09:25:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:25:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 09:31:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:33:28: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:34:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:35:52: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:41:07: prof: ERR: IQ error received, id: N2YyODNhMmQtNTQyMi00ZmU3LWE3ZjktMjg1YTBkNzE3ZGMxMjlmYTU3YWJmMWZhMDA1OGE3YWFlZWJkMmU4MjBhMjkzZGVlN2M3YWE3YTgwNjUwMzQ4ODdiMDlhNDE2NTdkZQ==, error: Request has timed out -04/07/2021 09:41:07: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 09:41:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:41:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:41:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:01: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:06: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:22: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:28: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:42:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:43:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:43:02: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:43:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:43:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:43:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:43:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:44:52: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:45:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:45:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:45:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:45:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:45:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:45:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:46:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:46:22: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:47:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:49:36: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:49:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:49:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:49:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:49:53: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:50:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:50:14: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:50:24: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:50:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:51:09: prof: ERR: IQ error received, id: ZWMwZmViZmUtNDM0OC00ODYwLWFjYTEtY2VkZmVkODc0M2UzOTAwNTQzM2Y4ZTJmMDk0ZDViNjQ4YzJhMmIyZGU5MGZkODIwNWE3NTFkMmY2MmViM2ZmZDZjNDM1NjQwMDUyNw==, error: Request has timed out -04/07/2021 09:51:09: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 09:51:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:51:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:51:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:51:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:52:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:52:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:52:41: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:52:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:53:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:54:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:54:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:54:20: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij -04/07/2021 09:54:20: prof: ERR: Message received without body for room: chat@dino.im/ij -04/07/2021 09:54:20: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij -04/07/2021 09:54:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij -04/07/2021 09:54:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:54:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:54:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:55:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:55:34: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:55:49: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij -04/07/2021 09:55:49: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij -04/07/2021 09:55:49: prof: ERR: Message received without body for room: chat@dino.im/ij -04/07/2021 09:55:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij -04/07/2021 09:57:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 09:57:09: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Étienne -04/07/2021 09:57:17: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Étienne -04/07/2021 09:58:14: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij -04/07/2021 09:58:14: prof: ERR: Message received without body for room: chat@dino.im/ij -04/07/2021 09:58:14: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij -04/07/2021 09:58:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij -04/07/2021 09:58:44: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij -04/07/2021 09:58:44: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij -04/07/2021 09:58:44: prof: ERR: Message received without body for room: chat@dino.im/ij -04/07/2021 09:58:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij -04/07/2021 09:58:58: prof: ERR: Message received without body for room: joinxmpp-operators@chat.cluxia.eu/ij -04/07/2021 09:58:58: prof: ERR: Message received without body for room: chat@dino.im/ij -04/07/2021 09:58:58: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/ij -04/07/2021 09:58:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ij -04/07/2021 09:59:30: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:00:31: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:00:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:00:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:00:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:01:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:01:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:01:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:01:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:01:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:02:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:02:23: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:02:33: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:02:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:02:56: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:02:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:03:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:03:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:03:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:03:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:03:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:04:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:04:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:04:30: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:06:05: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:06:36: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:06:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:11:09: prof: ERR: IQ error received, id: OTU3ZWI5N2UtYzNkMi00Mzc2LWFiOGItYzQ2MGUxN2Q0OTBjNDNmMzFlZjFmNjJkZDRiYWU1OTU3ZDEwMTVjMjVlYWE0NDM1Y2E1YTQ4NWQ2ZGU0ZmU4YThhZjA2YmQ5ZGM0MQ==, error: Request has timed out -04/07/2021 10:11:09: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 10:24:11: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 10:24:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 10:24:30: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 10:24:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:26:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:26:33: prof: WRN: Generated sha-1 does not match given: -04/07/2021 10:26:33: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 10:26:33: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 10:26:49: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:27:14: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:27:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:27:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:27:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:27:26: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:28:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 10:28:03: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 10:28:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:28:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:29:27: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:29:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:29:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:29:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:30:17: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat -04/07/2021 10:30:43: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:30:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat -04/07/2021 10:32:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:32:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:32:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:32:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:33:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:33:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ -04/07/2021 10:34:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:35:01: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:35:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:35:22: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ -04/07/2021 10:36:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:37:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:38:30: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:39:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:41:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:41:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ -04/07/2021 10:41:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/JonNJ -04/07/2021 10:42:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:42:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:45:20: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 10:46:33: prof: WRN: Generated sha-1 does not match given: -04/07/2021 10:46:33: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 10:46:33: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 10:47:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:47:31: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -04/07/2021 10:48:24: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:48:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:48:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:48:35: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:48:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:49:55: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 10:58:33: prof: WRN: Generated sha-1 does not match given: -04/07/2021 10:58:33: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 10:58:33: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 11:01:43: prof: ERR: IQ error received, id: ZmQ3YThiNjUtN2JlZC00ZDcwLTgyMTktOGVhMGYxMmM3ZDNjYTUzMGE0NWQ0YTY2NWMzNmRjMmUxMzA3ZWY5OWE3MTRkNzgwMGM0YjI3ZjZhYTk1ODMzYjBjNDBkMmRlZDE1Mw==, error: Queries to the conference members are not allowed in this room -04/07/2021 11:01:43: prof: WRN: Error received for capabilities response from conversations-offtopic-reloaded@conference.trashserver.net/mazyani: -04/07/2021 11:01:53: prof: ERR: IQ error received, id: YTA3ZmY4NWEtODc3ZC00ZGY5LWI1YjMtYWE0OTRlYTMwYmNkMGRkOGI3NjBjMjhhYjQ2MzA0MDg4MTdkNTQyZDlkZjI3MzM4ZTI2Y2ZlNzhlZDJmOWQ3YTgyM2E1MjU3Y2ZkZQ==, error: Request has timed out -04/07/2021 11:01:53: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Baba: -04/07/2021 11:12:15: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:12:50: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:13:18: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:14:56: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:15:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:15:13: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:15:19: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:16:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:17:19: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve -04/07/2021 11:19:47: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 11:20:31: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:20:33: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:20:59: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 11:21:22: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -04/07/2021 11:21:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/bullgard4 -04/07/2021 11:25:20: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:25:29: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:25:40: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 11:25:42: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 11:25:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:25:59: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:26:04: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:27:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:27:12: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -04/07/2021 11:27:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -04/07/2021 11:27:54: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Link Mauve -04/07/2021 11:28:08: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:30:13: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:30:18: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:30:18: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:30:30: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:30:55: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:30:58: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:31:04: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:31:09: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:31:27: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:31:41: prof: ERR: Message received without body for room: movim@conference.movim.eu/Link Mauve -04/07/2021 11:31:42: prof: ERR: Message received without body for room: movim@conference.movim.eu/Link Mauve -04/07/2021 11:31:46: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 11:31:47: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 11:31:55: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 11:31:56: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 11:35:26: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 11:35:29: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 11:37:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 11:37:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 11:37:20: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -04/07/2021 11:37:51: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -04/07/2021 11:37:52: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -04/07/2021 11:38:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 11:38:39: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Link Mauve -04/07/2021 11:38:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 11:38:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 11:41:04: prof: ERR: Message received without body for room: hmm@conference.hmm.st/g1n -04/07/2021 11:41:36: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -04/07/2021 11:41:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Matthias -04/07/2021 11:42:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 11:42:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 11:42:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 11:42:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 11:44:57: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:05: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:07: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:07: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:22: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:33: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:39: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:40: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:45:48: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:46:19: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:46:51: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:48:38: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:48:41: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:48:43: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:48:51: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:51:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:51:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 11:51:14: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:51:15: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:52:00: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:52:03: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:53:08: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:53:12: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:53:42: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:53:47: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:55:18: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:55:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:55:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:55:34: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:55:35: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:55:41: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:55:43: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:56:03: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:56:09: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:56:15: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:56:25: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:56:28: prof: ERR: Message received without body for room: chat@dino.im/Link Mauve -04/07/2021 11:56:28: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve -04/07/2021 11:56:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:56:29: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve -04/07/2021 11:56:42: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 11:56:43: prof: ERR: Message received without body for room: biboumi@muc.poez.io/southerntofu -04/07/2021 11:56:45: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 11:57:17: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve -04/07/2021 11:58:33: prof: ERR: Message received without body for room: biboumi@muc.poez.io/Link Mauve -04/07/2021 12:00:12: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:01:17: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:01:21: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:01:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:01:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:02:27: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:04:31: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:05:31: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:07:50: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:08:56: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:09:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/southerntofu -04/07/2021 12:09:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/southerntofu -04/07/2021 12:09:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/Treebilou -04/07/2021 12:10:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:10:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:11:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:12:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:14:00: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] -04/07/2021 12:14:00: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] -04/07/2021 12:14:00: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien -04/07/2021 12:16:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:19:25: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin -04/07/2021 12:21:12: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin -04/07/2021 12:22:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/vm -04/07/2021 12:22:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:25:31: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -04/07/2021 12:25:35: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -04/07/2021 12:26:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:26:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:27:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:27:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:29:34: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:30:34: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:32:31: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:33:32: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 12:38:24: prof: ERR: Message received without body for room: support@room.pix-art.de/yvo -04/07/2021 12:40:36: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:45:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:45:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Link Mauve -04/07/2021 12:46:07: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:46:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:46:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:51:01: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:52:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:52:13: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:52:14: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:53:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:53:26: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:54:08: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:55:50: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:55:55: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:56:19: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:56:26: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:56:40: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:57:03: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:57:20: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:57:23: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:57:30: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:57:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 12:57:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:57:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 12:57:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 12:57:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:57:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:57:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:58:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 12:58:31: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:58:39: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:58:43: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 12:58:53: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 12:58:54: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 12:59:05: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 12:59:30: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:59:30: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:59:34: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 12:59:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:59:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 12:59:57: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:00:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 13:00:12: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:00:18: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 13:00:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 13:00:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 13:01:17: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 13:01:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 13:01:50: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:01:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:01:55: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:02:04: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:02:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:02:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:02:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:02:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:02:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:02:31: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:03:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 13:03:27: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:03:43: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:04:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:04:16: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:04:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:05:37: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 13:05:48: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 13:06:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:06:09: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:06:16: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:06:23: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:06:30: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:06:33: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:06:41: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:06:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:08:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:09:21: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:11:02: prof: ERR: IQ error received, id: ZTQxY2JlOTQtMTY5Ni00Y2UxLWI2ZmMtY2Q2NDMwNGQ5NjIxZjNlMTk0OWY3Njg3ZDZmOWYzNzc3OWU0NjAwNDZmMDE2MWEwMGRhNGZmYTU1YTY4ZTY1NWFmM2YxMmFjOWI2Nw==, error: Request has timed out -04/07/2021 13:11:02: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 13:11:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:11:12: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:11:14: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:11:49: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:11:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:12:21: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:13:22: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:14:00: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:14:20: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:14:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:14:46: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:14:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:15:05: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:16:03: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:16:16: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:16:41: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:17:03: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 13:17:03: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 13:17:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:17:25: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:17:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:17:40: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 13:17:42: prof: ERR: Message received without body for room: biboumi@muc.poez.io/l- -04/07/2021 13:17:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:17:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:18:00: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:18:03: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:18:03: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:18:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:18:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 13:19:12: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:21:02: prof: ERR: IQ error received, id: MjIwNDJkMzctZjY1NS00ZjUwLWE5OTUtMDIwNzk5MTIzNjhhMjFlZGI0ZGY5ZWRkNzg1OTI4MDBmNDhmOGVmNmI2ZTQzY2ZhMzUxMzk4NGRlMmNhNDBhZWE5ODljOGU4NmIxZg==, error: Request has timed out -04/07/2021 13:21:02: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 13:21:03: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:21:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 13:21:37: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:21:37: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 13:21:38: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:21:39: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:21:54: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:22:01: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:22:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:22:14: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 13:22:40: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:22:58: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:23:09: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:23:10: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:23:25: prof: WRN: Generated sha-1 does not match given: -04/07/2021 13:23:25: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 13:23:25: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 13:24:10: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:24:25: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:24:49: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:24:55: prof: WRN: Generated sha-1 does not match given: -04/07/2021 13:24:55: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 13:24:55: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 13:25:10: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:25:12: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 13:26:42: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:26:53: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:27:56: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:29:39: prof: ERR: IQ error received, id: M2Q5ODg3NGItNjBiMS00MmQ3LWFkZTctYmJlYzJlZWMxYmM4ZGMzYWU0YjE3MWY5MGRhZTA2MGM5NGNlOGQ4ZTkzZDNjMDhmY2U1YWU5OGQyZGNhNmFmMDMyNzljYjAzNDhjYw==, error: Request has timed out -04/07/2021 13:29:39: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 13:31:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:37:27: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:37:43: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:37:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:41:11: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:41:33: prof: ERR: IQ error received, id: ODIyYmU0NWQtNDk1ZC00MWE5LWFlNTAtNWE3NjM0MGVmZDA5MWI3MGNjZWM2Njk2ZGY2NTRlNTVkMzIxYTZjMmJmMzE0YTJkNjE3ZDE5Y2JlNTYzMGVmYzI2ODljZmM5OTc5Yw==, error: Request has timed out -04/07/2021 13:41:33: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 13:41:42: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:41:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:42:54: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:44:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:47:16: prof: ERR: Message received without body for room: operators@muc.xmpp.org/ibikk -04/07/2021 13:53:56: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:54:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 13:54:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 13:55:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 13:55:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 13:55:38: prof: WRN: Generated sha-1 does not match given: -04/07/2021 13:55:38: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -04/07/2021 13:55:38: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -04/07/2021 13:57:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 13:57:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 13:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 13:59:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 13:59:38: prof: ERR: IQ error received, id: OGJjMGQ2OTAtOWYyMC00MzJiLWI1NjEtNzVlNTExMWQyZDM5YzE4YzY2M2Y4YTJjMWRkNGE4YzBmM2NiMzBkZGE1N2U2M2FhYjk4ZmZkODhmYjcyZmRmNTQ5ZWQ3OWJkNGUyZg==, error: Request has timed out -04/07/2021 13:59:38: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 13:59:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 13:59:55: prof: WRN: Generated sha-1 does not match given: -04/07/2021 13:59:55: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 13:59:55: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 14:00:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:00:28: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 14:00:48: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:00:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:01:00: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 14:02:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 14:02:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 14:02:26: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 14:02:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 14:05:12: prof: WRN: Generated sha-1 does not match given: -04/07/2021 14:05:12: prof: WRN: Generated : +CzQigt1PrEGRnbUdv1BVfwyXwg= -04/07/2021 14:05:12: prof: WRN: Given : D4WYzeLFHaRoSGdPGp5ghAA9WDs= -04/07/2021 14:09:02: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 14:11:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 14:11:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 14:11:59: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 14:12:20: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 14:14:34: prof: ERR: Message received without body for room: support@room.pix-art.de/emus -04/07/2021 14:14:35: prof: ERR: Message received without body for room: support@room.pix-art.de/emus -04/07/2021 14:15:03: prof: ERR: Message received without body for room: support@room.pix-art.de/emus -04/07/2021 14:20:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:23:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:23:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:23:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:23:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:23:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:24:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:25:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:25:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:25:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:26:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:27:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:27:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:27:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:27:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:27:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:30:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:32:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:51:34: prof: ERR: Message received without body for room: support@room.pix-art.de/yvo -04/07/2021 14:51:49: prof: ERR: Message received without body for room: support@room.pix-art.de/yvo -04/07/2021 14:52:20: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -04/07/2021 14:53:03: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:53:34: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:53:45: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:54:06: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:54:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:54:36: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:54:39: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:54:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/christian -04/07/2021 14:55:33: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:55:56: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:55:57: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:56:46: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:57:06: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:57:35: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:57:42: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -04/07/2021 14:58:43: prof: ERR: Message received without body for room: support@room.pix-art.de/*IM* -04/07/2021 14:58:43: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -04/07/2021 14:59:17: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -04/07/2021 15:06:20: prof: ERR: Message received without body for room: hmm@conference.hmm.st/wgreenhouse -04/07/2021 15:12:09: prof: ERR: Message received without body for room: movim@conference.movim.eu/eyome -04/07/2021 15:16:09: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 15:23:19: prof: ERR: IQ error received, id: ZDRjMTNlMjQtOWU4Zi00YTU0LTllZGYtYzI4NjUyMDE5MjZlN2E5ODI5NTI1MTkwNjUxNjAyODI3ZDZmMzNjNTE3OThlYjhkNzIxM2EzMWFkOGVkZTdmZDQ2NjY1MWVhZTFlZg==, error: Conference room does not exist -04/07/2021 15:23:19: prof: ERR: IQ error received, id: NzNlOWZkMTYtNDE2Mi00MWI5LTk2MGYtMGQzZjZjYTQ1NDcyZjIwODY3NDUxOTg5ZjdiMmU1MWExNGExMWZiZTE1MzVlYTNmYjA1ZWFjNWNlMThkMmRhYjIwM2QzY2EwNDI0NA==, error: Conference room does not exist -04/07/2021 15:23:19: prof: ERR: IQ error received, id: OGNjMTcyNzUtNzU3ZS00YmZiLWE1MDItM2IyOGJkMzc2OTZiMWIyMTVjMmMyM2RkNWY1ZTczMTgzNjE1Y2Q2OTM1NDNiOTg3NDBiYWM0YmE5NGE1NzlkOGMzNjA0ZWRlNzk5Zg==, error: Conference room does not exist -04/07/2021 15:26:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/404.city -04/07/2021 15:31:48: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:31:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:32:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 15:32:36: prof: ERR: IQ error received, id: OGUwZDI1YWUtYTcwZi00NTNhLWEyY2QtNmRjODQwNjdjNzRjMTFjZWQxYjZjZTYyMTliNjNmMmI1ZTk4NWZkMDM1MzVmMmEzNGNiMDU3M2ZjNzhiYWMxNzJmMDVmNzIyMjI5NA==, error: Request has timed out -04/07/2021 15:32:36: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 15:32:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 15:32:50: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 15:32:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 15:33:03: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 15:33:12: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 15:33:43: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 15:37:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:38:42: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:41:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 15:41:50: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 15:42:22: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 15:42:23: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 15:42:47: prof: ERR: IQ error received, id: YjBlOTY5YTQtMTRkMi00MGJkLTk3MWEtNjc1ODIwYTYxMTFjODRiMDU4M2QyMjE2YTc0N2ZkOGM4MWM2ZDliY2IyZWY0NzdlNjBiYjIwZjNkZjRiZTU1Y2RjYzY0MDhkNDhhZA==, error: Request has timed out -04/07/2021 15:42:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 15:43:35: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:44:36: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:45:12: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -04/07/2021 15:45:14: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -04/07/2021 15:46:08: prof: ERR: Message received without body for room: support@room.pix-art.de/dominion -04/07/2021 15:46:26: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:46:28: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:46:41: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:46:46: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:47:02: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:47:32: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:49:32: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 15:49:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 15:49:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 15:49:39: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 15:49:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 15:49:53: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 15:49:55: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 15:50:04: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 15:52:14: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 15:52:14: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 15:52:25: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 15:56:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:57:40: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 15:58:29: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 15:59:50: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 15:59:51: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 16:00:06: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 16:00:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 16:00:18: prof: ERR: IQ error received, id: ZjQzYTBmMmMtMmJmYi00MTM0LTgyNzctMTA2Y2EzNzZhM2FkNmJhZjI5ZWJjYzgzYTkzNDM2NTg2ODY4Mjk0OGQwNDMwYjMyMzEzODNjODdhOTYyZDgzNTNlMDFjMWFiZmExNw==, error: Request has timed out -04/07/2021 16:00:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 16:00:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 16:03:19: prof: ERR: Message received without body for room: en@chat.404.city/support -04/07/2021 16:10:20: prof: ERR: IQ error received, id: ZWRlNDA1ZmYtZWM0Yy00ZTQ2LTgyMDctZThhMmU1NGQ0OTRjOGJhNzFkOTViNzJmOWVkODFhNmYxMDA4MmE4YmMxNmQ1ZWJjNTk0MWY0NjFiNTViNGE3YzQ1NzJhMTVhZjMxOA==, error: Request has timed out -04/07/2021 16:10:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 16:15:00: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 16:15:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 16:17:32: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 16:19:28: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 16:29:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 16:30:16: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 16:30:19: prof: ERR: IQ error received, id: YzQ0ZDkxZWUtZjdhOC00ODIxLTgxYzctMDJiMGU4NWZkOTliYzFmNzNkZDE5ZDhiNGZmMDhiNWZlNTg2MWMwMDQ1YTkwM2IxMjIzNDhmYzIyMmNlZmQ3NzAzM2FhNmUzYzI2Yg==, error: Request has timed out -04/07/2021 16:30:19: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 16:30:23: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 16:30:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 16:31:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 16:31:02: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 16:38:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian -04/07/2021 16:38:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian -04/07/2021 16:42:42: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 16:42:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 16:45:25: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 16:49:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -04/07/2021 16:49:31: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/osprey -04/07/2021 16:52:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/allie -04/07/2021 16:52:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -04/07/2021 17:00:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:00:39: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:01:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:01:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 17:01:35: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:01:42: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 17:01:42: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 17:01:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 17:01:50: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:02:08: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:02:14: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:02:15: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:06:21: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -04/07/2021 17:07:20: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:07:34: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:07:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 17:07:44: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 17:07:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 17:07:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 17:07:49: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:09:32: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 17:09:32: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 17:11:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:11:30: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:13:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/fugata -04/07/2021 17:13:21: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:13:21: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:14:03: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:15:45: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:16:14: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 17:16:17: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 17:17:24: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 17:32:24: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:32:37: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:32:51: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:32:52: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 17:34:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:35:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:40:52: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 17:41:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 17:44:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:45:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:46:41: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -04/07/2021 17:46:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:47:30: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:47:52: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian -04/07/2021 17:47:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/Demian -04/07/2021 17:53:43: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 17:53:57: prof: ERR: Message received without body for room: en@chat.404.city/kraver -04/07/2021 17:54:46: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 17:55:02: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:55:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 17:55:17: prof: ERR: Message received without body for room: xmpp@chat.yax.im/MattJ -04/07/2021 17:55:17: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 17:55:33: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 17:55:34: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 17:55:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:55:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:55:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:56:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:57:37: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 17:57:40: prof: ERR: Message received without body for room: emacs@salas.suchat.org/toggle-debug-on-error -04/07/2021 17:58:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:58:29: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:58:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:58:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 17:59:03: prof: WRN: Generated sha-1 does not match given: -04/07/2021 17:59:03: prof: WRN: Generated : exKm3kVTNmQgDs6u4ZYbeh3mf38= -04/07/2021 17:59:03: prof: WRN: Given : qEnzKHv8Jt9GnghvePgxtG8ISps= -04/07/2021 18:00:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 18:00:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 18:01:03: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 18:01:03: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 18:01:21: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 18:01:21: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 18:02:08: prof: ERR: IQ error received, id: YTdmMTRkN2UtYWUxNi00NWRlLTg4YzYtYzI1ZGFiNmM1N2M5NTU2NGRmYjFiZDg5MjU3NWZhZGZiZWUyMjI4MjIzMzZiNWFkYWY4ZDFiNmEzZDJlNmVlYWU2YmRkY2U4ODYxMQ==, error: Request has timed out -04/07/2021 18:02:08: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 18:02:37: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 18:03:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 18:03:24: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 18:04:27: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 18:04:27: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 18:05:41: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -04/07/2021 18:06:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qy -04/07/2021 18:08:05: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 18:08:08: prof: ERR: Message received without body for room: support@room.pix-art.de/Dirk S. -04/07/2021 18:09:03: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 18:09:24: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 18:11:14: prof: ERR: IQ error received, id: MDlhMWU4YWQtZjY0MC00YzFkLTk1ZWMtZmExZGI0OGU1M2I1NGNjNjdkNDJhNzY2YTljZGEwOWViMDA1ODQwNjBlNGRkNWQ3NjBlOGMwZTU2MjJjNDNmMjQyNjAyNTBmYTgyNQ==, error: Request has timed out -04/07/2021 18:11:14: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 18:17:42: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -04/07/2021 18:17:42: prof: ERR: Message received without body for room: xsf@muc.xmpp.org/MattJ -04/07/2021 18:17:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 18:17:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 18:17:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 18:18:56: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:19:57: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 18:21:18: prof: ERR: IQ error received, id: NThjZjk0MjEtMzVjNC00ZjkzLThhNjEtMjAyZGFlNDA3NzA5ZGJkYTIwMjViZTNlODEyYjI3N2VmNmM1NjQ4YjEwOGUzMDg4ZThjOGYxNzg3MmY4YTI2ZTA0ZGViMWExMWE3Zg==, error: Request has timed out -04/07/2021 18:21:18: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 18:22:40: prof: ERR: Message received without body for room: xmpp@chat.yax.im/Maranda[x] -04/07/2021 18:23:20: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:23:20: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:23:20: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:23:24: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:23:24: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:23:24: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:23:28: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:23:28: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:23:28: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:23:47: prof: ERR: IQ error received, id: MGMyNzgxODUtNjUwOS00YWIyLTlmZjMtOGJkYjA3ZDM4ZDNmZThhMWEwOTg1NWY1Y2ZkM2NhNWQ5NGRkYWIzY2UyNDZmMjY3ZDI2ZTM1OGE5Mjg5ZDgyM2M2M2MzMWZmNWQ3Yw==, error: Request has timed out -04/07/2021 18:23:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: -04/07/2021 18:23:57: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:23:57: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:23:57: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:24:40: prof: ERR: IQ error received, id: YWJhNWI5ODMtMmZhNy00MzFjLWE2OTEtODU2ZTljZGNlMzg2MWZmOWJhNDQ5NTBlNWI2YTUwMmJiMzIyYzc2MjA5NDIyNDlmYzNiNTA1OTMyMzY0MzQzMTE1ODMxM2Q3NDgxMg==, error: User session terminated -04/07/2021 18:24:53: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:24:53: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:24:53: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:24:53: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:24:53: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:24:53: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:24:53: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:24:53: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:24:53: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:24:59: prof: WRN: Generated sha-1 does not match given: -04/07/2021 18:24:59: prof: WRN: Generated : qOJceTZcYa4WWg64zJo+oRe5yhE= -04/07/2021 18:24:59: prof: WRN: Given : s+EYjUb70g/04A2tZ8xwrhPGY7s= -04/07/2021 18:25:16: prof: ERR: IQ error received, id: MTI5MDFmZjEtMzQ4NC00N2JmLThiMDQtMmIzYWI1OTVmZDY4YmRjOTEzYmIxMzE2ZDVhZjg4Njg2YTI4MWRjM2QxNWNiMDlkNDg2OTAzNzg4Yjc5NDY4MWI5NGY0MmE2Yzk5Yg==, error: Request has timed out -04/07/2021 18:25:16: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: -04/07/2021 18:26:01: prof: ERR: IQ error received, id: OWRhZDY3N2UtZjI4OC00ZmQ4LTk3MTgtYTBiNGZjOTk0MGQ0MTY5ZjAzM2UxY2NiZjRjNGFhMDdiNmVmZmQ1MGE1MWRlZmY2YjA1NjIzODA5MjNlZTEyOTk2YTJjNTY4NDUwYQ==, error: Request has timed out -04/07/2021 18:26:01: prof: WRN: Error received for capabilities response from en@chat.404.city/sander: -04/07/2021 18:26:01: prof: ERR: IQ error received, id: NTYwNzMwMWEtZDMyNC00MzkyLTk3MGYtZTUxZTczOTUwNmY4MDhmNmE0MTA2OWQxYTlkMDdlYmJkMWU1MmNkZTc0NDUzM2UxNmNhMzIxNjdhZTFhN2E5ZmM4M2IzZjIxOWY4MA==, error: Request has timed out -04/07/2021 18:26:01: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 18:26:01: prof: ERR: IQ error received, id: NTk2MTZjYzUtZjE2ZS00ZDllLWJjZTctMWZkYmJiNzMwZWNkZjA4MjQyMzExNjEzNmRkMWQwOTZiY2JhNDFhYzAzYTJlNjM1MjYzMjQyZGNjOWFhZDQ4MWIxNTIyMDU1MjM2YQ==, error: Request has timed out -04/07/2021 18:26:01: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: -04/07/2021 18:26:24: prof: ERR: IQ error received, id: NGJhYzhkNTEtYTE4NC00NDNlLWI1NGQtM2VmMGVkYmRiZTVkM2U4MTYyZDE5OTUzZWU1NGIxMWQyNTU1OTg3OGU1ZTEzOWIxZTdiNzMzNTRjYzYxMzI3MTc0NDEzOTk4NTQ0Yw==, error: Request has timed out -04/07/2021 18:26:24: prof: WRN: Error received for capabilities response from en@chat.404.city/sander: -04/07/2021 18:26:24: prof: ERR: IQ error received, id: NjVkOTkwOGQtMWY4Zi00ZDFkLTgyOTEtNWQwYjJkMWIxYTFlODQ4NTNmZDNkMjk4MGU0MjI5NzEyMzE2YWI1MTBjNmFjMDQ4MWQwODNhZThiMWVlOTBlMDU0NDkzNjE4YmJjNg==, error: Request has timed out -04/07/2021 18:26:24: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/sander: -04/07/2021 18:26:25: prof: ERR: IQ error received, id: ZjFhNjYxYWItZDIxMy00MTUzLWFiZDMtZWQ5OTgxODMxNTdiMDVkNDU2ZmIyYWM5MzNhYzM2ODNkZWM5MmY2ZjFjMjc5ZGNhNDdmZjVlZDVhY2E4YmE1Y2ZmOGFkMGE0Y2U0Nw==, error: Request has timed out -04/07/2021 18:26:25: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 18:27:11: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice -04/07/2021 18:28:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:28:36: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:28:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:28:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:30:09: prof: ERR: IQ error received, id: N2FlMTAyMGQtNGRkYi00NTI5LWI2MjQtM2IzYmZlYTJkZjFhZmM0OWZhOTc0YjE2Yzk4ODg2ZDY3NWE5MWIyZWI2Y2EwN2Y1Y2Q5NTU2MDliYjY4ZDY1Y2ZiYzMwMTI4MThhZA==, error: User session terminated -04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 18:30:09: prof: ERR: IQ error received, id: MmU4M2I4YTQtNjNjMi00NjkwLWE2OTctZDQ2Mjc5YmFhNDRhNjFjMzVmMDBjYjgzOWJlZmY5YjEwYjIzYmM1ODYxYWI1MGRkMjYwZTYyOGQwMWFhZTUwMGVlMmJlZmE3ZWEwYw==, error: User session terminated -04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 18:30:09: prof: ERR: IQ error received, id: YzVmOWJmMTItMjYxMy00OGU1LWIzYzctNDkxYmJlYTAxYjBlZjgyMjgwYzQwMjBjZTVmYzE2ODNlNDI5NjU0OTU3ZGFiOWZlMDkwZmQ2Y2VhNmVhNzJhMzFkZGRjZDNkYzk5Yw==, error: User session terminated -04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from operators@muc.xmpp.org/sander: -04/07/2021 18:30:09: prof: ERR: IQ error received, id: ZjgzZDZiZDUtMzUxNS00MTI4LTk3MzUtMzFmMzY1MTBlNTQwYWI2M2JmYThmZWIxMzJiNTU1OTJiYWRjY2ZlODEyZTAzNTliZjU0ZDg4MmNlMTNjZTg1MDM5YzEzM2JmOTA0Mg==, error: User session terminated -04/07/2021 18:30:09: prof: WRN: Error received for capabilities response from operators@muc.xmpp.org/sander: -04/07/2021 18:30:35: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:30:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/qv -04/07/2021 18:32:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:32:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:33:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:33:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:33:30: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:33:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:33:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:34:01: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:34:09: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:34:14: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:34:24: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:34:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:34:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:34:57: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:35:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:38:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:38:58: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:39:03: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:39:07: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:39:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:40:23: prof: ERR: IQ error received, id: NjRkYTEwYTYtMzU1YS00ZWNlLTgzZjAtZTVhZjM4NjJhNjg0NzRjNjliOTFiMTM3NWM0YmNlYjEzZWNjNDk2ZDYxM2U0YTM2MDVkNzFlZGQwMTMyMzY1ZDMzMWI4OWE3ZGI4YQ==, error: Request has timed out -04/07/2021 18:40:23: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 18:40:34: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:40:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:41:13: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:44:02: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:44:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:44:57: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:45:51: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 18:51:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 18:51:12: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:51:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:51:22: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:51:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:51:26: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:51:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:51:59: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice -04/07/2021 18:52:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:52:28: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:52:32: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 18:53:20: prof: ERR: IQ error received, id: M2JjN2ZkMWEtZWQwNy00NTU2LWIxZGItODc5YTUzM2FlY2MyYmU5ODI0OGE5NDg2ZTQ5MjcyMjRiOWI4MjllZjIzNzg1N2VhNmJmZGY1ZTkxZDBjMGQ1Y2ZmZTdmNGZjNDA2NQ==, error: Request has timed out -04/07/2021 18:53:20: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 18:55:12: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:02:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:02:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:03:18: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:03:58: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:04:00: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:04:41: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:05:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice -04/07/2021 19:05:56: prof: ERR: IQ error received, id: ZTU5NGQ2ZDItOWMxNy00ODc3LTk0ZjItMGFkMWM0YjU4Y2NjMTI3ZjUzYThiNGEwMDYzMGUwNWUyOThjMzI2ZGIxZGU2OTc1YzE0Y2YwZTlmYjcwYTQyYjY2MGZiOGY5ZmVmYQ==, error: Request has timed out -04/07/2021 19:05:56: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 19:06:22: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:06:22: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 19:06:22: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 19:06:22: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:06:24: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:06:46: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 19:06:46: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:07:22: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:07:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:07:35: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:07:36: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:07:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:07:43: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 19:07:44: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:07:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:08:01: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:08:02: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:08:11: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:08:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:08:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:08:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:08:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:09:25: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice -04/07/2021 19:09:32: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:09:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:09:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:09:55: prof: ERR: Message received without body for room: en@chat.404.city/support -04/07/2021 19:09:58: prof: ERR: Message received without body for room: operators@muc.xmpp.org/404.city -04/07/2021 19:10:01: prof: ERR: Message received without body for room: operators@muc.xmpp.org/404.city -04/07/2021 19:10:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:10:17: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:10:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:10:27: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:10:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:10:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:10:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:12:00: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:12:14: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:12:41: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:12:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:12:46: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:12:49: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:13:28: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:13:44: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:13:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:13:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:13:48: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:14:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:15:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:15:14: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:15:20: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:15:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:15:40: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:15:51: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:16:06: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:16:06: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 19:16:10: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:16:19: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:17:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:17:23: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:17:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:17:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:20:16: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:20:22: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 19:20:22: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:20:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:21:02: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:21:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:21:20: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:21:34: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:21:46: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -04/07/2021 19:21:48: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:22:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:22:24: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:22:35: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:22:46: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:22:47: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:23:03: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:23:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:23:55: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:24:12: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:24:15: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:24:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:24:31: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:24:38: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:24:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:24:51: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:24:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:24:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:24:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:25:04: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:25:04: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 19:25:11: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:25:13: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:25:29: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:26:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:26:12: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -04/07/2021 19:26:27: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:26:47: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:26:57: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:27:04: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:27:08: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:27:22: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:27:30: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:27:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:27:42: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/ij -04/07/2021 19:27:42: prof: ERR: Message received without body for room: neurodiversity@chat.neurodivers.de/ij -04/07/2021 19:27:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:27:45: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:27:49: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:27:57: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:27:58: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:28:01: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:28:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:28:39: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:28:42: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:28:51: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:28:53: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:28:55: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:29:14: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:29:15: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:29:17: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:29:25: prof: ERR: Message received without body for room: chat@dino.im/Kazuky Akayashi -04/07/2021 19:29:54: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:30:37: prof: ERR: Message received without body for room: autism@chat.neurodivers.de/qy -04/07/2021 19:30:55: prof: ERR: IQ error received, id: MmIyMzc1ZGItZTg0NS00MDdhLThjMzktYzVjYzM4MTI0OTA1YmE5NjkyN2JkYjNkNTA2OWRlMjU5Y2VhZmIyMjU2ODA4NTkzN2IwMDMwYzJkN2Y4YWJmNjMxMTg3MGNlNWNiMg==, error: User session not found -04/07/2021 19:30:55: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 19:30:56: prof: ERR: IQ error received, id: NmE2NDRjMTItYTU3Mi00MzkzLTlkN2UtY2IxODQ0ODlhOGM1YjlhNTYwYTE0MjVmMDc0NTRlMTIxYTY1YmU5OTBiMmNhNDAyYTgxZjJjZWQyMzE2YTQzNDQ4ZDJmYzNhOTExOQ==, error: User session not found -04/07/2021 19:30:56: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 19:31:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:31:28: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:31:35: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:31:44: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:31:53: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:32:06: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:32:26: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:32:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:32:36: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:32:37: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/kompowiec2 -04/07/2021 19:33:10: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:33:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:33:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:33:37: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:33:40: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/chunk -04/07/2021 19:34:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:35:15: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -04/07/2021 19:36:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:41:31: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:41:35: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:42:22: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:42:32: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:42:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:43:39: prof: ERR: IQ error received, id: ZWQzNjE5YWYtYzZjNS00ODA2LTg4OWEtOGE4MDkzNTBlNzQwMjVhY2ZkOWJhNTI3MTNmNGFmYmM2MzUxNjFkMGYxNTYyN2M1MGUxNjA4OTRjOTQ1OWFiMDViZWE2OTI5Yjc5Ng==, error: User session not found -04/07/2021 19:43:39: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 19:43:46: prof: ERR: IQ error received, id: ZTgyNmZjYmUtZmY2MS00Y2M1LTliNDMtYzFjZjhhMDlhZGZlM2M5OTA1M2FiNzE4MzA5MjI0MWRlNWE5ZjMwMmQ4MTE1MmViNTUxNDhlMzQyNjA3ODNiOTJhNDcyZDVhN2ExZA==, error: Request has timed out -04/07/2021 19:43:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 19:44:00: prof: ERR: IQ error received, id: NDNhYTc1NzQtYWEzMC00ODU3LTk3YzQtN2ZlM2M5MWE2YWUzMzcyODg4NTRjOWZiMzI4ZTNiMDliNDhkMjEyNDUyYzk0MjkxNTQ5MWZiODUyYzNlMjY3ODgxYjI0YWVjNzI5MQ==, error: User session not found -04/07/2021 19:44:00: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 19:44:09: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice -04/07/2021 19:44:10: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/alice -04/07/2021 19:44:37: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:44:39: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:44:42: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:45:47: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:45:48: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:45:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:45:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:46:58: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:46:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:46:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:47:03: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:47:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:47:20: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:48:07: prof: ERR: Message received without body for room: profanity@rooms.dismail.de/mwuttke97 -04/07/2021 19:48:40: prof: ERR: IQ error received, id: YjA4ZGQ3NDItZWFkYy00ODY5LWI5NzAtZWM3YTNmODhmYjlmOTgyZDcyM2I4ZmU5YzA5YWVlNGFjMzdjY2Y0MDI0Mjc1ZGFhMTI0NTQzZTZjYjY5ZDllMGY5MzliODIyNWIwNA==, error: User session not found -04/07/2021 19:48:40: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 19:48:40: prof: ERR: IQ error received, id: OTczNTgxOTItZTkxMC00NzE3LThhOWItN2U3YjBlM2FhZGUwYTFlZTU5ZGRhMDBhNTA2ZWZkNzczOWIwYjYxNjE3ZWE1NzU5MWIyNDAwZWYxYjI5OGI2YzNkYmMyYTgwNDY2Nw==, error: User session not found -04/07/2021 19:48:40: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 19:53:29: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:53:41: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:53:43: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:53:44: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:53:47: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:54:29: prof: ERR: IQ error received, id: N2NlZmNkMjMtNWZlYS00YWU5LTgxNmEtZjc5NGFlOWU4MzgzYmYwMDJlOWJjNjI0YTJlZWNjMjZmMTQyNmNkMjkxYmU3YmQ5MTI4OWFiYWIwNzM5OTY2NzM0N2VlNmQ1YWU3YQ==, error: User session not found -04/07/2021 19:54:29: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 19:54:29: prof: ERR: IQ error received, id: MmFmYTQ2YTktMGJjNi00ZWRkLWEyMDItM2IxNTVmYmUyNjE4Y2U2OTUxYzdkZWIwMGRmZDNmZDJjZTNhNzMzMGE0ZTEzN2I1NjFhNjNkYTcyZjkwZDU4MWM4MTIzMjJiNjAzNA==, error: User session not found -04/07/2021 19:54:29: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 19:55:13: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 19:55:13: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:55:15: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 19:55:15: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:55:55: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 19:56:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 19:56:37: prof: ERR: IQ error received, id: ZTJmMDkwNTAtZjljNi00MDE1LWIxNWMtOWVkNDA1ZjE0ZDhjNzcwMmYzY2U3Y2VhMjQ4Y2ZlZjdhNzJlYjE1ZTM3Njc1YzE2NDcxZDkzODNjOWI4YzBlOTQwY2ZlNmMxODUzNQ==, error: User session not found -04/07/2021 19:56:37: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 19:56:37: prof: ERR: IQ error received, id: YTJjZmFhNmEtNTgyMi00Y2FlLTkzNWQtMWU5ODJlYjZjNGJjZjAxZjE1ODZhNTZiYWNmM2ZkMDZhNzY0MDg1MjRkZDhiZDEzMmJmODEyMTE1NWQ5ZjUzYWZkMDY0NGFlY2FkYQ==, error: User session not found -04/07/2021 19:56:37: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 19:56:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:56:45: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:56:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:56:57: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:57:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:57:04: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:57:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:57:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 19:57:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:57:50: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:57:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:57:55: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:57:55: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:58:00: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:01: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:58:04: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:13: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 19:58:19: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:20: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:21: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:24: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 19:58:24: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:58:37: prof: ERR: IQ error received, id: ZmI0ZmRlNmEtNWY2OC00ZjNlLTgxYTItOTdiYzgwZWYwNzg1MjU3NjNmMmVmOTgwZGM1ZTgxNTJlMzQ5YTM5N2MwMDI1MDAyNmQ5MWYzMTMzY2Y2MjRkZGNkZDc0ZmVmNzcwMw==, error: Request has timed out -04/07/2021 19:58:37: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 19:59:00: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:59:06: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 19:59:07: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:59:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 19:59:33: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:59:34: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:59:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 19:59:53: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 19:59:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 19:59:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:00:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:00:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:00:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:00:19: prof: ERR: IQ error received, id: ZWZiZmUwMjMtZDlmNi00MGE4LTllNWUtYTlmZDY0ZDdjNjUyZGRiOWRlOTYyYjIxMWYzZWJhZGQ4NDAwMjE1MDRmZWFkYzlkY2FhZGQ1MTEzZjM3ODhmOWJiNTk0YmRjMzRlYQ==, error: User session not found -04/07/2021 20:00:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:00:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:00:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:00:49: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 20:00:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:00:50: prof: ERR: Message received without body for room: modernxmpp@rooms.modernxmpp.org/lovetox -04/07/2021 20:00:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 20:00:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:02:03: prof: ERR: IQ error received, id: MTQ1N2ZkZmItNmQ4Mi00Y2U4LThlMGItMzJiZmE3MjYwNzU2ODI5MmQ5YTIxZmNhYzkzZjA5M2UyZjVjNWQzNTY3MWFjM2E3NWQzNGRkOGY3MzRjYThiM2NkZWM5ZWQwZTc5Ng==, error: User session not found -04/07/2021 20:02:03: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 20:02:03: prof: ERR: IQ error received, id: OGRjNjU2NzMtNDM2NS00NTJlLWIxNGMtNjY3NjViN2JmYTcwYWU3NTZlZjZlZTg2ZWY1ZWFjMjZjNWQzZDkxY2YxMjIyZWQ2ODFhNjM5MDFlY2E1YzI3NTc1ZDNiZGZlOTRlMg==, error: User session not found -04/07/2021 20:02:03: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:02:15: prof: ERR: IQ error received, id: YjBiZGQ2YTItYTE2Zi00OWM1LWI2YWUtZjc4MjUxZGFjZDE1MjU4ZWVmYTJjOWNhZmQwZTkyYTk3MzhhNWUzMThhZTBhMjIyNzRiNjA3NDcxYzA4MWIzOGU4ZGE2ODEyMGQ3MQ==, error: User session not found -04/07/2021 20:02:15: prof: WRN: Error received for capabilities response from gajim@conference.gajim.org/sander: -04/07/2021 20:02:15: prof: ERR: IQ error received, id: ZGJlN2RmMzYtZDc4Yy00YTFhLWE3NmItYzMyNjU0OTc1OTUyNWU5OWRiMzVhNTgyYjkzOTkxMGMxMTg0OGVkNjE3YzA5ZDcyZWExYjYzY2I2ZGRjODk4MTczY2U1MDA5MDEzYg==, error: User session not found -04/07/2021 20:02:15: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:03:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:03:42: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mirux -04/07/2021 20:03:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:04:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:04:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:04:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:04:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:05:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:05:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:05:30: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:05:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:05:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:05:47: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:06:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:06:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:07:21: prof: ERR: IQ error received, id: NTEyYzVlZTAtMjM3YS00ZTg1LWIxNTEtM2YyNDllZjUwZWY3MzU3MTFjNzExOTdkNmI4YTIwNDM4ZGQwZDU5ZGY0ZDE0OGMzOWVhOTk2ZTYyYmRmYjk0N2MwNWZlNGI5MjQxNA==, error: User session not found -04/07/2021 20:07:21: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:08:34: prof: ERR: IQ error received, id: YmU4NWFhNjUtYjRjNy00ZTJkLWE5ZWQtNzRhMGQxOTcwNDRlZWJhN2EwYzJjNDIwZDgyNDAzMTJhZmEzOTE2Yjg4NWM1YzU3MWU1MmU5NzJjMjk5NWUyM2Y2ZTExMDZjMjFjZQ==, error: Request has timed out -04/07/2021 20:08:34: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 20:09:36: prof: ERR: IQ error received, id: ZjgzYWMyMGItMjllOC00Yzk5LTlhZjAtZmZmMzQyNGI2OTFkNWU2MGY2ZTQyMWU2MTMxYTA5YzlkODcxMzIwNDdmNzZhNWFiN2YxMjI5MGJkZTdhZTE5OGRhMTYyMTFlZTM5Nw==, error: User session not found -04/07/2021 20:09:36: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:10:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:10:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:10:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:11:00: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:11:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:13:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:14:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:15:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:15:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:16:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:16:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:16:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:16:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:16:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:16:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:17:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/jumbuck -04/07/2021 20:17:04: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lemoldu -04/07/2021 20:17:04: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/lemoldu -04/07/2021 20:17:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:17:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:17:33: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:17:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:18:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:18:37: prof: ERR: IQ error received, id: ZjM0MTYzNWYtNjA1Ni00MTU2LTg4ZTktNGI3ZWQwZWJhN2I5NDNiMjViNjE5ODQ1MjgwZWQxZWIyMWMyNDIyMDAxZDUwNzFhMDY2NWY0YTlhOGIyM2NkMzc1NTE1ZmI0NzAxMQ==, error: Request has timed out -04/07/2021 20:18:37: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 20:19:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:19:16: prof: ERR: IQ error received, id: MTRjMjIzNzktODRjMS00NzU5LTg3NWItZTA2M2ZiY2UwNTdiYTNjOGEwZDFiYTNlOTdjZDVmOWZmODEyM2ZjYzA0NDBiZmMzYjRjZWJkMzNiOWE1MmM2MDM5YmJlNDhjZDA4MQ==, error: User session not found -04/07/2021 20:19:16: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:19:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:20:37: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mirux -04/07/2021 20:20:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:21:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:24:23: prof: ERR: IQ error received, id: ZmFkODI5YjMtNjBlNi00ZjdmLTllZTEtOTYyYWEzNjQ1NzMwZjA4NWJhNjJhZGZjM2Q2NDA1YTliZWYwMTljYzhlNjRkYjNiNGFhMjgzMmZjYzlkYzUyMzhiNTQyYWEzMWVmNQ==, error: User session not found -04/07/2021 20:24:23: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:26:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 20:26:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/mirux -04/07/2021 20:28:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:29:24: prof: ERR: IQ error received, id: ZDc5ZmQyMzgtZTBhNy00NTgyLThlOTYtNzA0Y2E4OWJiM2I3Zjc0N2UwZjA5NDBjYTQ4MWI0Y2U2ZjFjMDFlZjQwYmNhZDY2ZDk5YjU5NGI4ZmNiODQyNTQyNDAyYTAyYWYzNg==, error: User session not found -04/07/2021 20:29:24: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:30:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:34:34: prof: ERR: IQ error received, id: YzMzOGM4ZTctZTQzZi00MjQ4LThjMDgtNWUzODc3ZmEyNzQ3ZDY4MmJlYmYyMDUxNzVmMTNjNWQyNTY1NTFlMzk0OGU4ZTA3NzJhNGVmM2RmNzdiYjEyZjQ2NGI2ODYzMjlmOA==, error: User session not found -04/07/2021 20:34:34: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 20:40:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:40:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:40:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:41:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:41:36: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:41:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:41:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:43:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 20:48:06: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 20:48:08: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 20:51:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:08: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 20:51:11: prof: ERR: Message received without body for room: operators@muc.xmpp.org/MattJ -04/07/2021 20:51:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:51:59: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 20:51:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 20:55:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 20:55:28: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 20:55:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat -04/07/2021 20:56:33: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 20:56:39: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 20:56:43: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 20:56:46: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 21:01:18: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 21:01:49: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 21:01:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 21:01:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 21:02:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 21:02:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 21:04:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 21:08:06: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo -04/07/2021 21:08:19: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo -04/07/2021 21:08:20: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo -04/07/2021 21:08:34: prof: ERR: Message received without body for room: support@room.pix-art.de/Demo -04/07/2021 21:11:29: prof: WRN: Generated sha-1 does not match given: -04/07/2021 21:11:29: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -04/07/2021 21:11:29: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -04/07/2021 21:11:34: prof: WRN: Generated sha-1 does not match given: -04/07/2021 21:11:34: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -04/07/2021 21:11:34: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -04/07/2021 21:14:32: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:14:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:14:58: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:15:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:15:54: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:16:03: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:16:13: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:16:19: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:16:19: prof: ERR: IQ error received, id: ZjczNWRlODctMGUwMi00MjQyLTkzYjYtZWQ1M2M1MWJmODg5NThjYjlkMmUyOTM0OWUyMTI4YmNiNDQzNjczZmMwNTdjNzVkMWUzMGQ0ODQwNTNiMTg1ZDJiMmJiOWNmOTQ1MQ==, error: User session not found -04/07/2021 21:16:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 21:16:25: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:16:29: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:16:48: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:17:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander -04/07/2021 21:17:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:17:28: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander -04/07/2021 21:18:18: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:18:40: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander -04/07/2021 21:18:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 21:22:10: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:22:21: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 -04/07/2021 21:22:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:24:50: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:25:20: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:25:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:25:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:25:46: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:25:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:25:59: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:28:08: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:28:44: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander -04/07/2021 21:30:02: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:30:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/lovetox -04/07/2021 21:31:51: prof: ERR: IQ error received, id: NGYxNGNhZDYtYzQ5NS00Yjc5LWE1Y2YtM2MzYjMxNDIzYTNjYWM3NTc4OTdlMGY5Nzk1ZGZmMzgzMjg0NjNmOTg5ZjQ0ZmRkYzgzZmQ1NDRhOTM0ZTdiMDZkYzZiMDQyOGM2ZA==, error: Queries to the conference members are not allowed in this room -04/07/2021 21:31:51: prof: WRN: Error received for capabilities response from conversations-offtopic-reloaded@conference.trashserver.net/dvorak: -04/07/2021 21:32:14: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:33:16: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:33:38: prof: ERR: Message received without body for room: gajim@conference.gajim.org/wurstsalat -04/07/2021 21:37:17: prof: ERR: Message received without body for room: gajim@conference.gajim.org/sander -04/07/2021 21:39:25: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:39:47: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck -04/07/2021 21:40:23: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck -04/07/2021 21:40:26: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:40:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:40:48: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck -04/07/2021 21:40:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck -04/07/2021 21:41:40: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:41:50: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck -04/07/2021 21:41:53: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/jumbuck -04/07/2021 21:42:06: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:42:11: prof: ERR: IQ error received, id: MGNlMDgyOTgtOGFhYi00ZmE4LWE1MjEtOTVkMzdkNjc0ZGFjNWFmYzgzZjI0NmFjYzE0Mzg3OTNjMjc0MzQxOTM5NDBlYWUyNDI5NjU0MzExNDc1MWI2NzM3YTllMTRkMjRjMA==, error: Request has timed out -04/07/2021 21:42:11: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/latino: -04/07/2021 21:45:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:46:53: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:47:54: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:48:04: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:49:22: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:50:31: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 21:50:41: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:51:01: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:51:01: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 21:51:12: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 21:51:54: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:52:28: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:52:28: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:52:31: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:52:37: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:52:51: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 21:52:59: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin -04/07/2021 21:53:11: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:54:10: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin -04/07/2021 21:54:36: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:54:42: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin -04/07/2021 21:54:44: prof: ERR: Message received without body for room: operators@muc.xmpp.org/rozzin -04/07/2021 21:54:58: prof: ERR: IQ error received, id: MTdlYmEwN2QtMzRiNi00NzRkLTg3YzAtZDUyZDk1MTkzY2E1OGNiNmE1ZjlhNDJmNjA5ZjM1YjQwNWY2NGE1MzQ0ZjdhZmYzY2EyYTQxMGIzZmZlNTk2NzM2NGE2OWVhZTExNw==, error: User session not found -04/07/2021 21:54:58: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 21:56:14: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:57:14: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:58:37: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 21:59:23: prof: ERR: Message received without body for room: floss@rooms.dismail.de/klausmcm -04/07/2021 21:59:38: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:00:03: prof: ERR: IQ error received, id: MmQzMzZjMjYtNzM2OC00YzcxLTkyMjItMTUwNjQ0MDRjNGU2MTY3N2UyNzg5MDc4ZWMxNzg4ZDYzZGVjMTM1MmE3M2MxYjhkYWJiYTg0ZDRjMWM1MGU5MDY0MmM4MjZkOTRhYw==, error: Request has timed out -04/07/2021 22:00:03: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/dev: -04/07/2021 22:00:43: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:01:19: prof: ERR: Message received without body for room: en@chat.404.city/poggerino -04/07/2021 22:01:44: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:01:58: prof: ERR: IQ error received, id: MGMzYTUyNGUtNjEzMy00ZmFiLTg0NzgtZTJkNGMxNTY3OGZjODZmZGFlYzAxMDUzZjJmMDM5ZWUzNmNkZGI4NjhmZTYzOGI4MzJiMWU5NjFkZDcwNTRkZWI3MTRiYjUzOTllNQ==, error: User session not found -04/07/2021 22:01:58: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:03:38: prof: ERR: Message received without body for room: en@chat.404.city/poggerino -04/07/2021 22:03:43: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:04:43: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 22:04:45: prof: ERR: Message received without body for room: support@room.pix-art.de/404.city -04/07/2021 22:05:16: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:06:02: prof: ERR: IQ error received, id: ZDJlYjBiNGUtZDc3Zi00ODA0LWI5NmEtODc4OGI2MzBjMjAzZmIwYzkwODMwYzg5NGYwMDgxMmExMWYwZjc1NThjNTJkYmIzOGQ5MDM0M2RkNDE0NDk1OTExMTE5ZDI2MWMyNA==, error: User session not found -04/07/2021 22:06:02: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:06:21: prof: ERR: Message received without body for room: en@chat.404.city/a -04/07/2021 22:09:22: prof: ERR: IQ error received, id: M2UyOGZiM2QtMWNjMC00YjJlLWE1NmUtOGY1MDc1OWU1ZmQ2YzI2ZGQwNzUyMTA3MTIyMDA1M2VlOTI3M2ZlMTViMmU0YzE0ZTNkYTY4MjVkNjVhYjIzZmE2OWU5ZWEzNDhlMQ==, error: Request has timed out -04/07/2021 22:09:22: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 22:10:02: prof: ERR: IQ error received, id: NDNmODNkNzAtN2ZiYy00OTRmLWJiNWItNTI5NmE5MTExMTRiNzhjZWQ5ZDJiOGE2YTU2YzU1YTk5NTZhZmZmZDUwMGM0N2I4NGQ1MTdkNGZhYmZmY2EwYzNiNDU3ZTViZTViZQ==, error: User session not found -04/07/2021 22:10:02: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:10:20: prof: ERR: IQ error received, id: ZDllODgwYzYtZjY4Yy00OTdhLTkyYzEtMDBjNGYzOGNhYjhhZjkwZTRiZWQ3NjA1Y2VhMzI5OGQ3M2U1NzRhYzcwNDRmNWE1ZTE0MWMzNTZjZTNiYjQxZmM3Yzk5N2U2YzU5Zg==, error: User session not found -04/07/2021 22:10:20: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:12:25: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 22:12:36: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 22:12:42: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 22:12:44: prof: ERR: Message received without body for room: chat@dino.im/wkg -04/07/2021 22:19:22: prof: ERR: IQ error received, id: NjZiZGUwNDEtYWJkZS00NDk0LWI5NWUtZjQ5NTc2MTg4N2QyMTk1ZTM5MmM1MTg1N2M4ZDYyNjBlZjM1NWI3YWYyOGM2NzE2NDljNjlhZjcyYWY2MjhlMDM3NjBhMjVlOWU5Ng==, error: Request has timed out -04/07/2021 22:19:22: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 22:20:19: prof: ERR: IQ error received, id: ZTZiZDdiMjktY2E0Mi00M2I1LWEzOTctNjI3NTBlNjZhNGJiMmI5OGE5YzdkZWI5NzY2MjRhYjJmMTU3NGIwOTRiY2RkOGI3NmZiYjJmMWIwMDYxNjY5MTY1ZTM1NmZmM2Y4Yw==, error: User session not found -04/07/2021 22:20:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:21:04: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:21:22: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 22:21:24: prof: ERR: Message received without body for room: support@room.pix-art.de/MattJ -04/07/2021 22:24:34: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 22:24:35: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 22:25:13: prof: ERR: IQ error received, id: NDFjNWI1MGEtZTk5MC00MzQzLWE5ZTgtZjI3ZDEwNzQxMmViOTI5NTI2MzhlYjkzZjU1N2E3NWMyYjA2Mzg0NWVhMDQ1MmEzNmViNTU2Yzg3ZDkwZjQyN2ZjODgyMTBjNmY3Zg==, error: User session not found -04/07/2021 22:25:13: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:25:14: prof: ERR: IQ error received, id: M2QzMjgyNjItYzMwNi00YjliLWExZDctOGJjMDdhMjlmMmNhZThmZDgyNTNlOWUyZDQwZGRiZWNmZDY4MmQwZWQyZDkyZjc0MzM1OTQxYzc1NDdlMDRiZjE5MWMwZTMzYzExZQ==, error: User session not found -04/07/2021 22:25:14: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:26:10: prof: ERR: IQ error received, id: ODFkNTAyOWMtYThhZS00ZTQ0LTkzZjctNjRkZDRmNmY0NzNmODg5ZGM4MTRjOTk4ZTFiY2I3MGRlNTc2NmMxMjVmMjc5ZjE1NDkwNDUxYjE1NzlkN2YzYWI0YWUyMzcyZTkzMw==, error: User session not found -04/07/2021 22:26:10: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:26:41: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:26:57: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:26:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:27:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:27:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:27:38: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:27:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:27:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:28:16: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:28:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:28:17: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:28:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:28:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/mirux -04/07/2021 22:28:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:28:57: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:29:24: prof: ERR: IQ error received, id: MzhkZjc2YWUtN2I0NC00MTM2LTg1NjktMmM1N2E0MDk0ZDU1ZjY5ZTJkOWQ1MzdhODdlZWY5ZTg0MzMxNGM4ZmFhZjkxYzY1MjdhYzMzMDA1MTRlY2Q2Njk3MTc1OGEzZWIwMQ==, error: User session not found -04/07/2021 22:29:24: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:29:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:29:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:29:58: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:29:58: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:30:04: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:30:17: prof: ERR: Message received without body for room: en@chat.404.city/[Alien] -04/07/2021 22:30:17: prof: ERR: Message received without body for room: support@room.pix-art.de/[Alien] -04/07/2021 22:30:17: prof: ERR: Message received without body for room: operators@muc.xmpp.org/alien -04/07/2021 22:30:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:30:44: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:30:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:30:52: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:30:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:31:24: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:31:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:32:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:32:27: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:32:37: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:32:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:07: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:34:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:08: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:34:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:34:59: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:34:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/MattJ -04/07/2021 22:39:22: prof: ERR: IQ error received, id: ODE1NDI0YzYtYjQxYy00ODcyLTliZGYtNDc1N2E5NTM2NWI1Yjg0MGVhMTg2YjFkYjUyMDFiNDg4YzI0ZTQ0YjQ2MWQ3OWQ3MWVjYjA0MTNiNzY5MDFhY2UxODdkMTIzNzlkMg==, error: Request has timed out -04/07/2021 22:39:22: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 22:40:20: prof: ERR: IQ error received, id: NzViM2FmN2EtOGRhNy00MmNjLWEyYzUtYjk1YWRlMGNkNjNkZTA4YzZiZTliMWU1NGIxNDVhM2Y3MTEzYTZhZDkwODk3ODgzMmIzOTI4ODZlMzhjYjhkYTExMGE0NzQ3ZDJkYQ==, error: User session not found -04/07/2021 22:40:20: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:41:07: prof: ERR: Message received without body for room: gajim@conference.gajim.org/darkness007 -04/07/2021 22:41:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:41:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:44:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:45:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:45:31: prof: ERR: IQ error received, id: ZTFiM2EzMGYtOTVmYy00OGZkLWE5OTEtNjNjOTk0Zjg1OGU2NDA3MWRmYzZjYWZmYjBmNWJjNDRkYjJkY2FkYjVjMWExZTdhZjQyZGNjMzBlYjM1YzA1NmVlNzgzNWU4MmRiMA==, error: User session not found -04/07/2021 22:45:31: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:48:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 22:50:19: prof: ERR: IQ error received, id: YzUxZTlhNTktZWEwZi00YWRiLWE0YjgtZThkOWJlODEwODM0Y2UzYjQ4ZmEyMDZhOTdiMzBjODJlY2VjZGZkMTFjYWRiZDRiMTYxMDAxMWZjZjBmNWZjNmU3MjI5YTQ3NmMxOA==, error: User session not found -04/07/2021 22:50:19: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:50:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:50:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:26: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:51:51: prof: ERR: Message received without body for room: conversations@conference.siacs.eu/MattJ -04/07/2021 22:52:51: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:52:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:52:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:52:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:52:56: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:53:25: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:53:58: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:54:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:56:07: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:56:32: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:57:26: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:58:03: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:59:04: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:59:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 22:59:48: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:11: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:00:50: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 23:01:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:01:46: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 23:03:27: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:03:34: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:03:36: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -04/07/2021 23:03:43: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:04:17: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:04:35: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:04:56: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:05:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:05:23: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:05:31: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:05:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:06:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷贝克 -04/07/2021 23:06:54: prof: WRN: Generated sha-1 does not match given: -04/07/2021 23:06:54: prof: WRN: Generated : VwHf6tBMNXyDmcD73/VEHmzdm8E= -04/07/2021 23:06:54: prof: WRN: Given : yVi4SI7C8Fc3YhMuGEM6XTp4ups= -04/07/2021 23:07:39: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:07:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:08:37: prof: ERR: Message received without body for room: prosody@conference.prosody.im/re -04/07/2021 23:10:14: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:11:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:12:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:13: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:28: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:13:29: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:14:18: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:14:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine -04/07/2021 23:16:10: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:16:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine -04/07/2021 23:17:01: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:17:05: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:18:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:18:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:18:21: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:18:42: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:18:50: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:18:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine -04/07/2021 23:19:02: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:19:08: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:19:09: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:19:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:19:22: prof: ERR: Message received without body for room: prosody@conference.prosody.im/k2o -04/07/2021 23:19:54: prof: ERR: Message received without body for room: prosody@conference.prosody.im/kane.valentine -04/07/2021 23:21:40: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:21:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:10: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:41: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:45: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:25:46: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:26:15: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:26:16: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:27:12: prof: ERR: Message received without body for room: prosody@conference.prosody.im/雷克顿 -04/07/2021 23:27:44: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:27:53: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:28:05: prof: ERR: IQ error received, id: YzEwYjRkMTQtMzQ1ZC00ZGM5LTk4ZDctOWZmNzVhZmE3MzkzMDU0OWMwMDk2YzQzYmUzMDk5NzU0MWE3MDUwNDViOGJlYWE4ODVmMTdjNjdmNDkzOGM0MzYxZjUzOGFhNTgyMQ==, error: Request has timed out -04/07/2021 23:28:05: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 23:29:15: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 23:29:24: prof: ERR: Message received without body for room: floss@rooms.dismail.de/Eff -04/07/2021 23:29:59: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -04/07/2021 23:38:06: prof: ERR: IQ error received, id: YzE2YTA0ZDItMTBjNy00NzY2LTg1NDQtYWM4MTExN2EwYjgyNWEwYmVhMGJhNTAxMDIwOWMzYjExMmViMmI4YjI5OTk1NzIzYzBiOGU1YzAzZmE2MzJmOThhZmFjYzYxNDNjZQ==, error: Request has timed out -04/07/2021 23:38:06: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 23:40:01: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:40:03: prof: ERR: Message received without body for room: prosody@conference.prosody.im/chunk9 -04/07/2021 23:40:07: prof: ERR: Message received without body for room: prosody@conference.prosody.im/chunk -04/07/2021 23:40:34: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:40:44: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:40:52: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:41:02: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:41:05: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:43:32: prof: ERR: IQ error received, id: NWQ3ZjAzMDktYTAyYS00MWMyLWE1MTUtYWJjZGViMzQ4ZTNkNmZkNzQ2M2U1MjYzYzJkNDIzMjVjNWQxYjhkZTIxMmU3ZTNjZWRiN2JmYWE0Y2FjYjU3NzdhNzM1YjRhODU1Mw==, error: Request has timed out -04/07/2021 23:43:32: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 23:43:41: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:47:20: prof: ERR: Message received without body for room: en@chat.404.city/jordyn -04/07/2021 23:50:12: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -04/07/2021 23:50:23: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -04/07/2021 23:50:32: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -04/07/2021 23:53:33: prof: ERR: IQ error received, id: Y2YxNWZjZDAtNDhlOC00OTkwLWE3YzktMjk3NzJhYjNkZDA2NWI5YmE4ZWIyMDA0MmM5MmFiODIyNDY4ZmViYjA2OTc5ZWU4Mzg4N2U0MTBmMmI3M2NkNjEyZWI5NGE3NjRlOQ==, error: Request has timed out -04/07/2021 23:53:33: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -04/07/2021 23:53:42: prof: ERR: Message received without body for room: hmm@conference.hmm.st/wgreenhouse -04/07/2021 23:59:25: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -04/07/2021 23:59:35: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -04/07/2021 23:59:36: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -04/07/2021 23:59:46: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -05/07/2021 00:00:10: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -05/07/2021 00:00:21: prof: ERR: IQ error received, id: MTNhZDIwZDQtZTdiNC00M2Y0LWI3MTgtODBjYTQyN2U5OTBmMmQ3NjY1Y2Y2NWVjNzJkZjIyODFiYjQ1ZjgzYjEyNDRjNDhhMzdiZjYxYjlhNjQzNDUwMzBmYjdhMjRmYzBkYg==, error: User session not found -05/07/2021 00:00:21: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -05/07/2021 00:00:47: prof: ERR: IQ error received, id: MmZlYmIxMjUtNjJhMy00Y2E1LTkyZTEtZDZhMjFmNTg5YjAzMTJkZDMwNDY4OGE0ZDU1Y2QxYzYyZDA4YjM4NTg4M2E5MDNhNzcxMjAzNDQxYmQzYzBkYTU5NzE5MWYwNzZkMQ==, error: Request has timed out -05/07/2021 00:00:47: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -05/07/2021 00:01:17: prof: ERR: Message received without body for room: en@chat.404.city/Jordyn -05/07/2021 00:05:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -05/07/2021 00:07:57: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -05/07/2021 00:08:15: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -05/07/2021 00:08:21: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -05/07/2021 00:11:12: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -05/07/2021 00:11:16: prof: ERR: Message received without body for room: gajim@conference.gajim.org/kenneth.baumann -05/07/2021 00:20:19: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -05/07/2021 00:20:20: prof: ERR: IQ error received, id: Y2I5NzNmNmItZmNhZi00ZWNhLTk3MDktMTgyMDgxOWViMDg5YjM5M2M5NDhiMWJhNjcxMDQzNmUyMGFhYzljNDk5M2UyYzkzN2ZlOWY4YWYyZDBlZmZjYmQ2NGYzYmQ2ZjVmMg==, error: User session not found -05/07/2021 00:20:20: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -05/07/2021 00:22:20: prof: ERR: Message received without body for room: prosody@conference.prosody.im/tom -05/07/2021 00:30:46: prof: ERR: IQ error received, id: NjMxNjhkNjQtNDg1NC00NzYwLWJkMWYtNTQ5ZjM4NjczZWY4ZTM0ZmQ1NTQ5YTEyNjlhZjZkOWY2YWFlZjQ0MzMyZmVhYjUxYzI5ZjQwODgzZTA3ZDlhMjBiMDc1YzNiN2QxNQ==, error: Request has timed out -05/07/2021 00:30:46: prof: WRN: Error received for capabilities response from conversations@conference.siacs.eu/Natrinicle: -05/07/2021 00:35:22: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -05/07/2021 00:35:55: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -05/07/2021 00:36:18: prof: ERR: Message received without body for room: hmm@conference.hmm.st/chunk -05/07/2021 00:39:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 00:40:39: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -05/07/2021 00:40:41: prof: ERR: Message received without body for room: en@chat.404.city/qrpnxz -05/07/2021 00:41:11: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 00:47:25: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 00:51:30: prof: ERR: IQ error received, id: MWNhZTE4ZjUtZGYwNi00YzQ0LThlMjYtNDE3MmI0MDMxZTkzNTk1NzE0NmMxMWEyYmYzYTg1YWFiMDBiMGI4MjQ3MzUzNWI0ZmUzZTUyY2IxYjQ3ZmRmMWEzMDk3MjZkNDU1YQ==, error: User session not found -05/07/2021 00:51:30: prof: WRN: Error received for capabilities response from movim@conference.movim.eu/sander: -05/07/2021 00:54:45: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 00:59:00: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:06:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:06:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:06:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:06:50: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:06:52: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:06:56: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:07:05: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:07:13: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:07:21: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:07:35: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:07:47: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:07:53: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:08:01: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:08:08: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:08:38: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:08:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:08:58: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:10:18: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:11:14: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:11:23: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:11:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:11:33: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/qv -05/07/2021 01:11:39: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:11:49: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:13:43: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:13:54: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:14:19: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:14:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:16:12: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -05/07/2021 01:16:18: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -05/07/2021 01:16:20: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -05/07/2021 01:16:25: prof: ERR: Message received without body for room: en@chat.404.city/alex11 -05/07/2021 01:16:25: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 -05/07/2021 01:17:28: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 -05/07/2021 01:19:40: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:19:46: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:21:37: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:25:43: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 -05/07/2021 01:25:44: prof: ERR: Message received without body for room: conversations-offtopic-reloaded@conference.trashserver.net/allie -05/07/2021 01:26:46: prof: ERR: Message received without body for room: hmm@conference.hmm.st/alex11 diff --git a/result b/result deleted file mode 120000 index 28f4fce..0000000 --- a/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/0nlcxz4fp2zhpjm67wng1g05vv37xiwk-catt-0.12.1 \ No newline at end of file diff --git a/xmpp/iq.c b/xmpp/iq.c new file mode 100644 index 0000000..c31941d --- /dev/null +++ b/xmpp/iq.c @@ -0,0 +1,102 @@ +// 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 + +xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, char *ns, char *id, + char *from, char *to, char *type) +{ + xmpp_stanza_t *parent = base ? base : xmpp_iq_new(context, type, id); + xmpp_stanza_t **child = children; + + if (ns) + { + xmpp_stanza_set_ns(parent, ns); + free(ns); + } + + if (base && id) + { + xmpp_stanza_set_id(parent, id); + free(id); + } + + if (from) + { + xmpp_stanza_set_from(parent, from); + free(from); + } + + if (to) + { + xmpp_stanza_set_to(parent, to); + free(to); + } + + if (base && type) + { + xmpp_stanza_set_attribute(parent, "type", type); + free(type); + } + + while (*child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child); + + ++child; + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, char *ns) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "pubsub"); + } + + if (ns) + { + xmpp_stanza_set_ns(parent, ns); + free(ns); + } + + while (*child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child); + + ++child; + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base, char *node) +{ + xmpp_stanza_t *parent = base; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "items"); + } + + if (node) + { + xmpp_stanza_set_attribute(parent, "node", node); + free(node); + } + + return parent; +} diff --git a/xmpp/stanza.h b/xmpp/stanza.h index 7273024..56f3d8f 100644 --- a/xmpp/stanza.h +++ b/xmpp/stanza.h @@ -7,6 +7,15 @@ xmpp_stanza_t *stanza__presence(xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, const char *ns, - const char *from, const char *to, const char *type); + char *from, char *to, const char *type); + +xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, char *ns, char *id, + char *from, char *to, char *type); + +xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, char *ns); + +xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base, char *node); #endif /*WEECHAT_XMPP_STANZA_H*/ From 2190c0a07538ff012c7606515455ad83aab9b733 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 5 Jul 2021 22:59:54 +0100 Subject: [PATCH 100/118] oh my fucking god --- connection.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connection.c b/connection.c index dafaf5b..8e31a18 100644 --- a/connection.c +++ b/connection.c @@ -113,7 +113,8 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void { if (weechat_strcasecmp(role, "none") == 0) channel__remove_member(account, channel, from); - channel__add_member(account, channel, from); + else + channel__add_member(account, channel, from); } return 1; From ee16eaaa7acc75dcd7bc94304177cc018a062c4e Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 7 Jul 2021 18:27:06 +0100 Subject: [PATCH 101/118] fetch devicelist --- .envrc | 1 + Makefile | 9 +- README.org | 2 + account.c | 153 +++++++++++++----- account.h | 25 ++- buffer.c | 2 +- channel.c | 57 ++++++- channel.h | 11 ++ connection.c | 420 +++++++++++++++++++++++++++++++------------------- omemo.c | 53 ++++++- omemo.h | 28 +++- xmpp/iq.c | 139 ++++++++++++++++- xmpp/stanza.h | 61 +++++++- 13 files changed, 740 insertions(+), 221 deletions(-) diff --git a/.envrc b/.envrc index 1cb1c12..f61f48c 100644 --- a/.envrc +++ b/.envrc @@ -38,6 +38,7 @@ use_guix() make cmake gcc-toolchain pkg-config patchelf weechat libxml2 libstrophe glib libsignal-protocol-c sqlite + minixml ) # Thanks diff --git a/Makefile b/Makefile index 8023aa7..2f7b713 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ FIND=find INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags glib-2.0) $(shell pkg-config --cflags libsignal-protocol-c) CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) -LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs glib-2.0) $(shell pkg-config --libs libsignal-protocol-c) +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs glib-2.0) $(shell pkg-config --libs libsignal-protocol-c) -lmxml PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -27,7 +27,7 @@ SRCS=plugin.c \ xmpp/presence.c \ xmpp/iq.c \ -DEPS=axc/build/libaxc.a +DEPS=omemo/build/libomemo-conversations.a axc/build/libaxc.a OBJS=$(subst .c,.o,$(SRCS)) all: weechat-xmpp @@ -39,6 +39,10 @@ xmpp.so: $(OBJS) $(DEPS) patchelf --set-rpath $(LIBRARY_PATH):$(shell realpath $(shell dirname $(shell gcc --print-libgcc-file-name))/../../../) xmpp.so && \ patchelf --shrink-rpath xmpp.so || true +omemo/build/libomemo-conversations.a: + $(MAKE) -C omemo +omemo: omemo/build/libomemo-conversations.a + axc/build/libaxc.a: $(MAKE) -C axc axc: axc/build/libaxc.a @@ -62,6 +66,7 @@ tidy: clean: $(RM) -f $(OBJS) + $(MAKE) -C omemo clean || true $(MAKE) -C axc clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true diff --git a/README.org b/README.org index 8d1fc0b..a6770c9 100644 --- a/README.org +++ b/README.org @@ -122,10 +122,12 @@ * [ ] [#A] Send typing notifications * [ ] [#A] Recv typing notifications * [ ] [#C] Read receipts + * [ ] Message Carbons * [ ] Service Disco * [ ] Bookmarks / Roster * [ ] OTR (libotr) * [ ] PGP (libgpgme) + * [ ] Room Explorer (https://search.jabber.network/docs/api) ** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) * [ ] Absorb libomemo / axc, and drop glib diff --git a/account.c b/account.c index daf0e3d..9186b61 100644 --- a/account.c +++ b/account.c @@ -13,6 +13,7 @@ #include "plugin.h" #include "config.h" #include "input.h" +#include "omemo.h" #include "account.h" #include "connection.h" #include "user.h" @@ -86,6 +87,81 @@ int account__search_option(const char *option_name) return -1; } +struct t_device *account__search_device(struct t_account *account, int id) +{ + struct t_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_device *device) +{ + struct t_device *new_device; + + new_device = account__search_device(account, device->id); + if (!new_device) + { + new_device = malloc(sizeof(*new_device)); + new_device->id = device->id; + new_device->name = strdup(device->name); + + 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_device *device) +{ + struct t_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->name) + free(device->name); + + free(device); + + account->devices = new_devices; +} + +void account__free_device_all(struct t_account *account) +{ + while (account->devices) + account__free_device(account, account->devices); +} + void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg) { @@ -204,6 +280,10 @@ struct t_account *account__alloc(const char *name) new_account->is_connected = 0; new_account->disconnected = 0; + new_account->current_retry = 0; + new_account->reconnect_delay = 0; + new_account->reconnect_start = 0; + new_account->logger.handler = &account__log_emit_weechat; new_account->logger.userdata = new_account; new_account->context = xmpp_ctx_new(NULL, &new_account->logger); @@ -211,6 +291,11 @@ struct t_account *account__alloc(const char *name) new_account->buffer = NULL; new_account->buffer_as_string = NULL; + + new_account->omemo = NULL; + + new_account->devices = NULL; + new_account->last_device = NULL; new_account->users = NULL; new_account->last_user = NULL; new_account->channels = NULL; @@ -300,6 +385,9 @@ void account__free_data(struct t_account *account) if (account->buffer_as_string) free(account->buffer_as_string); + if (account->omemo) + omemo__free(account->omemo); + //channel__free_all(account); //user__free_all(account); } @@ -384,58 +472,34 @@ void account__disconnect(struct t_account *account, int reconnect) weechat_prefix ("network"), WEECHAT_XMPP_PLUGIN_NAME); } - /* - account->current_retry = 0; - - if (switch_address) - account__switch_address(account, 0); - else - account__set_index_current_address(account, 0); - - if (account->nick_modes) + if (reconnect) { - free (account->nick_modes); - account->nick_modes = NULL; - weechat_bar_item_update ("input_prompt"); - weechat_bar_item_update ("xmpp_nick_modes"); + if (account->current_retry++ == 0) + { + account->reconnect_delay = 5; + account->reconnect_start = time(NULL) + account->reconnect_delay; + } + account->current_retry %= 5; } - account->cap_away_notify = 0; - account->cap_account_notify = 0; - account->cap_extended_join = 0; - account->is_away = 0; - account->away_time = 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) + - weechat_config_integer (xmpp_config_network_lag_check); - account->lag_last_refresh = 0; - account__set_lag (account); - account->monitor = 0; - account->monitor_time = 0; - */ - - /* - if (reconnect - && IRC_SERVER_OPTION_BOOLEAN(account, IRC_SERVER_OPTION_AUTORECONNECT)) - account__reconnect_schedule(account); else { + account->current_retry = 0; account->reconnect_delay = 0; account->reconnect_start = 0; } - */ - - /* discard current nick if no reconnection asked */ - /* - if (!reconnect && account->nick) - account__set_nick(account, NULL); - account__set_buffer_title(account); + /* + 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) + + weechat_config_integer(xmpp_config_network_lag_check); + account->lag_last_refresh = 0; + account__set_lag(account); + */ // lag based on xmpp ping account->disconnected = 1; - */ /* send signal "account_disconnected" with account name */ (void) weechat_hook_signal_send("xmpp_account_disconnected", @@ -536,6 +600,11 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls) && (xmpp_conn_is_connecting(ptr_account->connection) || xmpp_conn_is_connected(ptr_account->connection))) connection__process(ptr_account->context, ptr_account->connection, 10); + else if (ptr_account->reconnect_start > 0 + && ptr_account->reconnect_start < time(NULL)) + { + account__connect(ptr_account); + } } return WEECHAT_RC_OK; diff --git a/account.h b/account.h index dd196be..7f1015b 100644 --- a/account.h +++ b/account.h @@ -58,6 +58,15 @@ enum t_account_option #define account_autojoin(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_AUTOJOIN]) +struct t_device +{ + int id; + char *name; + + struct t_device *prev_device; + struct t_device *next_device; +}; + struct t_account { char *name; @@ -68,18 +77,26 @@ struct t_account int is_connected; int disconnected; + int current_retry; + int reconnect_delay; + int reconnect_start; + xmpp_log_t logger; xmpp_ctx_t *context; xmpp_conn_t *connection; struct t_gui_buffer *buffer; char *buffer_as_string; - //struct t_device *devices; - //struct t_device *last_device; + + struct t_omemo *omemo; + + struct t_device *devices; + struct t_device *last_device; 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; }; @@ -89,6 +106,10 @@ 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_device *account__search_device(struct t_account *account, int id); +void account__add_device(struct t_account *account, struct t_device *device); +void account__free_device(struct t_account *account, struct t_device *device); +void account__free_device_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); diff --git a/buffer.c b/buffer.c index 11ed14d..25fa3f6 100644 --- a/buffer.c +++ b/buffer.c @@ -2,8 +2,8 @@ // 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 "plugin.h" diff --git a/channel.c b/channel.c index 5803a7e..8c7f51e 100644 --- a/channel.c +++ b/channel.c @@ -10,6 +10,7 @@ #include #include "plugin.h" +#include "omemo.h" #include "account.h" #include "user.h" #include "channel.h" @@ -489,6 +490,10 @@ void channel__member_free(struct t_channel *channel, /* free member data */ if (member->id) free(member->id); + if (member->role) + free(member->role); + if (member->affiliation) + free(member->affiliation); free(member); @@ -589,6 +594,9 @@ struct t_channel_member *channel__add_member(struct t_account *account, member = malloc(sizeof(struct t_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) @@ -607,12 +615,13 @@ struct t_channel_member *channel__add_member(struct t_account *account, && channel->type == CHANNEL_TYPE_MUC) weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s entered", weechat_prefix("join"), - jid_resource); + user__as_prefix_raw(account, jid_resource)); else weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) entered", weechat_prefix("join"), xmpp_jid_bare(account->context, user->id), - xmpp_jid_resource(account->context, user->id)); + user__as_prefix_raw(account, + xmpp_jid_resource(account->context, user->id))); return member; } @@ -635,6 +644,46 @@ struct t_channel_member *channel__member_search(struct t_channel *channel, return NULL; } +int channel__set_member_role(struct t_account *account, + struct t_channel *channel, + const char *id, const char *role) +{ + struct t_channel_member *member; + struct t_user *user; + + user = user__search(account, id); + if (!user) + return 0; + + member = channel__member_search(channel, id); + if (!member) + return 0; + + member->role = strdup(role); + + return 1; +} + +int channel__set_member_affiliation(struct t_account *account, + struct t_channel *channel, + const char *id, const char *affiliation) +{ + struct t_channel_member *member; + struct t_user *user; + + user = user__search(account, id); + if (!user) + return 0; + + member = channel__member_search(channel, id); + if (!member) + return 0; + + member->affiliation = strdup(affiliation); + + return 1; +} + struct t_channel_member *channel__remove_member(struct t_account *account, struct t_channel *channel, const char *id) @@ -643,8 +692,8 @@ struct t_channel_member *channel__remove_member(struct t_account *account, struct t_user *user; user = user__search(account, id); - if (user) - user__nicklist_remove(account, channel, user); + //if (user) + // user__nicklist_remove(account, channel, user); member = channel__member_search(channel, id); if (member) diff --git a/channel.h b/channel.h index ed9ca23..3c2924d 100644 --- a/channel.h +++ b/channel.h @@ -27,6 +27,9 @@ struct t_channel_member { char *id; + char *role; + char *affiliation; + struct t_channel_member *prev_member; struct t_channel_member *next_member; }; @@ -120,6 +123,14 @@ struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel *channel, const char *id); +int channel__set_member_role(struct t_account *account, + struct t_channel *channel, + const char *id, const char *role); + +int channel__set_member_affiliation(struct t_account *account, + struct t_channel *channel, + const char *id, const char *affiliation); + struct t_channel_member *channel__remove_member(struct t_account *account, struct t_channel *channel, const char *id); diff --git a/connection.c b/connection.c index 8e31a18..a433ce0 100644 --- a/connection.c +++ b/connection.c @@ -111,6 +111,8 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void } else if (channel) { + channel__set_member_role(account, channel, from, role); + channel__set_member_affiliation(account, channel, from, affiliation); if (weechat_strcasecmp(role, "none") == 0) channel__remove_member(account, channel, from); else @@ -127,7 +129,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * struct t_account *account = (struct t_account *)userdata; struct t_channel *channel; xmpp_stanza_t *body, *delay, *topic, *replace; - const char *type, *from, *from_bare, *to, *id, *replace_id, *timestamp; + const char *type, *from, *nick, *from_bare, *to, *id, *replace_id, *timestamp; char *intext; struct tm time = {0}; time_t date = 0; @@ -170,9 +172,10 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + nick = NULL; if (weechat_strcasecmp(type, "groupchat") == 0) { - from = weechat_strcasecmp(channel->name, + nick = weechat_strcasecmp(channel->name, xmpp_jid_bare(account->context, from)) == 0 ? xmpp_jid_resource(account->context, from) @@ -188,6 +191,14 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * char **dyn_tags = weechat_string_dyn_alloc(1); weechat_string_dyn_concat(dyn_tags, "xmpp_message,message", -1); + { + weechat_string_dyn_concat(dyn_tags, ",nick_", -1); + weechat_string_dyn_concat(dyn_tags, nick, -1); + } + { + weechat_string_dyn_concat(dyn_tags, ",host_", -1); + weechat_string_dyn_concat(dyn_tags, from, -1); + } if (id) { weechat_string_dyn_concat(dyn_tags, ",id_", -1); @@ -213,15 +224,15 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly if (strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s[to %s]: %s", - edit, user__as_prefix_raw(account, from), + edit, user__as_prefix_raw(account, nick), to, intext ? intext : ""); else if (weechat_string_match(intext, "/me *", 0)) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s %s", - edit, weechat_prefix("action"), from, + edit, weechat_prefix("action"), nick, intext ? intext+4 : ""); else weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s", - edit, user__as_prefix_raw(account, from), + edit, user__as_prefix_raw(account, nick), intext ? intext : ""); weechat_string_dyn_free(dyn_tags, 1); @@ -238,196 +249,276 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd struct t_account *account = (struct t_account *)userdata; xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; - const char *node; + xmpp_stanza_t *pubsub, *items, *item, *list, *device, *children[2]; static struct utsname osinfo; - char *client_name = weechat_string_eval_expression("weechat ${info:version}", - NULL, NULL, NULL); - - reply = xmpp_stanza_reply(stanza); - xmpp_stanza_set_type(reply, "result"); - query = xmpp_stanza_get_child_by_name_and_ns( stanza, "query", "http://jabber.org/protocol/disco#info"); - node = xmpp_stanza_get_attribute(query, "node"); - xmpp_stanza_set_attribute(reply, "id", node); - - 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); - xmpp_stanza_set_attribute(identity, "type", "pc"); - xmpp_stanza_add_child(query, identity); - xmpp_stanza_release(identity); - -#define FEATURE(ns) \ - 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); \ - xmpp_stanza_release(feature); - - FEATURE("http://jabber.org/protocol/caps"); - FEATURE("http://jabber.org/protocol/disco#info"); - FEATURE("http://jabber.org/protocol/disco#items"); - FEATURE("http://jabber.org/protocol/muc"); - FEATURE("eu.siacs.conversations.axolotl.devicelist"); - FEATURE("eu.siacs.conversations.axolotl.devicelist+notify"); + if (query) + { + char *client_name; + + reply = xmpp_stanza_reply(stanza); + xmpp_stanza_set_type(reply, "result"); + + client_name = weechat_string_eval_expression("weechat ${info:version}", + NULL, NULL, NULL); + + 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); + xmpp_stanza_set_attribute(identity, "type", "pc"); + xmpp_stanza_add_child(query, identity); + xmpp_stanza_release(identity); + +#define FEATURE(ns) \ + 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); \ + xmpp_stanza_release(feature); + + FEATURE("http://jabber.org/protocol/caps"); + FEATURE("http://jabber.org/protocol/disco#info"); + FEATURE("http://jabber.org/protocol/disco#items"); + FEATURE("http://jabber.org/protocol/muc"); + FEATURE("eu.siacs.conversations.axolotl.devicelist"); + FEATURE("eu.siacs.conversations.axolotl.devicelist+notify"); + FEATURE("storage:bookmarks+notify"); #undef FEATURE - 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"); + 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"); - if (uname(&osinfo) < 0) - { - *osinfo.sysname = 0; - *osinfo.release = 0; - } + if (uname(&osinfo) < 0) + { + *osinfo.sysname = 0; + *osinfo.release = 0; + } + + // This is utter bullshit, TODO: not this. + { + 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"); - { - 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); + xmpp_stanza_set_name(value, "value"); - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "urn:xmpp:dataforms:softwareinfo"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, "urn:xmpp:dataforms:softwareinfo"); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "ip_version"); + xmpp_stanza_set_attribute(field, "type", "text-multi"); + + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); - } + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "ipv4"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); - { - field = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(field, "field"); - xmpp_stanza_set_attribute(field, "var", "ip_version"); - xmpp_stanza_set_attribute(field, "type", "text-multi"); + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "ipv6"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, "ipv4"); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "os"); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, "ipv6"); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, osinfo.sysname); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); - } + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); - { - field = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(field, "field"); - xmpp_stanza_set_attribute(field, "var", "os"); + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "os_version"); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, osinfo.sysname); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, osinfo.release); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); - } + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); - { - field = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(field, "field"); - xmpp_stanza_set_attribute(field, "var", "os_version"); + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "software"); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, osinfo.release); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, "weechat"); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); - } + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); - { - field = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(field, "field"); - xmpp_stanza_set_attribute(field, "var", "software"); + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + { + field = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(field, "field"); + xmpp_stanza_set_attribute(field, "var", "software_version"); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, "weechat"); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + value = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(value, "value"); - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, weechat_info_get("version", NULL)); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); - } + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); - { - field = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(field, "field"); - xmpp_stanza_set_attribute(field, "var", "software_version"); + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } - value = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(value, "value"); + xmpp_stanza_add_child(query, x); + xmpp_stanza_release(x); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, weechat_info_get("version", NULL)); - xmpp_stanza_add_child(value, text); - xmpp_stanza_release(text); + xmpp_stanza_add_child(reply, query); - xmpp_stanza_add_child(field, value); - xmpp_stanza_release(value); + xmpp_send(conn, reply); + xmpp_stanza_release(reply); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); + free(client_name); } - xmpp_stanza_add_child(query, x); - xmpp_stanza_release(x); - - xmpp_stanza_add_child(reply, query); - - xmpp_send(conn, reply); - xmpp_stanza_release(reply); - - free(client_name); + pubsub = xmpp_stanza_get_child_by_name_and_ns( + stanza, "pubsub", "http://jabber.org/protocol/pubsub"); + if (pubsub) + { + const char *items_node, *item_id, *device_id, *ns, *node; + + items = xmpp_stanza_get_child_by_name(pubsub, "items"); + if (items) + items_node = xmpp_stanza_get_attribute(items, "node"); + if (items && items_node + && weechat_strcasecmp(items_node, + "eu.siacs.conversations.axolotl.devicelist") == 0) + { + item = xmpp_stanza_get_child_by_name(items, "item"); + if (item) + item_id = xmpp_stanza_get_id(item); + if (item && item_id && weechat_strcasecmp(item_id, "current") == 0) + { + list = xmpp_stanza_get_child_by_name_and_ns( + item, "list", "eu.siacs.conversations.axolotl"); + if (list) + { + account__free_device_all(account); + + struct t_device *dev = malloc(sizeof(dev)); + char id[64] = {0}; + + dev->id = account->omemo->device_id; + snprintf(id, sizeof(id), "%d", dev->id); + dev->name = strdup(id); + account__add_device(account, dev); + + free(dev->name); + free(dev); + + for (device = xmpp_stanza_get_children(list); + device; device = xmpp_stanza_get_next(device)) + { + device_id = xmpp_stanza_get_id(device); + + dev = malloc(sizeof(dev)); + dev->id = atoi(device_id); + dev->name = strdup(device_id); + account__add_device(account, dev); + + free(dev->name); + free(dev); + } + + reply = xmpp_stanza_reply(stanza); + xmpp_stanza_set_type(reply, "result"); + + children[1] = NULL; + children[0] = stanza__iq_pubsub_publish_item_list_device( + account->context, NULL, with_noop(id)); + ns = "http://jabber.org/protocol/pubsub"; + children[0] = stanza__iq_pubsub_publish_item_list( + account->context, NULL, children, with_noop(ns)); + node = "eu.siacs.conversations.axolotl.devicelist"; + children[0] = stanza__iq_pubsub_publish_item( + account->context, NULL, children, with_noop(node)); + children[0] = stanza__iq_pubsub_publish(account->context, + NULL, children, + with_noop(ns)); + children[0] = stanza__iq_pubsub(account->context, NULL, + children, with_noop("")); + reply = stanza__iq(account->context, reply, children, NULL, + NULL, NULL, NULL, NULL); + + xmpp_send(conn, reply); + xmpp_stanza_release(reply); + } + } + } + } return 1; } @@ -441,18 +532,21 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, (void)error; (void)stream_error; - if (status == XMPP_CONN_CONNECT) { + if (status == XMPP_CONN_CONNECT) + { xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, **children; char cap_hash[28+1] = {0}; - xmpp_handler_add(conn, connection__version_handler, + xmpp_handler_add(conn, &connection__version_handler, "jabber:iq:version", "iq", NULL, account); - xmpp_handler_add(conn, connection__presence_handler, + xmpp_handler_add(conn, &connection__presence_handler, NULL, "presence", NULL, account); - xmpp_handler_add(conn, connection__message_handler, + xmpp_handler_add(conn, &connection__message_handler, NULL, "message", /*type*/ NULL, account); - xmpp_handler_add(conn, connection__iq_handler, - NULL, "iq", "get", account); + //xmpp_handler_add(conn, &connection__iq_handler, + // NULL, "iq", "get", account); + xmpp_handler_add(conn, &connection__iq_handler, + NULL, "iq", NULL, account); /* Send initial so that we appear online to contacts */ children = malloc(sizeof(*children) * (2 + 1)); @@ -495,7 +589,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, strdup("eu.siacs.conversations.axolotl.devicelist")); children[0] = stanza__iq_pubsub(account->context, NULL, children, - strdup("http://jabber.org/protocol/pubsub")); + with_noop("http://jabber.org/protocol/pubsub")); children[0] = stanza__iq(account->context, NULL, children, NULL, strdup("fetch1"), strdup(account_jid(account)), strdup(account_jid(account)), @@ -504,8 +598,10 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, children[0]); xmpp_stanza_release(children[0]); - omemo__init(account); - } else { + omemo__init(&account->omemo, 0, NULL); + } + else + { account__disconnect(account, 1); //xmpp_stop(account->context); //keep context? } diff --git a/omemo.c b/omemo.c index affb2b0..6ce67d7 100644 --- a/omemo.c +++ b/omemo.c @@ -4,13 +4,58 @@ #include -#include "omemo/src/libomemo.h" -#include "axc/src/axc.h" - #include "omemo.h" -void omemo__init() +void omemo__init(struct t_omemo **omemo, uint32_t device, + struct t_identity *identity) { const char* ns_devicelist = "eu.siacs.conversations.axolotl.devicelist"; const char* ft_devicelist = "eu.siacs.conversations.axolotl.devicelist+notify"; + int rc; + + srandom(time(NULL)); + + omemo_bundle* bundle; + rc = omemo_bundle_create(&bundle); + if (rc) + return; + + if (!device) + device = random(); + omemo_bundle_set_device_id(bundle, device); + + if (identity) + omemo_bundle_set_identity_key(bundle, identity->key, identity->length); + else + { + identity = malloc(sizeof(*identity)); + identity->length = 4; + identity->key = malloc(sizeof(*identity->key) * identity->length); + + identity->key[0] = random(); + identity->key[1] = random(); + identity->key[2] = random(); + identity->key[3] = random(); + + omemo_bundle_set_identity_key(bundle, identity->key, identity->length); + + free(identity->key); + free(identity); + } + + *omemo = malloc(sizeof(**omemo)); + (*omemo)->provider.random_bytes_func = omemo_default_crypto_random_bytes; + (*omemo)->provider.aes_gcm_encrypt_func = omemo_default_crypto_aes_gcm_encrypt; + (*omemo)->provider.aes_gcm_decrypt_func = omemo_default_crypto_aes_gcm_decrypt; + (*omemo)->provider.user_data_p = (void *)(*omemo); + (*omemo)->bundle = bundle; + (*omemo)->device_id = omemo_bundle_get_device_id(bundle); + omemo_bundle_get_identity_key(bundle, &(*omemo)->identity.key, &(*omemo)->identity.length); + + omemo_devicelist *devicelist; +} + +void omemo__free(struct t_omemo *omemo) +{ + free(omemo); } diff --git a/omemo.h b/omemo.h index 7fb146c..faccd8e 100644 --- a/omemo.h +++ b/omemo.h @@ -5,6 +5,32 @@ #ifndef _WEECHAT_XMPP_OMEMO_H_ #define _WEECHAT_XMPP_OMEMO_H_ -void omemo__init(); +#include "axc/src/axc.h" +#include "omemo/src/libomemo.h" +#include "omemo/src/libomemo_crypto.h" + +struct t_identity +{ + uint8_t *key; + size_t length; +}; + +struct t_omemo +{ + omemo_crypto_provider provider; + + omemo_devicelist *devicelist; + + omemo_bundle *bundle; + + struct t_identity identity; + + uint32_t device_id; +}; + +void omemo__init(struct t_omemo **omemo, uint32_t device, + struct t_identity *identity); + +void omemo__free(struct t_omemo *omemo); #endif /*WEECHAT_XMPP_OMEMO_H*/ diff --git a/xmpp/iq.c b/xmpp/iq.c index c31941d..c5c8277 100644 --- a/xmpp/iq.c +++ b/xmpp/iq.c @@ -5,6 +5,8 @@ #include #include +#include "stanza.h" + xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, char *ns, char *id, char *from, char *to, char *type) @@ -54,7 +56,7 @@ xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base, } xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base, - xmpp_stanza_t **children, char *ns) + xmpp_stanza_t **children, struct t_string *ns) { xmpp_stanza_t *parent = base; xmpp_stanza_t **child = children; @@ -67,7 +69,8 @@ xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base, if (ns) { - xmpp_stanza_set_ns(parent, ns); + xmpp_stanza_set_ns(parent, ns->value); + ns->finalize(ns); free(ns); } @@ -100,3 +103,135 @@ xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base, return parent; } + +xmpp_stanza_t *stanza__iq_pubsub_publish(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *node) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "publish"); + } + + if (node) + { + xmpp_stanza_set_attribute(parent, "node", node->value); + node->finalize(node); + free(node); + } + + while (*child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child); + + ++child; + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *id) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "item"); + } + + if (id) + { + xmpp_stanza_set_id(parent, id->value); + id->finalize(id); + free(id); + } + + while (*child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child); + + ++child; + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *ns) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "list"); + } + + if (ns) + { + xmpp_stanza_set_ns(parent, ns->value); + ns->finalize(ns); + free(ns); + } + + while (*child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child); + + ++child; + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *id) +{ + xmpp_stanza_t *parent = base; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "device"); + } + + if (id) + { + xmpp_stanza_set_id(parent, id->value); + id->finalize(id); + free(id); + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *ns) +{ + xmpp_stanza_t *parent = base; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "ping"); + } + + if (ns) + { + xmpp_stanza_set_ns(parent, ns->value); + ns->finalize(ns); + free(ns); + } + + return parent; +} diff --git a/xmpp/stanza.h b/xmpp/stanza.h index 56f3d8f..38aa459 100644 --- a/xmpp/stanza.h +++ b/xmpp/stanza.h @@ -5,6 +5,50 @@ #ifndef _WEECHAT_XMPP_STANZA_H_ #define _WEECHAT_XMPP_STANZA_H_ +struct t_string +{ + char *value; + + void (*finalize)(struct t_string *); + void *pointer; +}; + +static void t_string_noop(struct t_string *string) +{ (void)string; } + +static void t_string_free(struct t_string *string) +{ free(string->value); } + +static void t_string_xmpp_free(struct t_string *string) +{ xmpp_free(string->pointer, string->value); } + +static inline struct t_string *with_noop(const char *const value) +{ + struct t_string *string = malloc(sizeof(struct t_string)); + string->value = (char*)value; + string->finalize = &t_string_noop; + string->pointer = NULL; + return string; +} + +static inline struct t_string *with_free(char *value) +{ + struct t_string *string = malloc(sizeof(struct t_string)); + string->value = value; + string->finalize = &t_string_free; + string->pointer = NULL; + return string; +} + +static inline struct t_string *with_xmpp_free(char *value, xmpp_ctx_t *pointer) +{ + struct t_string *string = malloc(sizeof(struct t_string)); + string->value = value; + string->finalize = &t_string_xmpp_free; + string->pointer = pointer; + return string; +} + xmpp_stanza_t *stanza__presence(xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, const char *ns, char *from, char *to, const char *type); @@ -14,8 +58,23 @@ xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base, char *from, char *to, char *type); xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base, - xmpp_stanza_t **children, char *ns); + xmpp_stanza_t **children, struct t_string *ns); xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base, char *node); +xmpp_stanza_t *stanza__iq_pubsub_publish(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *node); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *id); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *ns); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *id); + +xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *ns); + #endif /*WEECHAT_XMPP_STANZA_H*/ From 0048ffde4c7296738afd9e59d278026a8c7b3835 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 7 Jul 2021 20:53:25 +0100 Subject: [PATCH 102/118] bookmarks --- command.c | 2 +- connection.c | 231 ++++++++++++++++++++++++++++++++++++--------------- user.c | 6 +- xmpp/iq.c | 4 +- 4 files changed, 170 insertions(+), 73 deletions(-) diff --git a/command.c b/command.c index ccd9fa8..85de4f5 100644 --- a/command.c +++ b/command.c @@ -592,7 +592,7 @@ int command__msg(const void *pointer, void *data, if (ptr_channel->type != CHANNEL_TYPE_MUC) weechat_printf_date_tags(ptr_channel->buffer, 0, "xmpp_message,message,private,notify_none,self_msg,log1", - "%s%s", + "%s\t%s", user__as_prefix_raw(ptr_account, account_jid(ptr_account)), text); } diff --git a/connection.c b/connection.c index a433ce0..b1d35a9 100644 --- a/connection.c +++ b/connection.c @@ -223,15 +223,15 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly if (strcmp(to, channel->id) == 0) - weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s[to %s]: %s", + weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", edit, user__as_prefix_raw(account, nick), to, intext ? intext : ""); else if (weechat_string_match(intext, "/me *", 0)) - weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s %s", + weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s %s", edit, weechat_prefix("action"), nick, intext ? intext+4 : ""); else - weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s", + weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s", edit, user__as_prefix_raw(account, nick), intext ? intext : ""); @@ -249,12 +249,14 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd struct t_account *account = (struct t_account *)userdata; xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; - xmpp_stanza_t *pubsub, *items, *item, *list, *device, *children[2]; + xmpp_stanza_t *pubsub, *items, *item, *list, *device, **children; + xmpp_stanza_t *storage, *conference, *nick; static struct utsname osinfo; query = xmpp_stanza_get_child_by_name_and_ns( stanza, "query", "http://jabber.org/protocol/disco#info"); - if (query) + const char *type = xmpp_stanza_get_attribute(stanza, "type"); + if (query && type && weechat_strcasecmp(type, "get") == 0) { char *client_name; @@ -279,13 +281,38 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd xmpp_stanza_add_child(query, feature); \ xmpp_stanza_release(feature); + FEATURE("eu.siacs.conversations.axolotl.devicelist+notify"); FEATURE("http://jabber.org/protocol/caps"); + FEATURE("http://jabber.org/protocol/chatstates"); FEATURE("http://jabber.org/protocol/disco#info"); FEATURE("http://jabber.org/protocol/disco#items"); FEATURE("http://jabber.org/protocol/muc"); - FEATURE("eu.siacs.conversations.axolotl.devicelist"); - FEATURE("eu.siacs.conversations.axolotl.devicelist+notify"); + FEATURE("http://jabber.org/protocol/nick+notify"); + FEATURE("jabber:iq:version"); + FEATURE("jabber:x:conference"); + FEATURE("jabber:x:oob"); FEATURE("storage:bookmarks+notify"); + FEATURE("urn:xmpp:avatar:metadata+notify"); + FEATURE("urn:xmpp:chat-markers:0"); + FEATURE("urn:xmpp:idle:1"); + //FEATURE("urn:xmpp:jingle-message:0"); + //FEATURE("urn:xmpp:jingle:1"); + //FEATURE("urn:xmpp:jingle:apps:dtls:0"); + //FEATURE("urn:xmpp:jingle:apps:file-transfer:3"); + //FEATURE("urn:xmpp:jingle:apps:file-transfer:4"); + //FEATURE("urn:xmpp:jingle:apps:file-transfer:5"); + //FEATURE("urn:xmpp:jingle:apps:rtp:1"); + //FEATURE("urn:xmpp:jingle:apps:rtp:audio"); + //FEATURE("urn:xmpp:jingle:apps:rtp:video"); + //FEATURE("urn:xmpp:jingle:jet-omemo:0"); + //FEATURE("urn:xmpp:jingle:jet:0"); + //FEATURE("urn:xmpp:jingle:transports:ibb:1"); + //FEATURE("urn:xmpp:jingle:transports:ice-udp:1"); + //FEATURE("urn:xmpp:jingle:transports:s5b:1"); + FEATURE("urn:xmpp:message-correct:0"); + FEATURE("urn:xmpp:ping"); + FEATURE("urn:xmpp:receipts"); + FEATURE("urn:xmpp:time"); #undef FEATURE x = xmpp_stanza_new(account->context); @@ -299,7 +326,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd *osinfo.release = 0; } - // This is utter bullshit, TODO: not this. + // This is utter bullshit, TODO: anything but this. { field = xmpp_stanza_new(account->context); xmpp_stanza_set_name(field, "field"); @@ -452,69 +479,132 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd items = xmpp_stanza_get_child_by_name(pubsub, "items"); if (items) - items_node = xmpp_stanza_get_attribute(items, "node"); - if (items && items_node - && weechat_strcasecmp(items_node, - "eu.siacs.conversations.axolotl.devicelist") == 0) { - item = xmpp_stanza_get_child_by_name(items, "item"); - if (item) - item_id = xmpp_stanza_get_id(item); - if (item && item_id && weechat_strcasecmp(item_id, "current") == 0) + items_node = xmpp_stanza_get_attribute(items, "node"); + if (items_node + && weechat_strcasecmp(items_node, + "eu.siacs.conversations.axolotl.devicelist") == 0) { - list = xmpp_stanza_get_child_by_name_and_ns( - item, "list", "eu.siacs.conversations.axolotl"); - if (list) + item = xmpp_stanza_get_child_by_name(items, "item"); + if (item) + item_id = xmpp_stanza_get_id(item); + if (item && item_id && weechat_strcasecmp(item_id, "current") == 0) { - account__free_device_all(account); - - struct t_device *dev = malloc(sizeof(dev)); - char id[64] = {0}; - - dev->id = account->omemo->device_id; - snprintf(id, sizeof(id), "%d", dev->id); - dev->name = strdup(id); - account__add_device(account, dev); - - free(dev->name); - free(dev); - - for (device = xmpp_stanza_get_children(list); - device; device = xmpp_stanza_get_next(device)) + list = xmpp_stanza_get_child_by_name_and_ns( + item, "list", "eu.siacs.conversations.axolotl"); + if (list) { - device_id = xmpp_stanza_get_id(device); + account__free_device_all(account); - dev = malloc(sizeof(dev)); - dev->id = atoi(device_id); - dev->name = strdup(device_id); + struct t_device *dev = malloc(sizeof(dev)); + char id[64] = {0}; + + dev->id = account->omemo->device_id; + snprintf(id, sizeof(id), "%d", dev->id); + dev->name = strdup(id); account__add_device(account, dev); + int i = 0; + children = malloc(sizeof(xmpp_stanza_t *) * 128); + children[i++] = stanza__iq_pubsub_publish_item_list_device( + account->context, NULL, with_noop(dev->name)); + free(dev->name); free(dev); - } - reply = xmpp_stanza_reply(stanza); - xmpp_stanza_set_type(reply, "result"); - - children[1] = NULL; - children[0] = stanza__iq_pubsub_publish_item_list_device( - account->context, NULL, with_noop(id)); - ns = "http://jabber.org/protocol/pubsub"; - children[0] = stanza__iq_pubsub_publish_item_list( - account->context, NULL, children, with_noop(ns)); - node = "eu.siacs.conversations.axolotl.devicelist"; - children[0] = stanza__iq_pubsub_publish_item( - account->context, NULL, children, with_noop(node)); - children[0] = stanza__iq_pubsub_publish(account->context, - NULL, children, - with_noop(ns)); - children[0] = stanza__iq_pubsub(account->context, NULL, - children, with_noop("")); - reply = stanza__iq(account->context, reply, children, NULL, - NULL, NULL, NULL, NULL); - - xmpp_send(conn, reply); - xmpp_stanza_release(reply); + for (device = xmpp_stanza_get_children(list); + device; device = xmpp_stanza_get_next(device)) + { + const char *name = xmpp_stanza_get_name(device); + if (weechat_strcasecmp(name, "device") != 0) + continue; + + device_id = xmpp_stanza_get_id(device); + + dev = malloc(sizeof(dev)); + dev->id = atoi(device_id); + dev->name = strdup(device_id); + account__add_device(account, dev); + + children[i++] = stanza__iq_pubsub_publish_item_list_device( + account->context, NULL, with_noop(dev->name)); + + free(dev->name); + free(dev); + } + + children[i] = NULL; + ns = "eu.siacs.conversations.axolotl"; + children[0] = stanza__iq_pubsub_publish_item_list( + account->context, NULL, children, with_noop(ns)); + children[1] = NULL; + children[0] = stanza__iq_pubsub_publish_item( + account->context, NULL, children, with_noop("current")); + node = "http://jabber.org/protocol/pubsub"; + children[0] = stanza__iq_pubsub_publish(account->context, + NULL, children, + with_noop(node)); + children[0] = stanza__iq_pubsub(account->context, NULL, + children, with_noop("")); + reply = stanza__iq(account->context, xmpp_stanza_reply(stanza), + children, NULL, strdup("announce1"), + NULL, NULL, strdup("set")); + + free(children); + + xmpp_send(conn, reply); + xmpp_stanza_release(reply); + } + } + } + if (items_node + && weechat_strcasecmp(items_node, "storage:bookmarks") == 0) + { + item = xmpp_stanza_get_child_by_name(items, "item"); + if (item) + item_id = xmpp_stanza_get_id(item); + if (item && item_id && weechat_strcasecmp(item_id, "current") == 0) + { + storage = xmpp_stanza_get_child_by_name_and_ns( + item, "storage", "storage:bookmarks"); + if (storage) + { + for (conference = xmpp_stanza_get_children(storage); + conference; conference = xmpp_stanza_get_next(conference)) + { + const char *name = xmpp_stanza_get_name(conference); + if (weechat_strcasecmp(name, "conference") != 0) + continue; + + const char *jid = xmpp_stanza_get_attribute(conference, "jid"); + const char *autojoin = xmpp_stanza_get_attribute(conference, "autojoin"); + name = xmpp_stanza_get_attribute(conference, "name"); + nick = xmpp_stanza_get_child_by_name(conference, "nick"); + char *intext; + if (nick) + { + text = xmpp_stanza_get_children(nick); + intext = xmpp_stanza_get_text(text); + } + + if (weechat_strcasecmp(autojoin, "true") == 0) + { + char **command = weechat_string_dyn_alloc(256); + weechat_string_dyn_concat(command, "/enter ", -1); + weechat_string_dyn_concat(command, jid, -1); + if (nick) + { + weechat_string_dyn_concat(command, "/", -1); + weechat_string_dyn_concat(command, intext, -1); + } + weechat_command(account->buffer, *command); + weechat_string_dyn_free(command, 1); + } + + if (nick) + free(intext); + } + } } } } @@ -577,11 +667,20 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, pres); xmpp_stanza_release(pres); - char **command = weechat_string_dyn_alloc(256); - weechat_string_dyn_concat(command, "/enter ", -1); - weechat_string_dyn_concat(command, account_autojoin(account), -1); - weechat_command(account->buffer, *command); - weechat_string_dyn_free(command, 1); + children[1] = NULL; + children[0] = + stanza__iq_pubsub_items(account->context, NULL, + strdup("storage:bookmarks")); + 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, strdup("retrieve1"), + strdup(account_jid(account)), strdup(account_jid(account)), + strdup("get")); + + xmpp_send(conn, children[0]); + xmpp_stanza_release(children[0]); children[1] = NULL; children[0] = diff --git a/user.c b/user.c index 4a9a654..a219707 100644 --- a/user.c +++ b/user.c @@ -30,9 +30,9 @@ const char *user__as_prefix_raw(struct t_account *account, (void) account; - snprintf(result, sizeof(result), "%s%s\t", + snprintf(result, sizeof(result), "%s%s%s", weechat_info_get("nick_color", name), - name); + name, weechat_color("reset")); return result; } @@ -131,7 +131,7 @@ void user__nicklist_remove(struct t_account *account, ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, user->is_away ? "+" : "..."); - weechat_nicklist_remove_nick(ptr_buffer, + weechat_nicklist_remove_nick(ptr_buffer, weechat_nicklist_search_nick(ptr_buffer, ptr_group, name)); } diff --git a/xmpp/iq.c b/xmpp/iq.c index c5c8277..1c51698 100644 --- a/xmpp/iq.c +++ b/xmpp/iq.c @@ -186,9 +186,7 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_sta while (*child) { xmpp_stanza_add_child(parent, *child); - xmpp_stanza_release(*child); - - ++child; + xmpp_stanza_release(*child++); } return parent; From dc00c41b4f29f884497ddd2a4145b6e700b6bcdc Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 7 Jul 2021 21:49:12 +0100 Subject: [PATCH 103/118] remove hacky autojoin option --- account.c | 1 - account.h | 3 --- channel.c | 22 +++++++++++++--------- config.c | 16 ---------------- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/account.c b/account.c index 9186b61..4943e83 100644 --- a/account.c +++ b/account.c @@ -31,7 +31,6 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "autoconnect", "" }, { "resource", "" }, { "status", "probably about to segfault" }, - { "autojoin", "" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index 7f1015b..342da5d 100644 --- a/account.h +++ b/account.h @@ -17,7 +17,6 @@ enum t_account_option ACCOUNT_OPTION_AUTOCONNECT, ACCOUNT_OPTION_RESOURCE, ACCOUNT_OPTION_STATUS, - ACCOUNT_OPTION_AUTOJOIN, ACCOUNT_NUM_OPTIONS, }; @@ -55,8 +54,6 @@ enum t_account_option weechat_config_string(account->options[ACCOUNT_OPTION_RESOURCE]) #define account_status(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_STATUS]) -#define account_autojoin(account) \ - weechat_config_string(account->options[ACCOUNT_OPTION_AUTOJOIN]) struct t_device { diff --git a/channel.c b/channel.c index 8c7f51e..6205ed9 100644 --- a/channel.c +++ b/channel.c @@ -613,15 +613,17 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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 entered", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s entered %s", weechat_prefix("join"), - user__as_prefix_raw(account, jid_resource)); + user__as_prefix_raw(account, jid_resource), + channel->id); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) entered", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) entered %s", weechat_prefix("join"), xmpp_jid_bare(account->context, user->id), user__as_prefix_raw(account, - xmpp_jid_resource(account->context, user->id))); + xmpp_jid_resource(account->context, user->id)), + channel->id); return member; } @@ -703,14 +705,16 @@ struct t_channel_member *channel__remove_member(struct t_account *account, 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 left", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s left %s", weechat_prefix("quit"), - jid_resource); + jid_resource, + channel->id); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) left", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) left %s", weechat_prefix("quit"), xmpp_jid_bare(account->context, user->id), - xmpp_jid_resource(account->context, user->id)); + xmpp_jid_resource(account->context, user->id), + channel->id); return member; } @@ -749,7 +753,7 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_send(account->connection, message); xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) - weechat_printf(channel->buffer, "%s%s", + weechat_printf(channel->buffer, "%s\t%s", user__as_prefix_raw(account, account_jid(account)), body); } diff --git a/config.c b/config.c index 8718d03..b7e6c66 100644 --- a/config.c +++ b/config.c @@ -186,22 +186,6 @@ config__account_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; - case ACCOUNT_OPTION_AUTOJOIN: - new_option = weechat_config_new_option ( - config_file, section, - option_name, "string", - N_("XMPP MUC Autojoins"), - 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; } From dba306a01e2c3e71c3e3be6cbad6b52a1e5df482 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Wed, 7 Jul 2021 22:34:31 +0100 Subject: [PATCH 104/118] style~~~ --- channel.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/channel.c b/channel.c index 6205ed9..8d8aa0d 100644 --- a/channel.c +++ b/channel.c @@ -613,16 +613,20 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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 entered %s", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s %sentered%s %s", weechat_prefix("join"), user__as_prefix_raw(account, jid_resource), + weechat_color("irc.color.message_join"), + weechat_color("reset"), channel->id); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) entered %s", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %sentered%s %s", weechat_prefix("join"), - xmpp_jid_bare(account->context, user->id), user__as_prefix_raw(account, - 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_join"), + weechat_color("reset"), channel->id); return member; @@ -705,15 +709,19 @@ struct t_channel_member *channel__remove_member(struct t_account *account, 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 left %s", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s %sleft%s %s", weechat_prefix("quit"), jid_resource, + weechat_color("irc.color.message_quit"), + weechat_color("reset"), channel->id); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) left %s", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) %sleft%s %s", weechat_prefix("quit"), 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); return member; From 55626cd08ff046d1e04b5ccd5ed0858ea49052fc Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 8 Jul 2021 04:19:49 +0100 Subject: [PATCH 105/118] change muc --- README.org | 6 ++++-- connection.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- omemo.c | 2 -- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/README.org b/README.org index a6770c9..37728fd 100644 --- a/README.org +++ b/README.org @@ -16,7 +16,7 @@ [[https://github.com/bqv/weechat-xmpp/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-xmpp.svg]] [[https://github.com/bqv/weechat-xmpp/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-xmpp.svg]] [[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-xmpp-blue.svg]] -[[https://github.com/bqv/weechat-extras/][file:https://inverse.chat/badge.svg?room=weechat@conference.hmm.st]] +[[https://github.com/bqv/weechat-extras/][file:https://inverse.chat/badge.svg?room=weechat@muc.xa0.uk]] | Status: | XMPP for power users and digital masochists | | Location: | [[http://github.com/bqv/weechat-xmpp]] | @@ -115,8 +115,10 @@ * [ ] OMEMO (libsignal-protocol-c / axc) * [ ] Presence * [X] Disco - * [ ] Disco response + * [X] Disco response * [ ] Key Generation / storage (secured_data?) + * [X] Generation + * [ ] Storage * [ ] Messages * [ ] [#C] MUC PMs * [ ] [#A] Send typing notifications diff --git a/connection.c b/connection.c index b1d35a9..d534ce2 100644 --- a/connection.c +++ b/connection.c @@ -697,7 +697,57 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, children[0]); xmpp_stanza_release(children[0]); - omemo__init(&account->omemo, 0, NULL); + struct t_hashtable *variables = weechat_hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + weechat_hashtable_set(variables, "account", account->name); + char *dev_str = weechat_string_eval_expression( + "${sec.data.xmpp_device_${account}}", + NULL, variables, NULL); + char *b64_id = weechat_string_eval_expression( + "${sec.data.xmpp_identity_${account}}", + NULL, variables, NULL); + weechat_hashtable_free(variables); + uint32_t dev_id = dev_str[0] ? atoi(dev_str) : 0; + uint8_t identity[128]; + if (b64_id) + weechat_string_base_decode(64, b64_id, (char*)identity); + struct t_identity id_key = { + .key = b64_id ? identity : NULL, + .length = 4, + }; + + omemo__init(&account->omemo, dev_id, &id_key); + + char account_id[64] = {0}; + snprintf(account_id, sizeof(account_id), "%d", account->omemo->device_id); + if (weechat_strcasecmp(dev_str, account_id) != 0) + { + char **command = weechat_string_dyn_alloc(256); + weechat_string_dyn_concat(command, "/secure set ", -1); + weechat_string_dyn_concat(command, "xmpp_device_", -1); + weechat_string_dyn_concat(command, account->name, -1); + weechat_string_dyn_concat(command, " ", -1); + weechat_string_dyn_concat(command, account_id, -1); + weechat_command(account->buffer, *command); + weechat_string_dyn_free(command, 1); + } + char account_key[64] = {0}; + weechat_string_base_encode(64, (char*)account->omemo->identity.key, + account->omemo->identity.length, account_key); + if (memcmp(identity, account->omemo->identity.key, + account->omemo->identity.length) != 0) + { + char **command = weechat_string_dyn_alloc(256); + weechat_string_dyn_concat(command, "/secure set ", -1); + weechat_string_dyn_concat(command, "xmpp_identity_", -1); + weechat_string_dyn_concat(command, account->name, -1); + weechat_string_dyn_concat(command, " ", -1); + weechat_string_dyn_concat(command, account_id, -1); + weechat_command(account->buffer, *command); + weechat_string_dyn_free(command, 1); + } } else { diff --git a/omemo.c b/omemo.c index 6ce67d7..d331bf1 100644 --- a/omemo.c +++ b/omemo.c @@ -9,8 +9,6 @@ void omemo__init(struct t_omemo **omemo, uint32_t device, struct t_identity *identity) { - const char* ns_devicelist = "eu.siacs.conversations.axolotl.devicelist"; - const char* ft_devicelist = "eu.siacs.conversations.axolotl.devicelist+notify"; int rc; srandom(time(NULL)); From f5d97c4bd87d7af7951554be6089e68ad0fc390d Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Mon, 12 Jul 2021 18:01:04 +0100 Subject: [PATCH 106/118] edit diffs --- .gitmodules | 3 ++ Makefile | 8 ++- README.org | 1 + account.c | 11 ++-- channel.c | 51 +++++++++++++------ channel.h | 5 +- connection.c | 141 ++++++++++++++++++++++++++++++++++++++++++++------- connection.h | 6 +++ diff | 1 + 9 files changed, 188 insertions(+), 39 deletions(-) create mode 160000 diff diff --git a/.gitmodules b/.gitmodules index 56502e4..6d435d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "omemo"] path = omemo url = https://github.com/gkdr/libomemo +[submodule "diff"] + path = diff + url = https://github.com/kristapsdz/libdiff diff --git a/Makefile b/Makefile index 2f7b713..160c79c 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ SRCS=plugin.c \ xmpp/presence.c \ xmpp/iq.c \ -DEPS=omemo/build/libomemo-conversations.a axc/build/libaxc.a +DEPS=omemo/build/libomemo-conversations.a axc/build/libaxc.a diff/libdiff.a OBJS=$(subst .c,.o,$(SRCS)) all: weechat-xmpp @@ -47,6 +47,11 @@ axc/build/libaxc.a: $(MAKE) -C axc axc: axc/build/libaxc.a +diff/libdiff.a: + cd diff && ./configure + $(MAKE) -C diff CFLAGS=-fPIC +diff: diff/libdiff.a + test: xmpp.so env LD_PRELOAD=$(DEBUG) \ weechat -a -P 'alias,buflist,irc' -r '/plugin load ./xmpp.so' @@ -68,6 +73,7 @@ clean: $(RM) -f $(OBJS) $(MAKE) -C omemo clean || true $(MAKE) -C axc clean || true + $(MAKE) -C diff clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true git submodule update --init --recursive || true diff --git a/README.org b/README.org index 37728fd..19d9269 100644 --- a/README.org +++ b/README.org @@ -106,6 +106,7 @@ * [X] [#B] Displaying * [X] [#B] Tagging * [ ] [#B] Making + * [X] [#C] Diff highlighting * [ ] [#B] Handle errors gracefully * [X] [#B] Presence/nicklist * [X] [#B] Enters diff --git a/account.c b/account.c index 4943e83..a9583db 100644 --- a/account.c +++ b/account.c @@ -168,6 +168,8 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve static const char *log_level_name[4] = {"debug", "info", "warn", "error"}; + const char *tags = level > XMPP_LEVEL_DEBUG ? "no_log" : NULL; + char *xml; if ((level == XMPP_LEVEL_DEBUG) && ((xml = strchr(msg, '<')) != NULL)) { @@ -219,14 +221,16 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve 0, 0, &size); if (lines[size-1][0] == 0) lines[--size] = 0; - weechat_printf( + weechat_printf_date_tags( account ? account->buffer : NULL, + 0, tags, _("%s%s (%s): %s"), weechat_prefix("network"), area, log_level_name[level], header); for (int i = 1; i < size; i++) - weechat_printf( + weechat_printf_date_tags( account ? account->buffer : NULL, + 0, tags, _("%s%s"), colour, lines[i]); weechat_string_free_split(lines); @@ -234,8 +238,9 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve } else { - weechat_printf( + weechat_printf_date_tags( account ? account->buffer : NULL, + 0, tags, _("%s%s (%s): %s"), weechat_prefix("network"), area, log_level_name[level], msg); diff --git a/channel.c b/channel.c index 8d8aa0d..bebed0d 100644 --- a/channel.c +++ b/channel.c @@ -86,7 +86,7 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, buffer_created = 0; snprintf(buffer_name, sizeof(buffer_name), - "%s.%s", account->name, name); + "xmpp.%s.%s", account->name, name); ptr_buffer = channel__search_buffer(account, type, name); if (ptr_buffer) @@ -586,7 +586,8 @@ void channel__update_topic(struct t_channel *channel, struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel *channel, - const char *id) + const char *id, const char *client, + const char *status) { struct t_channel_member *member; struct t_user *user; @@ -611,23 +612,35 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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 + if (weechat_strcasecmp(user->id, channel->id) == 0 && channel->type == CHANNEL_TYPE_MUC) - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s %sentered%s %s", + weechat_printf_date_tags(channel->buffer, 0, "log2", "%sMUC: %s", + weechat_prefix("network"), + user->id); + else 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 %sentered%s %s %s%s%s", weechat_prefix("join"), user__as_prefix_raw(account, jid_resource), + client ? "(" : "", client, client ? ")" : "", weechat_color("irc.color.message_join"), weechat_color("reset"), - channel->id); + channel->id, + status ? "[" : "", + status ? status : "", + status ? "]" : ""); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %sentered%s %s", + weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %sentered%s %s %s%s%s", weechat_prefix("join"), user__as_prefix_raw(account, xmpp_jid_bare(account->context, user->id)), xmpp_jid_resource(account->context, user->id), weechat_color("irc.color.message_join"), weechat_color("reset"), - channel->id); + channel->id, + status ? "[" : "", + status ? status : "", + status ? "]" : ""); return member; } @@ -692,7 +705,7 @@ int channel__set_member_affiliation(struct t_account *account, struct t_channel_member *channel__remove_member(struct t_account *account, struct t_channel *channel, - const char *id) + const char *id, const char *status) { struct t_channel_member *member; struct t_user *user; @@ -709,20 +722,26 @@ struct t_channel_member *channel__remove_member(struct t_account *account, 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", + weechat_printf_date_tags(channel->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); + channel->id, + status ? "[" : "", + status ? status : "", + status ? "]" : ""); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) %sleft%s %s", + weechat_printf_date_tags(channel->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), weechat_color("irc.color.message_quit"), weechat_color("reset"), - channel->id); + channel->id, + status ? "[" : "", + status ? status : "", + status ? "]" : ""); return member; } @@ -761,7 +780,9 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_send(account->connection, message); xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) - weechat_printf(channel->buffer, "%s\t%s", - user__as_prefix_raw(account, account_jid(account)), - body); + weechat_printf_date_tags(channel->buffer, 0, + "xmpp_message,message,notify_none,self_msg,log1", + "%s\t%s", + user__as_prefix_raw(account, account_jid(account)), + body); } diff --git a/channel.h b/channel.h index 3c2924d..591d87e 100644 --- a/channel.h +++ b/channel.h @@ -121,7 +121,8 @@ void channel__update_purpose(struct t_channel *channel, struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel *channel, - const char *id); + const char *id, const char *client, + const char *status); int channel__set_member_role(struct t_account *account, struct t_channel *channel, @@ -133,7 +134,7 @@ int channel__set_member_affiliation(struct t_account *account, struct t_channel_member *channel__remove_member(struct t_account *account, struct t_channel *channel, - const char *id); + const char *id, const char *status); void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body); diff --git a/connection.c b/connection.c index d534ce2..40fad43 100644 --- a/connection.c +++ b/connection.c @@ -11,6 +11,7 @@ #include #include "plugin.h" +#include "diff/diff.h" #include "xmpp/stanza.h" #include "config.h" #include "account.h" @@ -82,8 +83,10 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void struct t_account *account = (struct t_account *)userdata; struct t_user *user; struct t_channel *channel; - xmpp_stanza_t *iq__x, *iq__x__item; - const char *from, *from_bare, *role = NULL, *affiliation = NULL; + xmpp_stanza_t *iq__x, *iq__x__item, *iq__c, *iq__status; + const char *from, *from_bare, *role = NULL, *affiliation = NULL, *jid = NULL; + const char *node = NULL, *ver = NULL; + char *clientid = NULL, *status; from = xmpp_stanza_get_from(stanza); if (from == NULL) @@ -96,7 +99,25 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void iq__x__item = xmpp_stanza_get_child_by_name(iq__x, "item"); role = xmpp_stanza_get_attribute(iq__x__item, "role"); affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation"); + jid = xmpp_stanza_get_attribute(iq__x__item, "jid"); } + iq__c = xmpp_stanza_get_child_by_name_and_ns( + stanza, "c", "http://jabber.org/protocol/caps"); + if (iq__c) + { + node = xmpp_stanza_get_attribute(iq__c, "node"); + ver = xmpp_stanza_get_attribute(iq__c, "ver"); + if (jid) + clientid = strdup(jid); + else if (node && ver) + { + int len = strlen(node)+1+strlen(ver); + clientid = malloc(sizeof(char)*len); + snprintf(clientid, len, "%s#%s", node, ver); + } + } + iq__status = xmpp_stanza_get_child_by_name(stanza, "status"); + status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL; user = user__search(account, from); if (!user) @@ -107,18 +128,21 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void { if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - channel__add_member(account, channel, from); + channel__add_member(account, channel, from, clientid, status); } else if (channel) { channel__set_member_role(account, channel, from, role); channel__set_member_affiliation(account, channel, from, affiliation); if (weechat_strcasecmp(role, "none") == 0) - channel__remove_member(account, channel, from); + channel__remove_member(account, channel, from, status); else - channel__add_member(account, channel, from); + channel__add_member(account, channel, from, clientid, status); } + if (clientid) + free(clientid); + return 1; } @@ -130,7 +154,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * struct t_channel *channel; xmpp_stanza_t *body, *delay, *topic, *replace; const char *type, *from, *nick, *from_bare, *to, *id, *replace_id, *timestamp; - char *intext; + char *intext, *difftext = NULL; struct tm time = {0}; time_t date = 0; @@ -171,6 +195,80 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * channel = channel__search(account, from_bare); if (!channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + if (replace) + { + const char *orig = NULL; + void *lines = weechat_hdata_pointer(weechat_hdata_get("buffer"), + channel->buffer, "lines"); + if (lines) + { + void *last_line = weechat_hdata_pointer(weechat_hdata_get("lines"), + lines, "last_line"); + while (last_line && !orig) + { + void *line_data = weechat_hdata_pointer(weechat_hdata_get("line"), + last_line, "data"); + if (line_data) + { + int tags_count = weechat_hdata_integer(weechat_hdata_get("line_data"), + line_data, "tags_count"); + char str_tag[20] = {0}; + for (int n_tag = 0; n_tag < tags_count; n_tag++) + { + snprintf(str_tag, sizeof(str_tag), "%d|tags_array", n_tag); + const char *tag = weechat_hdata_string(weechat_hdata_get("line_data"), + line_data, str_tag); + if (strlen(tag) > strlen("id_") && + weechat_strcasecmp(tag+strlen("id_"), replace_id) == 0) + { + orig = weechat_hdata_string(weechat_hdata_get("line_data"), + line_data, "message"); + break; + } + } + } + + last_line = weechat_hdata_pointer(weechat_hdata_get("line"), + last_line, "prev_line"); + } + } + + if (orig) + { + struct diff result; + if (diff(&result, char_cmp, 1, orig, strlen(orig), intext, strlen(intext)) > 0) + { + char **visual = weechat_string_dyn_alloc(256); + char ch[2] = {0}; + + for (size_t i = 0; i < result.sessz; i++) + switch (result.ses[i].type) + { + case DIFF_ADD: + weechat_string_dyn_concat(visual, weechat_color("green"), -1); + *ch = *(const char *)result.ses[i].e; + weechat_string_dyn_concat(visual, ch, -1); + break; + case DIFF_DELETE: + weechat_string_dyn_concat(visual, weechat_color("red"), -1); + *ch = *(const char *)result.ses[i].e; + weechat_string_dyn_concat(visual, ch, -1); + break; + case DIFF_COMMON: + default: + weechat_string_dyn_concat(visual, weechat_color("resetcolor"), -1); + *ch = *(const char *)result.ses[i].e; + weechat_string_dyn_concat(visual, ch, -1); + break; + } + free(result.ses); + free(result.lcs); + + difftext = strdup(*visual); + weechat_string_dyn_free(visual, 1); + } + } + } nick = NULL; if (weechat_strcasecmp(type, "groupchat") == 0) @@ -225,20 +323,22 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", edit, user__as_prefix_raw(account, nick), - to, intext ? intext : ""); + to, difftext ? difftext : intext ? intext : ""); else if (weechat_string_match(intext, "/me *", 0)) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s %s", edit, weechat_prefix("action"), nick, - intext ? intext+4 : ""); + difftext ? difftext+4 : intext ? intext+4 : ""); else weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s", edit, user__as_prefix_raw(account, nick), - intext ? intext : ""); + difftext ? difftext : intext ? intext : ""); weechat_string_dyn_free(dyn_tags, 1); if (intext) xmpp_free(account->context, intext); + if (difftext) + free(difftext); return 1; } @@ -248,7 +348,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd (void) conn; struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; + xmpp_stanza_t *reply, *query, *identity, *feature, *enable, *x, *field, *value, *text; xmpp_stanza_t *pubsub, *items, *item, *list, *device, **children; xmpp_stanza_t *storage, *conference, *nick; static struct utsname osinfo; @@ -315,6 +415,12 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd FEATURE("urn:xmpp:time"); #undef FEATURE + enable = xmpp_stanza_new(account->context); + xmpp_stanza_set_name(enable, "enable"); + xmpp_stanza_set_ns(enable, "urn:xmpp:carbons:2"); + xmpp_stanza_add_child(query, enable); + xmpp_stanza_release(enable); + x = xmpp_stanza_new(account->context); xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_ns(x, "jabber:x:data"); @@ -710,15 +816,15 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, NULL, variables, NULL); weechat_hashtable_free(variables); uint32_t dev_id = dev_str[0] ? atoi(dev_str) : 0; - uint8_t identity[128]; - if (b64_id) + uint8_t identity[128] = {0}; + if (b64_id && *b64_id) weechat_string_base_decode(64, b64_id, (char*)identity); struct t_identity id_key = { - .key = b64_id ? identity : NULL, + .key = identity, .length = 4, }; - omemo__init(&account->omemo, dev_id, &id_key); + omemo__init(&account->omemo, dev_id, b64_id && *b64_id ? &id_key : NULL); char account_id[64] = {0}; snprintf(account_id, sizeof(account_id), "%d", account->omemo->device_id); @@ -735,16 +841,15 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, } char account_key[64] = {0}; weechat_string_base_encode(64, (char*)account->omemo->identity.key, - account->omemo->identity.length, account_key); - if (memcmp(identity, account->omemo->identity.key, - account->omemo->identity.length) != 0) + account->omemo->identity.length, account_key); + if (weechat_strcasecmp(b64_id, account_key) != 0) { char **command = weechat_string_dyn_alloc(256); weechat_string_dyn_concat(command, "/secure set ", -1); weechat_string_dyn_concat(command, "xmpp_identity_", -1); weechat_string_dyn_concat(command, account->name, -1); weechat_string_dyn_concat(command, " ", -1); - weechat_string_dyn_concat(command, account_id, -1); + weechat_string_dyn_concat(command, account_key, -1); weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); } diff --git a/connection.h b/connection.h index 54eb1dc..e84c419 100644 --- a/connection.h +++ b/connection.h @@ -13,4 +13,10 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, const unsigned long timeout); +static inline int +char_cmp(const void *p1, const void *p2) +{ + return *(const char *)p1 == *(const char *)p2; +} + #endif /*WEECHAT_XMPP_CONNECTION_H*/ diff --git a/diff b/diff new file mode 160000 index 0000000..aadb3d7 --- /dev/null +++ b/diff @@ -0,0 +1 @@ +Subproject commit aadb3d7fe4dcb4b212c77e4fc6c2599826aeb50a From 609d9963b57258ce494b898e37e3c87197e10b35 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Tue, 13 Jul 2021 04:03:34 +0100 Subject: [PATCH 107/118] more iqs --- Makefile | 1 + README.org | 7 +++- connection.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++----- connection.h | 6 ---- util.c | 14 ++++++++ util.h | 10 ++++++ xmpp/iq.c | 69 +++++++++++++++++++++++++++++++++++++++ xmpp/stanza.h | 18 +++++++++++ 8 files changed, 199 insertions(+), 15 deletions(-) create mode 100644 util.c create mode 100644 util.h diff --git a/Makefile b/Makefile index 160c79c..a7d0b0c 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ SRCS=plugin.c \ message.c \ omemo.c \ user.c \ + util.c \ xmpp/presence.c \ xmpp/iq.c \ diff --git a/README.org b/README.org index 19d9269..d16370a 100644 --- a/README.org +++ b/README.org @@ -119,7 +119,8 @@ * [X] Disco response * [ ] Key Generation / storage (secured_data?) * [X] Generation - * [ ] Storage + * [X] Storage + * [ ] Announce * [ ] Messages * [ ] [#C] MUC PMs * [ ] [#A] Send typing notifications @@ -128,6 +129,10 @@ * [ ] Message Carbons * [ ] Service Disco * [ ] Bookmarks / Roster + * [X] Autojoin bookmarks + * [ ] Add bookmarks + * [ ] Delete bookmarks + * [ ] Roster * [ ] OTR (libotr) * [ ] PGP (libgpgme) * [ ] Room Explorer (https://search.jabber.network/docs/api) diff --git a/connection.c b/connection.c index 40fad43..d58f940 100644 --- a/connection.c +++ b/connection.c @@ -19,6 +19,7 @@ #include "channel.h" #include "connection.h" #include "omemo.h" +#include "util.h" void connection__init() { @@ -221,8 +222,53 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (strlen(tag) > strlen("id_") && weechat_strcasecmp(tag+strlen("id_"), replace_id) == 0) { - orig = weechat_hdata_string(weechat_hdata_get("line_data"), - line_data, "message"); + struct t_arraylist *orig_lines = weechat_arraylist_new( + 0, 0, 0, NULL, NULL, NULL, NULL); + char *msg = (char*)weechat_hdata_string(weechat_hdata_get("line_data"), + line_data, "message"); + weechat_arraylist_insert(orig_lines, 0, msg); + + while (msg) + { + last_line = weechat_hdata_pointer(weechat_hdata_get("line"), + last_line, "prev_line"); + if (last_line) + line_data = weechat_hdata_pointer(weechat_hdata_get("line"), + last_line, "data"); + else + line_data = NULL; + + msg = NULL; + if (line_data) + { + tags_count = weechat_hdata_integer(weechat_hdata_get("line_data"), + line_data, "tags_count"); + for (n_tag = 0; n_tag < tags_count; n_tag++) + { + snprintf(str_tag, sizeof(str_tag), "%d|tags_array", n_tag); + tag = weechat_hdata_string(weechat_hdata_get("line_data"), + line_data, str_tag); + if (strlen(tag) > strlen("id_") && + weechat_strcasecmp(tag+strlen("id_"), replace_id) == 0) + { + msg = (char*)weechat_hdata_string(weechat_hdata_get("line_data"), + line_data, "message"); + break; + } + } + } + + if (msg) + weechat_arraylist_insert(orig_lines, 0, msg); + } + + char **orig_message = weechat_string_dyn_alloc(256); + for (int i = 0; i < weechat_arraylist_size(orig_lines); i++) + weechat_string_dyn_concat(orig_message, + weechat_arraylist_get(orig_lines, i), + -1); + orig = *orig_message; + weechat_string_dyn_free(orig_message, 0); break; } } @@ -640,26 +686,53 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd } children[i] = NULL; - ns = "eu.siacs.conversations.axolotl"; + node = "eu.siacs.conversations.axolotl"; children[0] = stanza__iq_pubsub_publish_item_list( - account->context, NULL, children, with_noop(ns)); + 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 = "http://jabber.org/protocol/pubsub"; + ns = "http://jabber.org/protocol/pubsub"; children[0] = stanza__iq_pubsub_publish(account->context, NULL, children, - with_noop(node)); + with_noop(ns)); children[0] = stanza__iq_pubsub(account->context, NULL, children, with_noop("")); reply = stanza__iq(account->context, xmpp_stanza_reply(stanza), children, NULL, strdup("announce1"), NULL, NULL, strdup("set")); - free(children); - xmpp_send(conn, reply); xmpp_stanza_release(reply); + + char bundle_node[128] = {0}; + snprintf(bundle_node, sizeof(bundle_node), + "eu.siacs.conversations.axolotl.bundles:%d", + account->omemo->device_id); + + children[1] = NULL; + children[0] = NULL; + ns = "eu.siacs.conversations.axolotl"; + children[0] = stanza__iq_pubsub_publish_item_bundle( + account->context, NULL, NULL, with_noop(ns)); + children[1] = NULL; + children[0] = stanza__iq_pubsub_publish_item( + account->context, NULL, children, with_noop("current")); + children[0] = stanza__iq_pubsub_publish(account->context, + NULL, children, + with_noop(bundle_node)); + 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, strdup("announce2"), + strdup(account_jid(account)), strdup(account_jid(account)), + strdup("set")); + + xmpp_send(conn, children[0]); + xmpp_stanza_release(children[0]); + + free(children); } } } diff --git a/connection.h b/connection.h index e84c419..54eb1dc 100644 --- a/connection.h +++ b/connection.h @@ -13,10 +13,4 @@ int connection__connect(struct t_account *account, xmpp_conn_t **connection, void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, const unsigned long timeout); -static inline int -char_cmp(const void *p1, const void *p2) -{ - return *(const char *)p1 == *(const char *)p2; -} - #endif /*WEECHAT_XMPP_CONNECTION_H*/ diff --git a/util.c b/util.c new file mode 100644 index 0000000..15972a8 --- /dev/null +++ b/util.c @@ -0,0 +1,14 @@ +// 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 "plugin.h" +#include "util.h" + +int char_cmp(const void *p1, const void *p2) +{ + return *(const char *)p1 == *(const char *)p2; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..2226299 --- /dev/null +++ b/util.h @@ -0,0 +1,10 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_UTIL_H_ +#define _WEECHAT_XMPP_UTIL_H_ + +int char_cmp(const void *p1, const void *p2); + +#endif /*WEECHAT_XMPP_UTIL_H*/ diff --git a/xmpp/iq.c b/xmpp/iq.c index 1c51698..1cf0b39 100644 --- a/xmpp/iq.c +++ b/xmpp/iq.c @@ -213,6 +213,75 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, x return parent; } +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *ns) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "bundle"); + } + + if (ns) + { + xmpp_stanza_set_ns(parent, ns->value); + ns->finalize(ns); + free(ns); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *id) +{ + xmpp_stanza_t *parent = base; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "signedPreKeyPublic"); + } + + if (id) + { + xmpp_stanza_set_id(parent, id->value); + id->finalize(id); + free(id); + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeySignature) +{ +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_identityKey( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *identityKey) +{ +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeys) +{ +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys_preKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeyPublic) +{ +} + xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *ns) { diff --git a/xmpp/stanza.h b/xmpp/stanza.h index 38aa459..a03d054 100644 --- a/xmpp/stanza.h +++ b/xmpp/stanza.h @@ -74,6 +74,24 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_sta xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *id); +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_stanza_t *base, + xmpp_stanza_t **children, struct t_string *ns); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeyId); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeySignature); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_identityKey( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *identityKey); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeys); + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys_preKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeyPublic); + xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *ns); From 9c03d4d660d6788e4e088641f17061e2799de5ec Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 16 Jul 2021 03:44:46 +0100 Subject: [PATCH 108/118] carbons --- .envrc | 3 +- Makefile | 16 +----- README.org | 16 +++--- account.c | 1 + channel.c | 1 + command.c | 2 +- connection.c | 150 ++++++++++++++++++++++++++++++++++++++----------- omemo.c | 153 +++++++++++++++++++++++++++++++++++++++----------- omemo.h | 15 ++--- xmpp/iq.c | 121 +++++++++++++++++++++++++++++++++++---- xmpp/stanza.h | 17 +++--- 11 files changed, 378 insertions(+), 117 deletions(-) diff --git a/.envrc b/.envrc index f61f48c..ae0bd87 100644 --- a/.envrc +++ b/.envrc @@ -37,8 +37,7 @@ use_guix() autoconf autoconf-archive automake libtool make cmake gcc-toolchain pkg-config patchelf weechat libxml2 libstrophe - glib libsignal-protocol-c sqlite - minixml + libgcrypt libsignal-protocol-c ) # Thanks diff --git a/Makefile b/Makefile index a7d0b0c..9936944 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,10 @@ ifdef DEBUG endif RM=rm -f FIND=find -INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags glib-2.0) $(shell pkg-config --cflags libsignal-protocol-c) +INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags libsignal-protocol-c) CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) -LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs glib-2.0) $(shell pkg-config --libs libsignal-protocol-c) -lmxml +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -28,7 +28,7 @@ SRCS=plugin.c \ xmpp/presence.c \ xmpp/iq.c \ -DEPS=omemo/build/libomemo-conversations.a axc/build/libaxc.a diff/libdiff.a +DEPS=diff/libdiff.a OBJS=$(subst .c,.o,$(SRCS)) all: weechat-xmpp @@ -40,14 +40,6 @@ xmpp.so: $(OBJS) $(DEPS) patchelf --set-rpath $(LIBRARY_PATH):$(shell realpath $(shell dirname $(shell gcc --print-libgcc-file-name))/../../../) xmpp.so && \ patchelf --shrink-rpath xmpp.so || true -omemo/build/libomemo-conversations.a: - $(MAKE) -C omemo -omemo: omemo/build/libomemo-conversations.a - -axc/build/libaxc.a: - $(MAKE) -C axc -axc: axc/build/libaxc.a - diff/libdiff.a: cd diff && ./configure $(MAKE) -C diff CFLAGS=-fPIC @@ -72,8 +64,6 @@ tidy: clean: $(RM) -f $(OBJS) - $(MAKE) -C omemo clean || true - $(MAKE) -C axc clean || true $(MAKE) -C diff clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true diff --git a/README.org b/README.org index d16370a..8b95555 100644 --- a/README.org +++ b/README.org @@ -88,7 +88,9 @@ * [X] Opening PMs (/chat) ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message - * [X] OOB media messages + * [-] OOB messages + * [X] Single media on a line + * [ ] Multiple media inline (protocol?) * [X] Buffer autoswitch on enter/open * [X] Handle open/enter jids with a resource without breaking * [X] Allow /close without crashing @@ -96,13 +98,13 @@ * [ ] [#B] Event-driven MUC entrance * [ ] [#C] XMPP Ping (xep-199) * [X] [#A] Highlight - * [ ] MUCs + * [-] MUCs * [X] Opening (/enter) * [ ] [#B] Leave on /close * [X] Receiving * [X] Sending * [X] With /msg - * [ ] [#B] Edits + * [-] [#B] Edits * [X] [#B] Displaying * [X] [#B] Tagging * [ ] [#B] Making @@ -113,11 +115,11 @@ * [X] [#B] Leaves * [X] [#B] Tracking * [X] [#B] Set/show topic - * [ ] OMEMO (libsignal-protocol-c / axc) - * [ ] Presence + * [-] OMEMO (libsignal-protocol-c / axc) + * [-] Presence * [X] Disco * [X] Disco response - * [ ] Key Generation / storage (secured_data?) + * [-] Key Generation / storage (secured_data?) * [X] Generation * [X] Storage * [ ] Announce @@ -128,7 +130,7 @@ * [ ] [#C] Read receipts * [ ] Message Carbons * [ ] Service Disco - * [ ] Bookmarks / Roster + * [-] Bookmarks / Roster * [X] Autojoin bookmarks * [ ] Add bookmarks * [ ] Delete bookmarks diff --git a/account.c b/account.c index a9583db..453fbe3 100644 --- a/account.c +++ b/account.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include diff --git a/channel.c b/channel.c index bebed0d..7a8a2a6 100644 --- a/channel.c +++ b/channel.c @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include #include #include diff --git a/command.c b/command.c index 85de4f5..c40b581 100644 --- a/command.c +++ b/command.c @@ -649,7 +649,7 @@ int command__me(const void *pointer, void *data, "xmpp_message,message,action,private,notify_none,self_msg,log1", "%s%s %s", weechat_prefix("action"), account_jid(ptr_account), - text); + strlen(text) > strlen("/me ") ? text+4 : ""); } return WEECHAT_RC_OK; diff --git a/connection.c b/connection.c index d58f940..6c24c90 100644 --- a/connection.c +++ b/connection.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -153,8 +154,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * struct t_account *account = (struct t_account *)userdata; struct t_channel *channel; - xmpp_stanza_t *body, *delay, *topic, *replace; - const char *type, *from, *nick, *from_bare, *to, *id, *replace_id, *timestamp; + xmpp_stanza_t *body, *delay, *topic, *replace, *composing, *sent, *received, *forwarded; + const char *type, *from, *nick, *from_bare, *to, *to_bare, *id, *replace_id, *timestamp; char *intext, *difftext = NULL; struct tm time = {0}; time_t date = 0; @@ -163,20 +164,66 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (body == NULL) { topic = xmpp_stanza_get_child_by_name(stanza, "subject"); - if (topic == NULL) - return 1; - intext = xmpp_stanza_get_text(topic); - 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); - if (!channel) - channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - channel__update_topic(channel, intext ? intext : "", from, 0); - if (intext != NULL) - xmpp_free(account->context, intext); + if (topic != NULL) + { + intext = xmpp_stanza_get_text(topic); + 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); + if (!channel) + channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + channel__update_topic(channel, intext ? intext : "", from, 0); + if (intext != NULL) + xmpp_free(account->context, intext); + } + + composing = xmpp_stanza_get_child_by_name_and_ns( + stanza, "composing", "http://jabber.org/protocol/chatstates"); + if (composing != NULL) + { + 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); + if (!channel) + return 1; + struct t_user *user = user__search(account, from); + if (!user) + user = user__new(account, from, from); + channel__add_typing(channel, user); + weechat_printf(channel->buffer, "%s typing...", from); + } + + sent = xmpp_stanza_get_child_by_name_and_ns( + stanza, "sent", "urn:xmpp:carbons:2"); + if (sent) + forwarded = xmpp_stanza_get_child_by_name_and_ns( + sent, "forwarded", "urn:xmpp:forward:0"); + received = xmpp_stanza_get_child_by_name_and_ns( + stanza, "received", "urn:xmpp:carbons:2"); + if (sent && forwarded != NULL) + { + xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); + //from = xmpp_stanza_get_from(stanza); + //to = xmpp_stanza_get_to(stanza); + //xmpp_stanza_set_from(stanza, to); + //xmpp_stanza_set_to(stanza, from); + return connection__message_handler(conn, message, userdata); + } + if (received) + forwarded = xmpp_stanza_get_child_by_name_and_ns( + received, "forwarded", "urn:xmpp:forward:0"); + if (received && forwarded != NULL) + { + xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); + return connection__message_handler(conn, message, userdata); + } + return 1; } type = xmpp_stanza_get_type(stanza); @@ -187,15 +234,19 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * return 1; from_bare = xmpp_jid_bare(account->context, from); to = xmpp_stanza_get_to(stanza); + to_bare = to ? xmpp_jid_bare(account->context, to) : NULL; id = xmpp_stanza_get_id(stanza); - replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", "urn:xmpp:message-correct:0"); + replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", + "urn:xmpp:message-correct:0"); replace_id = replace ? xmpp_stanza_get_id(replace) : NULL; intext = xmpp_stanza_get_text(body); - channel = channel__search(account, from_bare); + const char *channel_id = weechat_strcasecmp(account_jid(account), from_bare) + == 0 ? to_bare : from_bare; + channel = channel__search(account, channel_id); if (!channel) - channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + channel = channel__new(account, CHANNEL_TYPE_PM, channel_id, channel_id); if (replace) { const char *orig = NULL; @@ -304,6 +355,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * default: weechat_string_dyn_concat(visual, weechat_color("resetcolor"), -1); *ch = *(const char *)result.ses[i].e; + weechat_string_dyn_concat(visual, ch, -1); break; } @@ -316,7 +368,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * } } - nick = NULL; + nick = from; if (weechat_strcasecmp(type, "groupchat") == 0) { nick = weechat_strcasecmp(channel->name, @@ -366,7 +418,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * weechat_string_dyn_concat(dyn_tags, ",log1", -1); const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly - if (strcmp(to, channel->id) == 0) + if (channel_id == from_bare && strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", edit, user__as_prefix_raw(account, nick), to, difftext ? difftext : intext ? intext : ""); @@ -394,7 +446,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd (void) conn; struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *reply, *query, *identity, *feature, *enable, *x, *field, *value, *text; + xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; xmpp_stanza_t *pubsub, *items, *item, *list, *device, **children; xmpp_stanza_t *storage, *conference, *nick; static struct utsname osinfo; @@ -461,12 +513,6 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd FEATURE("urn:xmpp:time"); #undef FEATURE - enable = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(enable, "enable"); - xmpp_stanza_set_ns(enable, "urn:xmpp:carbons:2"); - xmpp_stanza_add_child(query, enable); - xmpp_stanza_release(enable); - x = xmpp_stanza_new(account->context); xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_ns(x, "jabber:x:data"); @@ -710,11 +756,38 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd "eu.siacs.conversations.axolotl.bundles:%d", account->omemo->device_id); - children[1] = NULL; - children[0] = NULL; + xmpp_stanza_t *textchild[2] = {NULL}; + textchild[0] = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(textchild[0], "b64enc1"); + children[0] = stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( + account->context, NULL, textchild, with_noop("1")); + textchild[0] = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(textchild[0], "b64enc2"); + children[1] = stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( + account->context, NULL, textchild); + textchild[0] = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(textchild[0], "b64enc3"); + children[2] = stanza__iq_pubsub_publish_item_bundle_identityKey( + account->context, NULL, textchild); + textchild[0] = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(textchild[0], "b64enc4"); + children[3] = stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + account->context, NULL, textchild, with_noop("1")); + textchild[0] = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(textchild[0], "b64enc5"); + children[4] = stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + account->context, NULL, textchild, with_noop("2")); + textchild[0] = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(textchild[0], "b64enc6"); + children[5] = stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + account->context, NULL, textchild, with_noop("3")); + children[6] = NULL; + children[3] = stanza__iq_pubsub_publish_item_bundle_prekeys( + account->context, NULL, &children[3]); + children[4] = NULL; ns = "eu.siacs.conversations.axolotl"; children[0] = stanza__iq_pubsub_publish_item_bundle( - account->context, NULL, NULL, with_noop(ns)); + account->context, NULL, children, with_noop(ns)); children[1] = NULL; children[0] = stanza__iq_pubsub_publish_item( account->context, NULL, children, with_noop("current")); @@ -846,6 +919,17 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, pres); xmpp_stanza_release(pres); + children[1] = NULL; + children[0] = + stanza__iq_enable(account->context, NULL, with_noop("urn:xmpp:carbons:2")); + children[0] = + stanza__iq(account->context, NULL, children, + strdup("jabber:client"), strdup("enable1"), + strdup(account_jid(account)), NULL, strdup("set")); + + xmpp_send(conn, children[0]); + xmpp_stanza_release(children[0]); + children[1] = NULL; children[0] = stanza__iq_pubsub_items(account->context, NULL, @@ -913,8 +997,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, weechat_string_dyn_free(command, 1); } char account_key[64] = {0}; - weechat_string_base_encode(64, (char*)account->omemo->identity.key, - account->omemo->identity.length, account_key); + weechat_string_base_encode(64, (char*)account->omemo->identity->key, + account->omemo->identity->length, account_key); if (weechat_strcasecmp(b64_id, account_key) != 0) { char **command = weechat_string_dyn_alloc(256); diff --git a/omemo.c b/omemo.c index d331bf1..c8e7795 100644 --- a/omemo.c +++ b/omemo.c @@ -3,57 +3,144 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include +#include +#include +#include #include "omemo.h" +/* +char *omemo__signal_init() +{ + signal_protocol_store_context *store_context_p = NULL; + + signal_protocol_session_store session_store = { + .load_session_func = &axc_db_session_load, + .get_sub_device_sessions_func = &axc_db_session_get_sub_device_sessions, + .store_session_func = &axc_db_session_store, + .contains_session_func = &axc_db_session_contains, + .delete_session_func = &axc_db_session_delete, + .delete_all_sessions_func = &axc_db_session_delete_all, + .destroy_func = &axc_db_session_destroy_store_ctx, + .user_data = ctx_p + }; + signal_protocol_pre_key_store pre_key_store = { + .load_pre_key = &axc_db_pre_key_load, + .store_pre_key = &axc_db_pre_key_store, + .contains_pre_key = &axc_db_pre_key_contains, + .remove_pre_key = &axc_db_pre_key_remove, + .destroy_func = &axc_db_pre_key_destroy_ctx, + .user_data = ctx_p + }; + signal_protocol_signed_pre_key_store signed_pre_key_store = { + .load_signed_pre_key = &axc_db_signed_pre_key_load, + .store_signed_pre_key = &axc_db_signed_pre_key_store, + .contains_signed_pre_key = &axc_db_signed_pre_key_contains, + .remove_signed_pre_key = &axc_db_signed_pre_key_remove, + .destroy_func = &axc_db_signed_pre_key_destroy_ctx, + .user_data = ctx_p + }; + signal_protocol_identity_key_store identity_key_store = { + .get_identity_key_pair = &axc_db_identity_get_key_pair, + .get_local_registration_id = &axc_db_identity_get_local_registration_id, + .save_identity = &axc_db_identity_save, + .is_trusted_identity = &axc_db_identity_always_trusted, + .destroy_func = &axc_db_identity_destroy_ctx, + .user_data = ctx_p + }; + + if (signal_context_create(&(ctx_p->axolotl_global_context_p), ctx_p)) { + return "failed to create global axolotl context"; + } + + signal_crypto_provider crypto_provider = { + .random_func = random_bytes, + .hmac_sha256_init_func = hmac_sha256_init, + .hmac_sha256_update_func = hmac_sha256_update, + .hmac_sha256_final_func = hmac_sha256_final, + .sha512_digest_init_func = sha512_digest_init, + .sha512_digest_update_func = sha512_digest_update, + .sha512_digest_final_func = sha512_digest_final, + .encrypt_func = aes_encrypt, + .decrypt_func = aes_decrypt, + .user_data = ctx_p + }; + if (signal_context_set_crypto_provider(ctx_p->axolotl_global_context_p, &crypto_provider)) { + return "failed to set crypto provider"; + } + + if (signal_context_set_locking_functions(ctx_p->axolotl_global_context_p, recursive_mutex_lock, recursive_mutex_unlock)) { + return "failed to set locking functions"; + } + + if (signal_protocol_store_context_create(&store_context_p, ctx_p->axolotl_global_context_p)) { + return "failed to create store context"; + } + + if (signal_protocol_store_context_set_session_store(store_context_p, &session_store)) { + return "failed to create session store"; + } + + if (signal_protocol_store_context_set_pre_key_store(store_context_p, &pre_key_store)) { + return "failed to set pre key store"; + } + + if (signal_protocol_store_context_set_signed_pre_key_store(store_context_p, &signed_pre_key_store)) { + return "failed to set signed pre key store"; + } + + if (signal_protocol_store_context_set_identity_key_store(store_context_p, &identity_key_store)) { + return "failed to set identity key store"; + } + + ctx_p->axolotl_store_context_p = store_context_p; + + return NULL; +} +*/ + void omemo__init(struct t_omemo **omemo, uint32_t device, - struct t_identity *identity) + struct t_identity *const identity) { - int rc; + struct t_omemo *new_omemo; srandom(time(NULL)); - omemo_bundle* bundle; - rc = omemo_bundle_create(&bundle); - if (rc) - return; - - if (!device) - device = random(); - omemo_bundle_set_device_id(bundle, device); + new_omemo = calloc(1, sizeof(**omemo)); + new_omemo->identity = malloc(sizeof(*identity)); if (identity) - omemo_bundle_set_identity_key(bundle, identity->key, identity->length); + { + new_omemo->identity->length = identity->length; + new_omemo->identity->key = calloc(identity->length, sizeof(*identity->key)); + memcpy(new_omemo->identity->key, identity->key, + identity->length * sizeof(*identity->key)); + } else { - identity = malloc(sizeof(*identity)); - identity->length = 4; - identity->key = malloc(sizeof(*identity->key) * identity->length); - - identity->key[0] = random(); - identity->key[1] = random(); - identity->key[2] = random(); - identity->key[3] = random(); + new_omemo->identity->length = 4; + new_omemo->identity->key = calloc(identity->length, sizeof(*identity->key)); - omemo_bundle_set_identity_key(bundle, identity->key, identity->length); - - free(identity->key); - free(identity); + new_omemo->identity->key[0] = random(); + new_omemo->identity->key[1] = random(); + new_omemo->identity->key[2] = random(); + new_omemo->identity->key[3] = random(); } - *omemo = malloc(sizeof(**omemo)); - (*omemo)->provider.random_bytes_func = omemo_default_crypto_random_bytes; - (*omemo)->provider.aes_gcm_encrypt_func = omemo_default_crypto_aes_gcm_encrypt; - (*omemo)->provider.aes_gcm_decrypt_func = omemo_default_crypto_aes_gcm_decrypt; - (*omemo)->provider.user_data_p = (void *)(*omemo); - (*omemo)->bundle = bundle; - (*omemo)->device_id = omemo_bundle_get_device_id(bundle); - omemo_bundle_get_identity_key(bundle, &(*omemo)->identity.key, &(*omemo)->identity.length); + new_omemo->device_id = device ? device : random(); - omemo_devicelist *devicelist; + *omemo = new_omemo; } void omemo__free(struct t_omemo *omemo) { - free(omemo); + if (omemo) + { + if (omemo->identity->key) + free(omemo->identity->key); + if (omemo->identity) + free(omemo->identity); + free(omemo); + } } diff --git a/omemo.h b/omemo.h index faccd8e..3138849 100644 --- a/omemo.h +++ b/omemo.h @@ -5,10 +5,6 @@ #ifndef _WEECHAT_XMPP_OMEMO_H_ #define _WEECHAT_XMPP_OMEMO_H_ -#include "axc/src/axc.h" -#include "omemo/src/libomemo.h" -#include "omemo/src/libomemo_crypto.h" - struct t_identity { uint8_t *key; @@ -17,13 +13,12 @@ struct t_identity struct t_omemo { - omemo_crypto_provider provider; - - omemo_devicelist *devicelist; - - omemo_bundle *bundle; + //omemo_crypto_provider provider; + //axc_context *context; + //axc_bundle *a_bundle; + //omemo_bundle *o_bundle; - struct t_identity identity; + struct t_identity *identity; uint32_t device_id; }; diff --git a/xmpp/iq.c b/xmpp/iq.c index 1cf0b39..91c70e5 100644 --- a/xmpp/iq.c +++ b/xmpp/iq.c @@ -242,9 +242,10 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_s } xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *id) + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *signedPreKeyId) { xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; if (!parent) { @@ -252,34 +253,132 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( xmpp_stanza_set_name(parent, "signedPreKeyPublic"); } - if (id) + if (signedPreKeyId) { - xmpp_stanza_set_id(parent, id->value); - id->finalize(id); - free(id); + xmpp_stanza_set_attribute(parent, "signedPreKeyId", signedPreKeyId->value); + signedPreKeyId->finalize(signedPreKeyId); + free(signedPreKeyId); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); } return parent; } xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeySignature) + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children) { + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "signedPreKeySignature"); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; } xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_identityKey( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *identityKey) + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children) { + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "identityKey"); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "prekeys"); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; } -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeys) +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *preKeyId) { + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "preKeyPublic"); + } + + if (preKeyId) + { + xmpp_stanza_set_attribute(parent, "preKeyId", preKeyId->value); + preKeyId->finalize(preKeyId); + free(preKeyId); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; } -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys_preKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeyPublic) +xmpp_stanza_t *stanza__iq_enable(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *ns) { + xmpp_stanza_t *parent = base; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "enable"); + } + + if (ns) + { + xmpp_stanza_set_ns(parent, ns->value); + ns->finalize(ns); + free(ns); + } + + return parent; } xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, diff --git a/xmpp/stanza.h b/xmpp/stanza.h index a03d054..e63f7de 100644 --- a/xmpp/stanza.h +++ b/xmpp/stanza.h @@ -78,19 +78,22 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_s xmpp_stanza_t **children, struct t_string *ns); xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeyId); + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *signedPreKeyId); xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeySignature); + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children); xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_identityKey( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *identityKey); + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children); -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeys); +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children); -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys_preKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeyPublic); +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *preKeyId); + +xmpp_stanza_t *stanza__iq_enable(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *ns); xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *ns); From 7d48adaf2496b1c22bf359fd6585c51271a21b4a Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sat, 17 Jul 2021 17:36:53 +0100 Subject: [PATCH 109/118] fix pm notifs --- channel.c | 2 +- connection.c | 18 +++++------------- input.c | 4 ++-- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/channel.c b/channel.c index 7a8a2a6..90c1af8 100644 --- a/channel.c +++ b/channel.c @@ -782,7 +782,7 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) weechat_printf_date_tags(channel->buffer, 0, - "xmpp_message,message,notify_none,self_msg,log1", + "xmpp_message,message,private,notify_none,self_msg,log1", "%s\t%s", user__as_prefix_raw(account, account_jid(account)), body); diff --git a/connection.c b/connection.c index 6c24c90..eab0cc3 100644 --- a/connection.c +++ b/connection.c @@ -188,7 +188,6 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * 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); if (!channel) return 1; @@ -206,19 +205,10 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * sent, "forwarded", "urn:xmpp:forward:0"); received = xmpp_stanza_get_child_by_name_and_ns( stanza, "received", "urn:xmpp:carbons:2"); - if (sent && forwarded != NULL) - { - xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); - //from = xmpp_stanza_get_from(stanza); - //to = xmpp_stanza_get_to(stanza); - //xmpp_stanza_set_from(stanza, to); - //xmpp_stanza_set_to(stanza, from); - return connection__message_handler(conn, message, userdata); - } if (received) forwarded = xmpp_stanza_get_child_by_name_and_ns( received, "forwarded", "urn:xmpp:forward:0"); - if (received && forwarded != NULL) + if ((sent || received) && forwarded != NULL) { xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); return connection__message_handler(conn, message, userdata); @@ -401,10 +391,10 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * weechat_string_dyn_concat(dyn_tags, id, -1); } - if (strcmp(to, channel->id) == 0) + if (channel->type == CHANNEL_TYPE_PM) weechat_string_dyn_concat(dyn_tags, ",private", -1); if (weechat_string_match(intext, "/me *", 0)) - weechat_string_dyn_concat(dyn_tags, ",action", -1); + weechat_string_dyn_concat(dyn_tags, ",xmpp_action", -1); if (replace) { weechat_string_dyn_concat(dyn_tags, ",edit", -1); @@ -414,6 +404,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (date != 0) weechat_string_dyn_concat(dyn_tags, ",notify_none", -1); + else if (channel->type == CHANNEL_TYPE_PM) + weechat_string_dyn_concat(dyn_tags, ",notify_private", -1); else weechat_string_dyn_concat(dyn_tags, ",log1", -1); diff --git a/input.c b/input.c index e454ede..323a493 100644 --- a/input.c +++ b/input.c @@ -46,8 +46,8 @@ int input__data(struct t_gui_buffer *buffer, const char *text) } int input__data_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *text) + struct t_gui_buffer *buffer, + const char *text) { (void) pointer; (void) data; From 1d67aaf8a7735863a7fcf0c72e02c7cffde394bb Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 22 Jul 2021 05:04:15 +0100 Subject: [PATCH 110/118] pgp stuff --- .envrc | 30 ++++- .gitignore | 1 + Makefile | 9 +- account.c | 2 + account.h | 7 + channel.c | 254 ++++++++++++++++++++++++++++++++++-- channel.h | 36 +++++- command.c | 53 +++++++- config.c | 32 +++++ connection.c | 70 +++++++--- input.c | 27 ++++ input.h | 8 +- pgp.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++++ pgp.h | 22 ++++ plugin.c | 3 + user.c | 41 +----- user.h | 19 --- 17 files changed, 873 insertions(+), 101 deletions(-) create mode 100644 pgp.c create mode 100644 pgp.h diff --git a/.envrc b/.envrc index ae0bd87..d474ea8 100644 --- a/.envrc +++ b/.envrc @@ -29,15 +29,28 @@ use_guix() # Miscellaneous packages. ENVIRONMENTS=( - weechat + weechat # Debug runs ) # Environment packages. PACKAGES=( - autoconf autoconf-archive automake libtool - make cmake gcc-toolchain pkg-config patchelf - weechat libxml2 libstrophe - libgcrypt libsignal-protocol-c + autoconf # Deps with autoreconf + autoconf-archive # Deps with m4 tooling + automake # Deps with automake + libtool # Deps with libtool + make # Makefile and deps with makefiles + cmake # Deps with cmake + gcc-toolchain # Compilation + pkg-config # Deps configuration and configuration of deps deps + patchelf # Fix linkage (guix) + bear # Generate compile_commands.json for language servers + universal-ctags # Generate tags (make tags) + weechat # Weechat includes + libxml2 # Dep (libxml2) + libstrophe # Dep (strophe) + libgcrypt # Dep (gcrypt) + libsignal-protocol-c # Dep (libsignal) + rnp # Dep (rnpgp) ) # Thanks @@ -46,4 +59,9 @@ use_guix() export CC=gcc } -use guix --with-debug-info=weechat --with-debug-info=libstrophe gdb +use guix \ + --with-debug-info=weechat\ + --with-debug-info=libstrophe\ + --with-debug-info=libsignal-protocol-c\ + --with-debug-info=rnp\ + clang:extra gdb diff --git a/.gitignore b/.gitignore index 93fe681..0a32016 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .direnv *~ compile_commands.json +.cache cscope* .depend *.d diff --git a/Makefile b/Makefile index 9936944..659dd2d 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,10 @@ ifdef DEBUG endif RM=rm -f FIND=find -INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags libsignal-protocol-c) +INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags librnp-0) $(shell pkg-config --cflags libsignal-protocol-c) CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) -LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs librnp-0) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -23,6 +23,7 @@ SRCS=plugin.c \ input.c \ message.c \ omemo.c \ + pgp.c \ user.c \ util.c \ xmpp/presence.c \ @@ -41,6 +42,7 @@ xmpp.so: $(OBJS) $(DEPS) patchelf --shrink-rpath xmpp.so || true diff/libdiff.a: + git submodule update --init --recursive cd diff && ./configure $(MAKE) -C diff CFLAGS=-fPIC diff: diff/libdiff.a @@ -67,7 +69,6 @@ clean: $(MAKE) -C diff clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true - git submodule update --init --recursive || true distclean: clean $(RM) *~ .depend @@ -86,7 +87,7 @@ endif .PHONY: tags cs tags: - $(CC) $(CFLAGS) -M $(SRCS) | sed -e "s/[\\ ]/\n/g" | sed -e "/^$$/d" -e "/\.o:[ \t]*$$/d" | sort | uniq | ctags -e -L - -f .git/tags -R --c-kinds=+px --c++-kinds=+px --fields=+iaS --extra=+fq + $(CC) $(CFLAGS) -M $(SRCS) | sed -e "s/[\\ ]/\n/g" | sed -e "/^$$/d" -e "/\.o:[ \t]*$$/d" | sort | uniq | ctags -e -L - -f .git/tags -R --c-kinds=+px --c++-kinds=+px --fields=+iaS --extras=+fq cs: cscope -RUbq diff --git a/account.c b/account.c index 453fbe3..664fcf3 100644 --- a/account.c +++ b/account.c @@ -32,6 +32,8 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "autoconnect", "" }, { "resource", "" }, { "status", "probably about to segfault" }, + { "pgp_pubring_path", "${weechat_data_dir}/pubring.gpg" }, + { "pgp_secring_path", "${weechat_data_dir}/secring.gpg" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index 342da5d..038ba61 100644 --- a/account.h +++ b/account.h @@ -17,6 +17,8 @@ enum t_account_option ACCOUNT_OPTION_AUTOCONNECT, ACCOUNT_OPTION_RESOURCE, ACCOUNT_OPTION_STATUS, + ACCOUNT_OPTION_PGP_PUBRING_PATH, + ACCOUNT_OPTION_PGP_SECRING_PATH, ACCOUNT_NUM_OPTIONS, }; @@ -54,6 +56,10 @@ enum t_account_option weechat_config_string(account->options[ACCOUNT_OPTION_RESOURCE]) #define account_status(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_STATUS]) +#define account_pgp_pubring_path(account) \ + weechat_config_string(account->options[ACCOUNT_OPTION_PGP_PUBRING_PATH]) +#define account_pgp_secring_path(account) \ + weechat_config_string(account->options[ACCOUNT_OPTION_PGP_SECRING_PATH]) struct t_device { @@ -86,6 +92,7 @@ struct t_account char *buffer_as_string; struct t_omemo *omemo; + struct t_pgp *pgp; struct t_device *devices; struct t_device *last_device; diff --git a/channel.c b/channel.c index 90c1af8..1efe323 100644 --- a/channel.c +++ b/channel.c @@ -17,6 +17,30 @@ #include "channel.h" #include "input.h" #include "buffer.h" +#include "pgp.h" + +struct t_account *channel__account(struct t_channel *channel) +{ + struct t_account *ptr_account; + struct t_channel *ptr_channel; + + if (!channel) + return NULL; + + for (ptr_account = accounts; ptr_account; + ptr_account = ptr_account->next_account) + { + for (ptr_channel = ptr_account->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + if (ptr_channel == channel) + return ptr_account; + } + } + + /* account not found */ + return NULL; +} struct t_channel *channel__search(struct t_account *account, const char *id) @@ -187,7 +211,7 @@ struct t_channel *channel__new(struct t_account *account, { struct t_channel *new_channel, *ptr_channel; struct t_gui_buffer *ptr_buffer; - struct t_hook *typing_timer; + struct t_hook *typing_timer, *self_typing_timer; if (!account || !id || !name || !name[0]) return NULL; @@ -209,9 +233,14 @@ struct t_channel *channel__new(struct t_account *account, &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->pgp_id = NULL; new_channel->topic.value = NULL; new_channel->topic.creator = NULL; @@ -223,8 +252,11 @@ struct t_channel *channel__new(struct t_account *account, 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->self_typings = NULL; + new_channel->last_self_typing = NULL; new_channel->typings = NULL; new_channel->last_typing = NULL; new_channel->members = NULL; @@ -441,10 +473,11 @@ struct t_channel_typing *channel__typing_search(struct t_channel *channel, return NULL; } -void channel__add_typing(struct t_channel *channel, - struct t_user *user) +int channel__add_typing(struct t_channel *channel, + struct t_user *user) { struct t_channel_typing *new_typing; + int ret = 0; new_typing = channel__typing_search(channel, user->id); if (!new_typing) @@ -460,10 +493,140 @@ void channel__add_typing(struct t_channel *channel, else channel->typings = new_typing; channel->last_typing = new_typing; + + ret = 1; } new_typing->ts = time(NULL); channel__typing_cb(channel, NULL, 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) +{ + 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; + (void) remaining_calls; + + if (!pointer) + return WEECHAT_RC_ERROR; + + channel = (struct t_channel *)pointer; + account = channel__account(channel); + + now = time(NULL); + + for (ptr_typing = channel->self_typings; ptr_typing; + ptr_typing = ptr_typing->next_typing) + { + next_typing = ptr_typing->next_typing; + + while (ptr_typing && 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; + } + + if (!ptr_typing) + break; + } + + return WEECHAT_RC_OK; +} + +struct t_channel_typing *channel__self_typing_search(struct t_channel *channel, + struct t_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) + { + if (user == ptr_typing->user) + return ptr_typing; + } + + return NULL; +} + +int channel__add_self_typing(struct t_channel *channel, + struct t_user *user) +{ + struct t_channel_typing *new_typing; + int ret = 0; + + new_typing = channel__self_typing_search(channel, user); + if (!new_typing) + { + new_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); + + return ret; } void channel__member_free(struct t_channel *channel, @@ -532,8 +695,11 @@ void channel__free(struct t_account *account, /* 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); @@ -542,6 +708,8 @@ void channel__free(struct t_account *account, free(channel->id); if (channel->name) free(channel->name); + if (channel->pgp_id) + free(channel->pgp_id); if (channel->topic.value) free(channel->topic.value); if (channel->topic.creator) @@ -593,6 +761,17 @@ struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel_member *member; struct t_user *user; + user = user__search(account, id); + + if (weechat_strcasecmp(user->id, channel->id) == 0 + && channel->type == CHANNEL_TYPE_MUC) + { + weechat_printf_date_tags(channel->buffer, 0, "log2", "%sMUC: %s", + weechat_prefix("network"), + id); + return NULL; + } + member = malloc(sizeof(struct t_channel_member)); member->id = strdup(id); @@ -607,18 +786,12 @@ struct t_channel_member *channel__add_member(struct t_account *account, channel->members = member; channel->last_member = member; - user = user__search(account, id); 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(user->id, channel->id) == 0 - && channel->type == CHANNEL_TYPE_MUC) - weechat_printf_date_tags(channel->buffer, 0, "log2", "%sMUC: %s", - weechat_prefix("network"), - user->id); - else if (weechat_strcasecmp(jid_bare, channel->id) == 0 + 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 %sentered%s %s %s%s%s", weechat_prefix("join"), @@ -757,6 +930,26 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_message_set_body(message, body); char *url = strstr(body, "http"); + if (channel->pgp_id) + { + 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(account->pgp, channel->pgp_id, body); + if (ciphertext) + xmpp_stanza_set_text(message__x__text, ciphertext); + free(ciphertext); + + xmpp_stanza_add_child(message__x, message__x__text); + xmpp_stanza_release(message__x__text); + + xmpp_stanza_add_child(message, message__x); + xmpp_stanza_release(message__x); + + weechat_printf(channel->buffer, "[~]\t%s%s: PGP", weechat_color("gray"), account_jid(account)); + } if (url) { xmpp_stanza_t *message__x = xmpp_stanza_new(account->context); @@ -787,3 +980,44 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, user__as_prefix_raw(account, account_jid(account)), body); } + +void channel__send_typing(struct t_account *account, struct t_channel *channel, + struct t_user *user) +{ + if (channel__add_self_typing(channel, user)) + { + xmpp_stanza_t *message = xmpp_message_new(account->context, + channel->type == CHANNEL_TYPE_MUC + ? "groupchat" : "chat", + user ? user->id : channel->id, NULL); + + 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_stanza_release(message); + } +} + +void channel__send_paused(struct t_account *account, struct t_channel *channel, + struct t_user *user) +{ + xmpp_stanza_t *message = xmpp_message_new(account->context, + channel->type == CHANNEL_TYPE_MUC + ? "groupchat" : "chat", + user ? user->id : channel->id, NULL); + + 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_stanza_release(message); +} diff --git a/channel.h b/channel.h index 591d87e..4bb4a93 100644 --- a/channel.h +++ b/channel.h @@ -15,7 +15,10 @@ enum t_channel_type struct t_channel_typing { - char *id; + union { + char *id; + struct t_user *user; + }; char *name; time_t ts; @@ -46,6 +49,7 @@ struct t_channel enum t_channel_type type; char *id; char *name; + char *pgp_id; struct t_channel_topic topic; @@ -56,7 +60,10 @@ struct t_channel 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_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; @@ -68,6 +75,8 @@ struct t_channel struct t_channel *next_channel; }; +struct t_account *channel__account(struct t_channel *channel); + struct t_channel *channel__search(struct t_account *account, const char *id); @@ -101,8 +110,23 @@ int channel__typing_cb(const void *pointer, struct t_channel_typing *channel__typing_search(struct t_channel *channel, const char *id); -void channel__add_typing(struct t_channel *channel, - struct t_user *user); +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); void channel__free(struct t_account *account, struct t_channel *channel); @@ -139,4 +163,10 @@ struct t_channel_member *channel__remove_member(struct t_account *account, void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body); +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); + #endif /*WEECHAT_XMPP_CHANNEL_H*/ diff --git a/command.c b/command.c index c40b581..7b2662e 100644 --- a/command.c +++ b/command.c @@ -648,13 +648,55 @@ int command__me(const void *pointer, void *data, weechat_printf_date_tags(ptr_channel->buffer, 0, "xmpp_message,message,action,private,notify_none,self_msg,log1", "%s%s %s", - weechat_prefix("action"), account_jid(ptr_account), + weechat_prefix("action"), + user__as_prefix_raw(ptr_account, account_jid(ptr_account)), strlen(text) > strlen("/me ") ? text+4 : ""); } return WEECHAT_RC_OK; } +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; + xmpp_stanza_t *message; + char *keyid; + + (void) pointer; + (void) data; + (void) argv; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_channel) + { + weechat_printf ( + ptr_account->buffer, + _("%s%s: \"%s\" command can not be executed on a account buffer"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "me"); + return WEECHAT_RC_OK; + } + + if (argc > 1) + { + keyid = argv_eol[1]; + + ptr_channel->pgp_id = strdup(keyid); + } + else + { + ptr_channel->pgp_id = NULL; + } + + return WEECHAT_RC_OK; +} + int command__xml(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) @@ -756,6 +798,15 @@ void command__init() if (!hook) weechat_printf(NULL, "Failed to setup command /me"); + hook = weechat_hook_command( + "pgp", + N_("set the target pgp key for the current channel"), + N_(""), + N_("keyid: recipient keyid"), + NULL, &command__pgp, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /pgp"); + hook = weechat_hook_command( "xml", N_("send a raw xml stanza"), diff --git a/config.c b/config.c index b7e6c66..f468605 100644 --- a/config.c +++ b/config.c @@ -186,6 +186,38 @@ config__account_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; + case ACCOUNT_OPTION_PGP_PUBRING_PATH: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("XMPP Account PGP Public Keyring Path"), + 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_SECRING_PATH: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("XMPP Account PGP Secure Keyring Path"), + 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; } diff --git a/connection.c b/connection.c index eab0cc3..1932c3a 100644 --- a/connection.c +++ b/connection.c @@ -20,6 +20,7 @@ #include "channel.h" #include "connection.h" #include "omemo.h" +#include "pgp.h" #include "util.h" void connection__init() @@ -86,7 +87,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void struct t_user *user; struct t_channel *channel; xmpp_stanza_t *iq__x, *iq__x__item, *iq__c, *iq__status; - const char *from, *from_bare, *role = NULL, *affiliation = NULL, *jid = NULL; + const char *from, *from_bare, *from_res, *role = NULL, *affiliation = NULL, *jid = NULL; const char *node = NULL, *ver = NULL; char *clientid = NULL, *status; @@ -94,6 +95,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void if (from == NULL) return 1; from_bare = xmpp_jid_bare(account->context, from); + from_res = xmpp_jid_resource(account->context, from); iq__x = xmpp_stanza_get_child_by_name_and_ns( stanza, "x", "http://jabber.org/protocol/muc#user"); if (iq__x) @@ -121,15 +123,18 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void iq__status = xmpp_stanza_get_child_by_name(stanza, "status"); status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL; + channel = channel__search(account, from_bare); + if (!iq__x && !channel) + channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + user = user__search(account, from); if (!user) - user = user__new(account, from, from); + user = user__new(account, from, + channel && weechat_strcasecmp(from_bare, channel->id) == 0 + ? from_res : from); - channel = channel__search(account, from_bare); if (!iq__x) { - if (!channel) - channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); channel__add_member(account, channel, from, clientid, status); } else if (channel) @@ -154,9 +159,9 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * struct t_account *account = (struct t_account *)userdata; struct t_channel *channel; - xmpp_stanza_t *body, *delay, *topic, *replace, *composing, *sent, *received, *forwarded; + xmpp_stanza_t *x, *body, *delay, *topic, *replace, *composing, *sent, *received, *forwarded; const char *type, *from, *nick, *from_bare, *to, *to_bare, *id, *replace_id, *timestamp; - char *intext, *difftext = NULL; + char *text, *intext, *difftext = NULL, *cleartext = NULL; struct tm time = {0}; time_t date = 0; @@ -188,14 +193,20 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * 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); if (!channel) return 1; struct t_user *user = user__search(account, from); if (!user) - user = user__new(account, from, from); + user = user__new(account, from, + weechat_strcasecmp(from_bare, channel->id) == 0 + ? nick : from); channel__add_typing(channel, user); - weechat_printf(channel->buffer, "%s typing...", from); + weechat_printf(channel->buffer, "...\t%s%s typing", + weechat_color("gray"), + weechat_strcasecmp(from_bare, channel->id) == 0 + ? nick : from); } sent = xmpp_stanza_get_child_by_name_and_ns( @@ -230,13 +241,24 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * "urn:xmpp:message-correct:0"); replace_id = replace ? xmpp_stanza_get_id(replace) : NULL; + x = xmpp_stanza_get_child_by_name_and_ns(stanza, "x", "jabber:x:encrypted"); intext = xmpp_stanza_get_text(body); + if (x) + { + char *ciphertext = xmpp_stanza_get_text(x); + cleartext = pgp__decrypt(account->pgp, ciphertext); + xmpp_free(account->context, ciphertext); + } + text = cleartext ? cleartext : intext; const char *channel_id = weechat_strcasecmp(account_jid(account), from_bare) == 0 ? to_bare : from_bare; channel = channel__search(account, channel_id); if (!channel) - channel = channel__new(account, CHANNEL_TYPE_PM, channel_id, channel_id); + channel = channel__new(account, + weechat_strcasecmp(type, "groupchat") == 0 + ? CHANNEL_TYPE_MUC : CHANNEL_TYPE_PM, + channel_id, channel_id); if (replace) { const char *orig = NULL; @@ -323,7 +345,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (orig) { struct diff result; - if (diff(&result, char_cmp, 1, orig, strlen(orig), intext, strlen(intext)) > 0) + if (diff(&result, char_cmp, 1, orig, strlen(orig), text, strlen(text)) > 0) { char **visual = weechat_string_dyn_alloc(256); char ch[2] = {0}; @@ -393,7 +415,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (channel->type == CHANNEL_TYPE_PM) weechat_string_dyn_concat(dyn_tags, ",private", -1); - if (weechat_string_match(intext, "/me *", 0)) + if (weechat_string_match(text, "/me *", 0)) weechat_string_dyn_concat(dyn_tags, ",xmpp_action", -1); if (replace) { @@ -404,24 +426,27 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (date != 0) weechat_string_dyn_concat(dyn_tags, ",notify_none", -1); - else if (channel->type == CHANNEL_TYPE_PM) + else if (channel->type == CHANNEL_TYPE_PM + && weechat_strcasecmp(from_bare, account_jid(account)) != 0) weechat_string_dyn_concat(dyn_tags, ",notify_private", -1); else weechat_string_dyn_concat(dyn_tags, ",log1", -1); const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly + if (x && text == cleartext) + weechat_printf(channel->buffer, "[~]\t%s%s: PGP", weechat_color("gray"), nick); if (channel_id == from_bare && strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", edit, user__as_prefix_raw(account, nick), - to, difftext ? difftext : intext ? intext : ""); - else if (weechat_string_match(intext, "/me *", 0)) + 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"), nick, - difftext ? difftext+4 : intext ? intext+4 : ""); + edit, weechat_prefix("action"), user__as_prefix_raw(account, nick), + 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), - difftext ? difftext : intext ? intext : ""); + difftext ? difftext : text ? text : ""); weechat_string_dyn_free(dyn_tags, 1); @@ -429,6 +454,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * xmpp_free(account->context, intext); if (difftext) free(difftext); + if (cleartext) + free(cleartext); return 1; } @@ -1002,6 +1029,13 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); } + + + pgp__init(&account->pgp, + weechat_string_eval_expression(account_pgp_pubring_path(account), + NULL, NULL, NULL), + weechat_string_eval_expression(account_pgp_secring_path(account), + NULL, NULL, NULL)); } else { diff --git a/input.c b/input.c index 323a493..a57ad4b 100644 --- a/input.c +++ b/input.c @@ -54,3 +54,30 @@ int input__data_cb(const void *pointer, void *data, return input__data(buffer, text); } + +int input__typing(struct t_gui_buffer *buffer) +{ + struct t_account *account = NULL; + struct t_channel *channel = NULL; + + buffer__get_account_and_channel(buffer, &account, &channel); + + if (account && account->is_connected && channel) + { + channel__send_typing(account, channel, NULL); + } + + return WEECHAT_RC_OK; +} + +int input__text_changed_cb(const void *pointer, void *data, + const char *signal, const char *type_data, + void *signal_data) +{ + (void) pointer; + (void) data; + (void) signal; + (void) type_data; + + return input__typing(signal_data); +} diff --git a/input.h b/input.h index c218506..50bdd01 100644 --- a/input.h +++ b/input.h @@ -6,7 +6,11 @@ #define _WEECHAT_XMPP_INPUT_H_ int input__data_cb(const void *pointer, void *data, - struct t_gui_buffer *buffer, - const char *input_data); + struct t_gui_buffer *buffer, + const char *input_data); + +int input__text_changed_cb(const void *pointer, void *data, + const char *signal, const char *type_data, + void *signal_data); #endif /*WEECHAT_XMPP_INPUT_H*/ diff --git a/pgp.c b/pgp.c new file mode 100644 index 0000000..7912b3c --- /dev/null +++ b/pgp.c @@ -0,0 +1,360 @@ +// This Source Code Form is subject to the terms of the Mozilla PublicAA +// 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 +#include + +#include "plugin.h" +#include "pgp.h" + +#define RNP_SUCCESS 0 + +#define PGP_MESSAGE_HEADER "-----BEGIN PGP MESSAGE-----\r\n\r\n" +#define PGP_MESSAGE_FOOTER "\r\n-----END PGP MESSAGE-----\r\n" + +const char *PGP_ADVICE = "[PGP encrypted message (XEP-0027)]"; + +void pgp__init(struct t_pgp **pgp, const char *pub, const char *sec) +{ + struct t_pgp *new_pgp; + rnp_input_t keyring; + + new_pgp = calloc(1, sizeof(**pgp)); + + if (rnp_ffi_create(&new_pgp->context, + RNP_KEYSTORE_GPG, RNP_KEYSTORE_GPG) != RNP_SUCCESS) { + return; + } + + if (rnp_input_from_path(&keyring, pub) == RNP_SUCCESS) { + if (rnp_load_keys(new_pgp->context, RNP_KEYSTORE_GPG, + keyring, RNP_LOAD_SAVE_PUBLIC_KEYS) == RNP_SUCCESS) { + rnp_input_destroy(keyring); + } + } + + if (rnp_input_from_path(&keyring, sec) == RNP_SUCCESS) { + if (rnp_load_keys(new_pgp->context, RNP_KEYSTORE_GPG, + keyring, RNP_LOAD_SAVE_SECRET_KEYS) == RNP_SUCCESS) { + rnp_input_destroy(keyring); + } + } + + *pgp = new_pgp; +} + +void pgp__free(struct t_pgp *pgp) +{ + if (pgp) + { + if (pgp->context) + free(pgp->context); + free(pgp); + } +} + +/* this simple helper function just prints armored key, searched by userid, to stdout */ +static bool pgp__print_key(rnp_ffi_t rnp, const char *uid, bool secret) +{ + rnp_output_t keydata = NULL; + rnp_key_handle_t key = NULL; + uint32_t flags = RNP_KEY_EXPORT_ARMORED | RNP_KEY_EXPORT_SUBKEYS; + uint8_t * buf = NULL; + size_t buf_len = 0; + bool result = false; + + /* you may search for the key via userid, keyid, fingerprint, grip */ + if (rnp_locate_key(rnp, "userid", uid, &key) != RNP_SUCCESS) { + return false; + } + + if (!key) { + return false; + } + + /* create in-memory output structure to later use buffer */ + if (rnp_output_to_memory(&keydata, 0) != RNP_SUCCESS) { + goto finish; + } + + flags = flags | (secret ? RNP_KEY_EXPORT_SECRET : RNP_KEY_EXPORT_PUBLIC); + if (rnp_key_export(key, keydata, flags) != RNP_SUCCESS) { + goto finish; + } + + /* get key's contents from the output structure */ + if (rnp_output_memory_get_buf(keydata, &buf, &buf_len, false) != RNP_SUCCESS) { + goto finish; + } + weechat_printf(NULL, "pgp: %.*s", (int) buf_len, buf); + + result = true; +finish: + rnp_key_handle_destroy(key); + rnp_output_destroy(keydata); + return result; +} + +static bool pgp__export_key(rnp_ffi_t rnp, const char *uid, bool secret) +{ + rnp_output_t keyfile = NULL; + rnp_key_handle_t key = NULL; + uint32_t flags = RNP_KEY_EXPORT_ARMORED | RNP_KEY_EXPORT_SUBKEYS; + char filename[32] = {0}; + char * keyid = NULL; + bool result = false; + + /* you may search for the key via userid, keyid, fingerprint, grip */ + if (rnp_locate_key(rnp, "userid", uid, &key) != RNP_SUCCESS) { + return false; + } + + if (!key) { + return false; + } + + /* get key's id and build filename */ + if (rnp_key_get_keyid(key, &keyid) != RNP_SUCCESS) { + goto finish; + } + snprintf(filename, sizeof(filename), "key-%s-%s.asc", keyid, secret ? "sec" : "pub"); + rnp_buffer_destroy(keyid); + + /* create file output structure */ + if (rnp_output_to_path(&keyfile, filename) != RNP_SUCCESS) { + goto finish; + } + + flags = flags | (secret ? RNP_KEY_EXPORT_SECRET : RNP_KEY_EXPORT_PUBLIC); + if (rnp_key_export(key, keyfile, flags) != RNP_SUCCESS) { + goto finish; + } + + result = true; +finish: + rnp_key_handle_destroy(key); + rnp_output_destroy(keyfile); + return result; +} + +char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message) +{ + rnp_op_encrypt_t encrypt = NULL; + rnp_key_handle_t key = NULL; + rnp_input_t keyfile = NULL; + rnp_input_t input = NULL; + rnp_output_t output = NULL; + char * result = NULL; + + rnp_result_t ret; + + /* create memory input and file output objects for the message and encrypted message */ + if ((ret = rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false)) != + RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); + goto encrypt_finish; + } + + if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create output object: %s\n", reason); + goto encrypt_finish; + } + + /* create encryption operation */ + if ((ret = rnp_op_encrypt_create(&encrypt, pgp->context, input, output)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create encrypt operation: %s\n", reason); + goto encrypt_finish; + } + + /* setup encryption parameters */ + rnp_op_encrypt_set_armor(encrypt, true); + rnp_op_encrypt_set_file_name(encrypt, "message.txt"); + rnp_op_encrypt_set_file_mtime(encrypt, time(NULL)); + rnp_op_encrypt_set_compression(encrypt, "ZIP", 6); + rnp_op_encrypt_set_cipher(encrypt, RNP_ALGNAME_AES_256); + rnp_op_encrypt_set_aead(encrypt, "None"); + + /* locate recipient's key and add it to the operation context. */ + if ((ret = rnp_locate_key(pgp->context, "keyid", target, &key)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to locate recipient key: %s\n", reason); + goto encrypt_finish; + } + + if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to add recipient: %s\n", reason); + goto encrypt_finish; + } + rnp_key_handle_destroy(key); + key = NULL; + + /* execute encryption operation */ + if ((ret = rnp_op_encrypt_execute(encrypt)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: encryption failed: %s\n", reason); + goto encrypt_finish; + } + + uint8_t *buf; + size_t buf_len; + + rnp_output_memory_get_buf(output, &buf, &buf_len, false); + result = strndup((char *)buf + strlen(PGP_MESSAGE_HEADER), + buf_len - strlen(PGP_MESSAGE_HEADER) - strlen(PGP_MESSAGE_FOOTER)); +encrypt_finish: + rnp_op_encrypt_destroy(encrypt); + rnp_input_destroy(keyfile); + rnp_input_destroy(input); + rnp_output_destroy(output); + rnp_key_handle_destroy(key); + return result; +} + +//"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_pgp *pgp, const char *ciphertext) +{ + rnp_input_t input = NULL; + rnp_output_t output = NULL; + uint8_t * buf = NULL; + size_t buf_len = 0; + char * result = NULL; + + rnp_result_t ret; + + buf_len = strlen(PGP_MESSAGE_HEADER) + strlen(ciphertext) + strlen(PGP_MESSAGE_FOOTER) + 1; + buf = malloc(sizeof(char) * buf_len); + buf_len = snprintf((char *)buf, buf_len, PGP_MESSAGE_HEADER "%s" PGP_MESSAGE_FOOTER, ciphertext); + + /* create file input and memory output objects for the encrypted message and decrypted + * message */ + if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); + goto decrypt_finish; + } + + if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create output object: %s\n", reason); + goto decrypt_finish; + } + + if ((ret = rnp_decrypt(pgp->context, input, output)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: public-key decryption failed: %s\n", reason); + goto decrypt_finish; + } + free(buf); + + /* get the decrypted message from the output structure */ + if (rnp_output_memory_get_buf(output, &buf, &buf_len, false) != RNP_SUCCESS) { + goto decrypt_finish; + } + + result = strndup((const char *)buf, (int)buf_len); +decrypt_finish: + rnp_input_destroy(input); + rnp_output_destroy(output); + return result; +} + +char *pgp__verify(struct t_pgp *pgp) +{ + rnp_op_verify_t verify = NULL; + rnp_input_t input = NULL; + rnp_output_t output = NULL; + uint8_t * buf = NULL; + size_t buf_len = 0; + size_t sigcount = 0; + char * result = NULL; + + rnp_result_t ret; + + /* create file input and memory output objects for the signed message and verified + * message */ + if ((ret = rnp_input_from_path(&input, "signed.asc")) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to open file 'signed.asc'. Did you run the sign example?: %s\n", reason); + goto verify_finish; + } + + if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create output object: %s\n", reason); + goto verify_finish; + } + + if ((ret = rnp_op_verify_create(&verify, pgp->context, input, output)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to create verification context: %s\n", reason); + goto verify_finish; + } + + if ((ret = rnp_op_verify_execute(verify)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to execute verification operation: %s\n", reason); + goto verify_finish; + } + + /* now check signatures and get some info about them */ + if ((ret = rnp_op_verify_get_signature_count(verify, &sigcount)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to get signature count: %s\n", reason); + goto verify_finish; + } + + for (size_t i = 0; i < sigcount; i++) { + rnp_op_verify_signature_t sig = NULL; + rnp_result_t sigstatus = RNP_SUCCESS; + rnp_key_handle_t key = NULL; + char * keyid = NULL; + + if ((ret = rnp_op_verify_get_signature_at(verify, i, &sig)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to get signature %d: %s\n", (int)i, reason); + goto verify_finish; + } + + if ((ret = rnp_op_verify_signature_get_key(sig, &key)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to get signature's %d key: %s\n", (int)i, reason); + goto verify_finish; + } + + if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(NULL, "pgp: failed to get key id %d: %s\n", (int)i, reason); + rnp_key_handle_destroy(key); + goto verify_finish; + } + + sigstatus = rnp_op_verify_signature_get_status(sig); + weechat_printf(NULL, "pgp: Status for signature from key %s : %d\n", keyid, (int)sigstatus); + result = strdup(keyid); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(key); + } + + /* get the verified message from the output structure */ + if ((ret = rnp_output_memory_get_buf(output, &buf, &buf_len, false)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + (void) reason; + goto verify_finish; + } + weechat_printf(NULL, "pgp: Verified message:\n%.*s\n", (int)buf_len, buf); + +verify_finish: + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + return result; +} diff --git a/pgp.h b/pgp.h new file mode 100644 index 0000000..2beac5a --- /dev/null +++ b/pgp.h @@ -0,0 +1,22 @@ +// 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/. + +#ifndef _WEECHAT_XMPP_PGP_H_ +#define _WEECHAT_XMPP_PGP_H_ + +struct t_pgp +{ + struct rnp_ffi_st *context; + const char *keyid; +}; + +void pgp__init(struct t_pgp **pgp, const char *pub, const char *sec); + +void pgp__free(struct t_pgp *pgp); + +char *pgp__decrypt(struct t_pgp *pgp, const char *ciphertext); + +char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message); + +#endif /*WEECHAT_XMPP_PGP_H*/ diff --git a/plugin.c b/plugin.c index 85ed513..d8668a7 100644 --- a/plugin.c +++ b/plugin.c @@ -13,6 +13,7 @@ #include "account.h" #include "connection.h" #include "command.h" +#include "input.h" #include "buffer.h" #include "completion.h" @@ -64,6 +65,8 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) &buffer__typing_bar_cb, NULL, NULL); + weechat_hook_signal("input_text_changed", &input__text_changed_cb, NULL, NULL); + return WEECHAT_RC_OK; } diff --git a/user.c b/user.c index a219707..6698c50 100644 --- a/user.c +++ b/user.c @@ -140,14 +140,11 @@ struct t_user *user__new(struct t_account *account, { struct t_user *new_user, *ptr_user; - if (!account || !id || !display_name) + if (!account || !id) { return NULL; } - if (!display_name[0] && strcmp("USLACKBOT", id) == 0) - return NULL; - if (!account->users) channel__add_nicklist_groups(account, NULL); @@ -173,23 +170,13 @@ struct t_user *user__new(struct t_account *account, new_user->id = strdup(id); new_user->name = NULL; - new_user->team_id = NULL; - new_user->real_name = NULL; - new_user->colour = NULL; - new_user->deleted = 0; - - new_user->tz = NULL; - new_user->tz_label = NULL; - new_user->tz_offset = 0; - new_user->locale = NULL; new_user->profile.avatar_hash = NULL; new_user->profile.status_text = NULL; new_user->profile.status_emoji = NULL; new_user->profile.real_name = NULL; - new_user->profile.display_name = display_name[0] ? - strdup(display_name) : - strdup("???"); + new_user->profile.display_name = display_name ? + strdup(display_name) : strdup(""); new_user->profile.real_name_normalized = NULL; new_user->profile.email = NULL; new_user->profile.team = NULL; @@ -197,16 +184,6 @@ struct t_user *user__new(struct t_account *account, new_user->updated = 0; new_user->is_away = 0; - new_user->is_admin = 0; - new_user->is_owner = 0; - new_user->is_primary_owner = 0; - new_user->is_restricted = 0; - new_user->is_ultra_restricted = 0; - new_user->is_bot = 0; - new_user->is_stranger = 0; - new_user->is_app_user = 0; - new_user->has_2fa = 0; - user__nicklist_add(account, NULL, new_user); return new_user; @@ -239,18 +216,6 @@ void user__free(struct t_account *account, free(user->id); if (user->name) free(user->name); - if (user->team_id) - free(user->team_id); - if (user->real_name) - free(user->real_name); - if (user->colour) - free(user->colour); - if (user->tz) - free(user->tz); - if (user->tz_label) - free(user->tz_label); - if (user->locale) - free(user->locale); if (user->profile.avatar_hash) free(user->profile.avatar_hash); if (user->profile.status_text) diff --git a/user.h b/user.h index f90e535..30c6440 100644 --- a/user.h +++ b/user.h @@ -22,30 +22,11 @@ struct t_user { char *id; char *name; - char *team_id; - char *real_name; - char *colour; - - int deleted; - char *tz; - char *tz_label; - int tz_offset; - char *locale; struct t_user_profile profile; int updated; int is_away; - int is_admin; - int is_owner; - int is_primary_owner; - int is_restricted; - int is_ultra_restricted; - int is_bot; - int is_stranger; - int is_app_user; - int has_2fa; - struct t_user *prev_user; struct t_user *next_user; }; From e13b46ce0f7d6333d4cf7949c96d0f7b6b2d4fb6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 22 Jul 2021 06:27:39 +0100 Subject: [PATCH 111/118] pgp automation --- .dir-locals.el | 2 +- connection.c | 26 +++++++--- pgp.c | 136 ++++++++++--------------------------------------- pgp.h | 2 + 4 files changed, 48 insertions(+), 118 deletions(-) diff --git a/.dir-locals.el b/.dir-locals.el index 178235e..211b59a 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -19,4 +19,4 @@ (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) (flycheck-clang-language-standard . "gnu99") (flycheck-checker . c/c++-clang) - (projectile-project-compilation-cmd . "scan-build-3.8 make -j8"))) + (projectile-project-compilation-cmd . "bear -- make -j8"))) diff --git a/connection.c b/connection.c index 1932c3a..1675a6c 100644 --- a/connection.c +++ b/connection.c @@ -86,9 +86,9 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void struct t_account *account = (struct t_account *)userdata; struct t_user *user; struct t_channel *channel; - xmpp_stanza_t *iq__x, *iq__x__item, *iq__c, *iq__status; + xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *iq__x__item, *iq__c, *iq__status; const char *from, *from_bare, *from_res, *role = NULL, *affiliation = NULL, *jid = NULL; - const char *node = NULL, *ver = NULL; + const char *certificate = NULL, *node = NULL, *ver = NULL; char *clientid = NULL, *status; from = xmpp_stanza_get_from(stanza); @@ -96,11 +96,17 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void return 1; from_bare = xmpp_jid_bare(account->context, from); from_res = xmpp_jid_resource(account->context, from); - iq__x = xmpp_stanza_get_child_by_name_and_ns( + iq__x_signed = xmpp_stanza_get_child_by_name_and_ns( + stanza, "x", "jabber:x:signed"); + if (iq__x_signed) + { + certificate = xmpp_stanza_get_text(iq__x_signed); + } + iq__x_muc_user = xmpp_stanza_get_child_by_name_and_ns( stanza, "x", "http://jabber.org/protocol/muc#user"); - if (iq__x) + if (iq__x_muc_user) { - iq__x__item = xmpp_stanza_get_child_by_name(iq__x, "item"); + iq__x__item = xmpp_stanza_get_child_by_name(iq__x_muc_user, "item"); role = xmpp_stanza_get_attribute(iq__x__item, "role"); affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation"); jid = xmpp_stanza_get_attribute(iq__x__item, "jid"); @@ -124,8 +130,14 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL; channel = channel__search(account, from_bare); - if (!iq__x && !channel) + if (!iq__x_muc_user && !channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + if (certificate) + { + channel->pgp_id = pgp__verify(account->pgp, certificate); + weechat_printf(channel->buffer, "[PGP]\t%sKey %s from %s", + weechat_color("gray"), channel->pgp_id, from); + } user = user__search(account, from); if (!user) @@ -133,7 +145,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void channel && weechat_strcasecmp(from_bare, channel->id) == 0 ? from_res : from); - if (!iq__x) + if (!iq__x_muc_user) { channel__add_member(account, channel, from, clientid, status); } diff --git a/pgp.c b/pgp.c index 7912b3c..fe8b2d3 100644 --- a/pgp.c +++ b/pgp.c @@ -16,6 +16,8 @@ #define PGP_MESSAGE_HEADER "-----BEGIN PGP MESSAGE-----\r\n\r\n" #define PGP_MESSAGE_FOOTER "\r\n-----END PGP MESSAGE-----\r\n" +#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----\r\n\r\n" +#define PGP_SIGNATURE_FOOTER "\r\n-----END PGP SIGNATURE-----\r\n" const char *PGP_ADVICE = "[PGP encrypted message (XEP-0027)]"; @@ -58,90 +60,6 @@ void pgp__free(struct t_pgp *pgp) } } -/* this simple helper function just prints armored key, searched by userid, to stdout */ -static bool pgp__print_key(rnp_ffi_t rnp, const char *uid, bool secret) -{ - rnp_output_t keydata = NULL; - rnp_key_handle_t key = NULL; - uint32_t flags = RNP_KEY_EXPORT_ARMORED | RNP_KEY_EXPORT_SUBKEYS; - uint8_t * buf = NULL; - size_t buf_len = 0; - bool result = false; - - /* you may search for the key via userid, keyid, fingerprint, grip */ - if (rnp_locate_key(rnp, "userid", uid, &key) != RNP_SUCCESS) { - return false; - } - - if (!key) { - return false; - } - - /* create in-memory output structure to later use buffer */ - if (rnp_output_to_memory(&keydata, 0) != RNP_SUCCESS) { - goto finish; - } - - flags = flags | (secret ? RNP_KEY_EXPORT_SECRET : RNP_KEY_EXPORT_PUBLIC); - if (rnp_key_export(key, keydata, flags) != RNP_SUCCESS) { - goto finish; - } - - /* get key's contents from the output structure */ - if (rnp_output_memory_get_buf(keydata, &buf, &buf_len, false) != RNP_SUCCESS) { - goto finish; - } - weechat_printf(NULL, "pgp: %.*s", (int) buf_len, buf); - - result = true; -finish: - rnp_key_handle_destroy(key); - rnp_output_destroy(keydata); - return result; -} - -static bool pgp__export_key(rnp_ffi_t rnp, const char *uid, bool secret) -{ - rnp_output_t keyfile = NULL; - rnp_key_handle_t key = NULL; - uint32_t flags = RNP_KEY_EXPORT_ARMORED | RNP_KEY_EXPORT_SUBKEYS; - char filename[32] = {0}; - char * keyid = NULL; - bool result = false; - - /* you may search for the key via userid, keyid, fingerprint, grip */ - if (rnp_locate_key(rnp, "userid", uid, &key) != RNP_SUCCESS) { - return false; - } - - if (!key) { - return false; - } - - /* get key's id and build filename */ - if (rnp_key_get_keyid(key, &keyid) != RNP_SUCCESS) { - goto finish; - } - snprintf(filename, sizeof(filename), "key-%s-%s.asc", keyid, secret ? "sec" : "pub"); - rnp_buffer_destroy(keyid); - - /* create file output structure */ - if (rnp_output_to_path(&keyfile, filename) != RNP_SUCCESS) { - goto finish; - } - - flags = flags | (secret ? RNP_KEY_EXPORT_SECRET : RNP_KEY_EXPORT_PUBLIC); - if (rnp_key_export(key, keyfile, flags) != RNP_SUCCESS) { - goto finish; - } - - result = true; -finish: - rnp_key_handle_destroy(key); - rnp_output_destroy(keyfile); - return result; -} - char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message) { rnp_op_encrypt_t encrypt = NULL; @@ -267,11 +185,11 @@ decrypt_finish: return result; } -char *pgp__verify(struct t_pgp *pgp) +char *pgp__verify(struct t_pgp *pgp, const char *certificate) { rnp_op_verify_t verify = NULL; rnp_input_t input = NULL; - rnp_output_t output = NULL; + rnp_input_t signature = NULL; uint8_t * buf = NULL; size_t buf_len = 0; size_t sigcount = 0; @@ -279,31 +197,38 @@ char *pgp__verify(struct t_pgp *pgp) rnp_result_t ret; - /* create file input and memory output objects for the signed message and verified - * message */ - if ((ret = rnp_input_from_path(&input, "signed.asc")) != RNP_SUCCESS) { + buf_len = strlen(PGP_SIGNATURE_HEADER) + strlen(certificate) + strlen(PGP_SIGNATURE_FOOTER) + 1; + buf = malloc(sizeof(char) * buf_len); + buf_len = snprintf((char *)buf, buf_len, PGP_SIGNATURE_HEADER "%s" PGP_SIGNATURE_FOOTER, certificate); + + /* create file input memory objects for the signed message and verified message */ + if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to open file 'signed.asc'. Did you run the sign example?: %s\n", reason); + weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); goto verify_finish; } - if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { + if ((ret = rnp_input_from_memory(&signature, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create output object: %s\n", reason); + weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); goto verify_finish; } - if ((ret = rnp_op_verify_create(&verify, pgp->context, input, output)) != RNP_SUCCESS) { + if ((ret = rnp_op_verify_detached_create(&verify, pgp->context, input, signature)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); weechat_printf(NULL, "pgp: failed to create verification context: %s\n", reason); goto verify_finish; } - if ((ret = rnp_op_verify_execute(verify)) != RNP_SUCCESS) { - const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to execute verification operation: %s\n", reason); - goto verify_finish; - } + //if (( + ret = rnp_op_verify_execute(verify) + ; + // ) != RNP_ERROR_SIGNATURE_INVALID) + // if (ret != RNP_ERROR_SIGNATURE_INVALID) { + // const char *reason = rnp_result_to_string(ret); + // weechat_printf(NULL, "pgp: failed to execute verification operation: %s\n", reason); + // goto verify_finish; + // } /* now check signatures and get some info about them */ if ((ret = rnp_op_verify_get_signature_count(verify, &sigcount)) != RNP_SUCCESS) { @@ -314,7 +239,6 @@ char *pgp__verify(struct t_pgp *pgp) for (size_t i = 0; i < sigcount; i++) { rnp_op_verify_signature_t sig = NULL; - rnp_result_t sigstatus = RNP_SUCCESS; rnp_key_handle_t key = NULL; char * keyid = NULL; @@ -337,24 +261,16 @@ char *pgp__verify(struct t_pgp *pgp) goto verify_finish; } - sigstatus = rnp_op_verify_signature_get_status(sig); - weechat_printf(NULL, "pgp: Status for signature from key %s : %d\n", keyid, (int)sigstatus); + result = strdup(keyid); rnp_buffer_destroy(keyid); rnp_key_handle_destroy(key); + break; } - /* get the verified message from the output structure */ - if ((ret = rnp_output_memory_get_buf(output, &buf, &buf_len, false)) != RNP_SUCCESS) { - const char *reason = rnp_result_to_string(ret); - (void) reason; - goto verify_finish; - } - weechat_printf(NULL, "pgp: Verified message:\n%.*s\n", (int)buf_len, buf); - verify_finish: rnp_op_verify_destroy(verify); rnp_input_destroy(input); - rnp_output_destroy(output); + rnp_input_destroy(signature); return result; } diff --git a/pgp.h b/pgp.h index 2beac5a..d4942f1 100644 --- a/pgp.h +++ b/pgp.h @@ -19,4 +19,6 @@ char *pgp__decrypt(struct t_pgp *pgp, const char *ciphertext); char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message); +char *pgp__verify(struct t_pgp *pgp, const char *certificate); + #endif /*WEECHAT_XMPP_PGP_H*/ From 0322e7d20a366dde391057c36d339cfc86b3c18b Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 22 Jul 2021 06:53:36 +0100 Subject: [PATCH 112/118] pgp instrumentation --- channel.c | 2 +- connection.c | 21 +++++++++++---------- pgp.c | 50 ++++++++++++++++++++++++++++++-------------------- pgp.h | 6 +++--- 4 files changed, 45 insertions(+), 34 deletions(-) diff --git a/channel.c b/channel.c index 1efe323..49eb4ab 100644 --- a/channel.c +++ b/channel.c @@ -937,7 +937,7 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_set_ns(message__x, "jabber:x:encrypted"); xmpp_stanza_t *message__x__text = xmpp_stanza_new(account->context); - char *ciphertext = pgp__encrypt(account->pgp, channel->pgp_id, body); + char *ciphertext = pgp__encrypt(channel->buffer, account->pgp, channel->pgp_id, body); if (ciphertext) xmpp_stanza_set_text(message__x__text, ciphertext); free(ciphertext); diff --git a/connection.c b/connection.c index 1675a6c..99dbae6 100644 --- a/connection.c +++ b/connection.c @@ -134,7 +134,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); if (certificate) { - channel->pgp_id = pgp__verify(account->pgp, certificate); + channel->pgp_id = pgp__verify(channel->buffer, account->pgp, certificate); weechat_printf(channel->buffer, "[PGP]\t%sKey %s from %s", weechat_color("gray"), channel->pgp_id, from); } @@ -253,24 +253,25 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * "urn:xmpp:message-correct:0"); replace_id = replace ? xmpp_stanza_get_id(replace) : NULL; + const char *channel_id = weechat_strcasecmp(account_jid(account), from_bare) + == 0 ? to_bare : from_bare; + channel = channel__search(account, channel_id); + if (!channel) + channel = channel__new(account, + weechat_strcasecmp(type, "groupchat") == 0 + ? CHANNEL_TYPE_MUC : CHANNEL_TYPE_PM, + channel_id, channel_id); + x = xmpp_stanza_get_child_by_name_and_ns(stanza, "x", "jabber:x:encrypted"); intext = xmpp_stanza_get_text(body); if (x) { char *ciphertext = xmpp_stanza_get_text(x); - cleartext = pgp__decrypt(account->pgp, ciphertext); + cleartext = pgp__decrypt(channel->buffer, account->pgp, ciphertext); xmpp_free(account->context, ciphertext); } text = cleartext ? cleartext : intext; - const char *channel_id = weechat_strcasecmp(account_jid(account), from_bare) - == 0 ? to_bare : from_bare; - channel = channel__search(account, channel_id); - if (!channel) - channel = channel__new(account, - weechat_strcasecmp(type, "groupchat") == 0 - ? CHANNEL_TYPE_MUC : CHANNEL_TYPE_PM, - channel_id, channel_id); if (replace) { const char *orig = NULL; diff --git a/pgp.c b/pgp.c index fe8b2d3..22f3e7b 100644 --- a/pgp.c +++ b/pgp.c @@ -60,7 +60,7 @@ void pgp__free(struct t_pgp *pgp) } } -char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message) +char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *target, const char *message) { rnp_op_encrypt_t encrypt = NULL; rnp_key_handle_t key = NULL; @@ -75,20 +75,20 @@ char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message) if ((ret = rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); goto encrypt_finish; } if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create output object: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create output object: %s\n", reason); goto encrypt_finish; } /* create encryption operation */ if ((ret = rnp_op_encrypt_create(&encrypt, pgp->context, input, output)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create encrypt operation: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create encrypt operation: %s\n", reason); goto encrypt_finish; } @@ -103,13 +103,13 @@ char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message) /* locate recipient's key and add it to the operation context. */ if ((ret = rnp_locate_key(pgp->context, "keyid", target, &key)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to locate recipient key: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to locate recipient key: %s\n", reason); goto encrypt_finish; } if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to add recipient: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to add recipient: %s\n", reason); goto encrypt_finish; } rnp_key_handle_destroy(key); @@ -118,7 +118,7 @@ char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message) /* execute encryption operation */ if ((ret = rnp_op_encrypt_execute(encrypt)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: encryption failed: %s\n", reason); + weechat_printf(buffer, "[PGP]\tencryption failed: %s\n", reason); goto encrypt_finish; } @@ -138,7 +138,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_pgp *pgp, const char *ciphertext) +char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ciphertext) { rnp_input_t input = NULL; rnp_output_t output = NULL; @@ -156,19 +156,19 @@ char *pgp__decrypt(struct t_pgp *pgp, const char *ciphertext) * message */ if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); goto decrypt_finish; } if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create output object: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create output object: %s\n", reason); goto decrypt_finish; } if ((ret = rnp_decrypt(pgp->context, input, output)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: public-key decryption failed: %s\n", reason); + weechat_printf(buffer, "[PGP]\tpublic-key decryption failed: %s\n", reason); goto decrypt_finish; } free(buf); @@ -185,7 +185,7 @@ decrypt_finish: return result; } -char *pgp__verify(struct t_pgp *pgp, const char *certificate) +char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate) { rnp_op_verify_t verify = NULL; rnp_input_t input = NULL; @@ -204,19 +204,19 @@ char *pgp__verify(struct t_pgp *pgp, const char *certificate) /* create file input memory objects for the signed message and verified message */ if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); goto verify_finish; } if ((ret = rnp_input_from_memory(&signature, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create input object: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); goto verify_finish; } if ((ret = rnp_op_verify_detached_create(&verify, pgp->context, input, signature)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to create verification context: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to create verification context: %s\n", reason); goto verify_finish; } @@ -226,14 +226,14 @@ char *pgp__verify(struct t_pgp *pgp, const char *certificate) // ) != RNP_ERROR_SIGNATURE_INVALID) // if (ret != RNP_ERROR_SIGNATURE_INVALID) { // const char *reason = rnp_result_to_string(ret); - // weechat_printf(NULL, "pgp: failed to execute verification operation: %s\n", reason); + // weechat_printf(buffer, "[PGP]\tfailed to execute verification operation: %s\n", reason); // goto verify_finish; // } /* now check signatures and get some info about them */ if ((ret = rnp_op_verify_get_signature_count(verify, &sigcount)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to get signature count: %s\n", reason); + weechat_printf(buffer, "[PGP]\tfailed to get signature count: %s\n", reason); goto verify_finish; } @@ -244,23 +244,33 @@ char *pgp__verify(struct t_pgp *pgp, const char *certificate) if ((ret = rnp_op_verify_get_signature_at(verify, i, &sig)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to get signature %d: %s\n", (int)i, reason); + weechat_printf(buffer, "[PGP]\tfailed to get signature %d: %s\n", (int)i, reason); goto verify_finish; } if ((ret = rnp_op_verify_signature_get_key(sig, &key)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to get signature's %d key: %s\n", (int)i, reason); + weechat_printf(buffer, "[PGP]\tfailed to get signature's %d key: %s\n", (int)i, reason); goto verify_finish; } if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(NULL, "pgp: failed to get key id %d: %s\n", (int)i, reason); + weechat_printf(buffer, "[PGP]\tfailed to get key id %d: %s\n", (int)i, reason); rnp_key_handle_destroy(key); goto verify_finish; } + rnp_signature_handle_t signature = NULL; + if ((ret = rnp_key_get_signature_at(key, 0, &signature)) == RNP_SUCCESS) { + if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason); + rnp_key_handle_destroy(key); + goto verify_finish; + } + rnp_signature_handle_destroy(signature); + } result = strdup(keyid); rnp_buffer_destroy(keyid); diff --git a/pgp.h b/pgp.h index d4942f1..e5d84c8 100644 --- a/pgp.h +++ b/pgp.h @@ -15,10 +15,10 @@ void pgp__init(struct t_pgp **pgp, const char *pub, const char *sec); void pgp__free(struct t_pgp *pgp); -char *pgp__decrypt(struct t_pgp *pgp, const char *ciphertext); +char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ciphertext); -char *pgp__encrypt(struct t_pgp *pgp, const char *target, const char *message); +char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *target, const char *message); -char *pgp__verify(struct t_pgp *pgp, const char *certificate); +char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate); #endif /*WEECHAT_XMPP_PGP_H*/ From a384787413050703726d5f7430d761268a832555 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 22 Jul 2021 06:58:45 +0100 Subject: [PATCH 113/118] pgp deredundancy --- channel.c | 2 ++ omemo.h | 2 ++ pgp.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/channel.c b/channel.c index 49eb4ab..ab918ab 100644 --- a/channel.c +++ b/channel.c @@ -948,6 +948,8 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_add_child(message, message__x); xmpp_stanza_release(message__x); + xmpp_message_set_body(message, PGP_ADVICE); + weechat_printf(channel->buffer, "[~]\t%s%s: PGP", weechat_color("gray"), account_jid(account)); } if (url) diff --git a/omemo.h b/omemo.h index 3138849..2ce48fa 100644 --- a/omemo.h +++ b/omemo.h @@ -5,6 +5,8 @@ #ifndef _WEECHAT_XMPP_OMEMO_H_ #define _WEECHAT_XMPP_OMEMO_H_ +extern const char *OMEMO_ADVICE; + struct t_identity { uint8_t *key; diff --git a/pgp.h b/pgp.h index e5d84c8..d1bd996 100644 --- a/pgp.h +++ b/pgp.h @@ -5,6 +5,8 @@ #ifndef _WEECHAT_XMPP_PGP_H_ #define _WEECHAT_XMPP_PGP_H_ +extern const char *PGP_ADVICE; + struct t_pgp { struct rnp_ffi_st *context; From 6d6d1555747d126a1563d5068c5448a419342c5f Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 22 Jul 2021 07:48:57 +0100 Subject: [PATCH 114/118] pgp presence --- README.org | 7 ++++- account.c | 1 + account.h | 3 ++ command.c | 1 - config.c | 16 +++++++++++ connection.c | 37 ++++++++++++++++++------- pgp.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pgp.h | 2 ++ 8 files changed, 133 insertions(+), 12 deletions(-) diff --git a/README.org b/README.org index 8b95555..d1ab7a2 100644 --- a/README.org +++ b/README.org @@ -136,7 +136,12 @@ * [ ] Delete bookmarks * [ ] Roster * [ ] OTR (libotr) - * [ ] PGP (libgpgme) + * [X] PGP (rnpgp) + * [X] Use keyrings (e.g. exported from gnupg) + * [X] Presence + * [X] Decryption + * [X] Encryption + * [X] Custom set/clear key (/pgp) * [ ] Room Explorer (https://search.jabber.network/docs/api) ** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) diff --git a/account.c b/account.c index 664fcf3..cb437e9 100644 --- a/account.c +++ b/account.c @@ -34,6 +34,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "status", "probably about to segfault" }, { "pgp_pubring_path", "${weechat_data_dir}/pubring.gpg" }, { "pgp_secring_path", "${weechat_data_dir}/secring.gpg" }, + { "pgp_keyid", "" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index 038ba61..b66a20a 100644 --- a/account.h +++ b/account.h @@ -19,6 +19,7 @@ enum t_account_option ACCOUNT_OPTION_STATUS, ACCOUNT_OPTION_PGP_PUBRING_PATH, ACCOUNT_OPTION_PGP_SECRING_PATH, + ACCOUNT_OPTION_PGP_KEYID, ACCOUNT_NUM_OPTIONS, }; @@ -60,6 +61,8 @@ enum t_account_option weechat_config_string(account->options[ACCOUNT_OPTION_PGP_PUBRING_PATH]) #define account_pgp_secring_path(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_PGP_SECRING_PATH]) +#define account_pgp_keyid(account) \ + weechat_config_string(account->options[ACCOUNT_OPTION_PGP_KEYID]) struct t_device { diff --git a/command.c b/command.c index 7b2662e..2b60858 100644 --- a/command.c +++ b/command.c @@ -662,7 +662,6 @@ int command__pgp(const void *pointer, void *data, { struct t_account *ptr_account = NULL; struct t_channel *ptr_channel = NULL; - xmpp_stanza_t *message; char *keyid; (void) pointer; diff --git a/config.c b/config.c index f468605..0686d10 100644 --- a/config.c +++ b/config.c @@ -218,6 +218,22 @@ config__account_new_option (struct t_config_file *config_file, 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; } diff --git a/connection.c b/connection.c index 99dbae6..34146f0 100644 --- a/connection.c +++ b/connection.c @@ -908,7 +908,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, if (status == XMPP_CONN_CONNECT) { - xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, **children; + xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, + *pres__x, *pres__x__text, **children; char cap_hash[28+1] = {0}; xmpp_handler_add(conn, &connection__version_handler, @@ -922,8 +923,14 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_handler_add(conn, &connection__iq_handler, NULL, "iq", NULL, account); + pgp__init(&account->pgp, + weechat_string_eval_expression(account_pgp_pubring_path(account), + NULL, NULL, NULL), + weechat_string_eval_expression(account_pgp_secring_path(account), + NULL, NULL, NULL)); + /* Send initial so that we appear online to contacts */ - children = malloc(sizeof(*children) * (2 + 1)); + children = malloc(sizeof(*children) * (3 + 1)); pres__c = xmpp_stanza_new(account->context); xmpp_stanza_set_name(pres__c, "c"); @@ -943,8 +950,25 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_stanza_release(pres__status__text); children[1] = pres__status; - children[2] = NULL; + + if (account->pgp) + { + 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)); + xmpp_stanza_set_text(pres__x__text, signature ? signature : ""); + free(signature); + xmpp_stanza_add_child(pres__x, pres__x__text); + xmpp_stanza_release(pres__x__text); + + children[2] = pres__x; + children[3] = NULL; + } + pres = stanza__presence(account->context, NULL, children, NULL, strdup(account_jid(account)), NULL, NULL); @@ -1042,13 +1066,6 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); } - - - pgp__init(&account->pgp, - weechat_string_eval_expression(account_pgp_pubring_path(account), - NULL, NULL, NULL), - weechat_string_eval_expression(account_pgp_secring_path(account), - NULL, NULL, NULL)); } else { diff --git a/pgp.c b/pgp.c index 22f3e7b..dc1c65c 100644 --- a/pgp.c +++ b/pgp.c @@ -284,3 +284,81 @@ verify_finish: rnp_input_destroy(signature); return result; } + +char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message) +{ + rnp_input_t keyfile = NULL; + rnp_input_t input = NULL; + rnp_output_t output = NULL; + rnp_op_sign_t sign = NULL; + rnp_key_handle_t key = NULL; + uint8_t * buf = NULL; + size_t buf_len = 0; + char * result = NULL; + + /* create file input and memory output objects for the encrypted message and decrypted + * message */ + if (rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false) != + RNP_SUCCESS) { + weechat_printf(buffer, "[PGP]\tfailed to create input object\n"); + goto sign_finish; + } + + if (rnp_output_to_memory(&output, 0) != RNP_SUCCESS) { + weechat_printf(buffer, "[PGP]\tfailed to create output object\n"); + goto sign_finish; + } + + /* initialize and configure sign operation */ + if (rnp_op_sign_detached_create(&sign, pgp->context, input, output) != RNP_SUCCESS) { + weechat_printf(buffer, "[PGP]\tfailed to create sign operation\n"); + goto sign_finish; + } + + /* armor, file name, compression */ + rnp_op_sign_set_armor(sign, true); + rnp_op_sign_set_file_name(sign, "message.txt"); + rnp_op_sign_set_file_mtime(sign, time(NULL)); + rnp_op_sign_set_compression(sign, "ZIP", 6); + /* signatures creation time - by default will be set to the current time as well */ + rnp_op_sign_set_creation_time(sign, time(NULL)); + /* signatures expiration time - by default will be 0, i.e. never expire */ + rnp_op_sign_set_expiration_time(sign, 365 * 24 * 60 * 60); + /* set hash algorithm - should be compatible for all signatures */ + rnp_op_sign_set_hash(sign, RNP_ALGNAME_SHA256); + + /* now add signatures. First locate the signing key, then add and setup signature */ + if (rnp_locate_key(pgp->context, "keyid", source, &key) != RNP_SUCCESS) { + weechat_printf(buffer, "[PGP]\tfailed to locate signing key: %s\n", source); + goto sign_finish; + } + + if (rnp_op_sign_add_signature(sign, key, NULL) != RNP_SUCCESS) { + weechat_printf(buffer, "[PGP]\tfailed to add signature for key: %s\n", source); + goto sign_finish; + } + + rnp_key_handle_destroy(key); + key = NULL; + + /* finally do signing */ + if (rnp_op_sign_execute(sign) != RNP_SUCCESS) { + weechat_printf(buffer, "[PGP]\tfailed to sign with key: %s\n", source); + goto sign_finish; + } + + /* get the signature from the output structure */ + if (rnp_output_memory_get_buf(output, &buf, &buf_len, false) != RNP_SUCCESS) { + goto sign_finish; + } + + result = strndup((char *)buf + strlen(PGP_SIGNATURE_HEADER), + buf_len - strlen(PGP_SIGNATURE_HEADER) - strlen(PGP_SIGNATURE_FOOTER)); +sign_finish: + rnp_input_destroy(keyfile); + rnp_key_handle_destroy(key); + rnp_op_sign_destroy(sign); + rnp_input_destroy(input); + rnp_output_destroy(output); + return result; +} diff --git a/pgp.h b/pgp.h index d1bd996..ab73475 100644 --- a/pgp.h +++ b/pgp.h @@ -23,4 +23,6 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate); +char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message); + #endif /*WEECHAT_XMPP_PGP_H*/ From b2f38c49016051f1a5efff47c11e37efe491382d Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 25 Jul 2021 09:15:12 +0100 Subject: [PATCH 115/118] see readme --- Makefile | 2 +- NOTES.md | 145 ++++++++++++++ README.org | 20 +- account.c | 12 +- account.h | 16 +- channel.c | 250 ++++++++++++++++++++++++- channel.h | 30 +++ completion.c | 2 +- connection.c | 123 ++++++++++-- input.c | 1 + omemo.c | 520 +++++++++++++++++++++++++++++++++++++++++++-------- omemo.h | 9 +- pgp.c | 37 ++-- user.c | 2 +- util.c | 35 ++++ util.h | 4 + 16 files changed, 1073 insertions(+), 135 deletions(-) create mode 100644 NOTES.md diff --git a/Makefile b/Makefile index 659dd2d..60f4fe1 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ endif RM=rm -f FIND=find INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags librnp-0) $(shell pkg-config --cflags libsignal-protocol-c) -CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) +CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -gdwarf-4 -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs librnp-0) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt diff --git a/NOTES.md b/NOTES.md new file mode 100644 index 0000000..45daedf --- /dev/null +++ b/NOTES.md @@ -0,0 +1,145 @@ +✗: No support +⧗: Planned support +✓: Partial support +?: Supported, but status not specified +✓: Complete support +🕇: Removed support +☠: Client will never support this XEP ++-------------------------------------------------------------------------+------------------------+---------------+------+-------+----------+-------+--------+-------+ +| XEP | Bruno the Jabber™ Bear | Conversations | Dino | Gajim | Monal IM | Movim | Poezio | yaxim | ++-------------------------------------------------------------------------+------------------------+---------------+------+-------+----------+-------+--------+-------+ +| 0004: Data Forms(Final) | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | +| 0012: Last Activity(Final) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | +| 0027: Current Jabber OpenPGP Usage(Obsolete) | ✗ | ✓ | ✓ | ✓ | ☠ | ✗ | ✓ | ✗ | +| 0030: Service Discovery(Final) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0033: Extended Stanza Addressing(Draft) | ✗ | ✗ | ✗ | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0045: Multi-User Chat(Draft) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0047: In-Band Bytestreams(Final) | ✗ | ✗ | ? | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0048: Bookmarks(Deprecated) | ✓ | ✓ | ? | ✓ | ⧗ | ✓ | ✓ | ✓ | +| 0049: Private XML Storage(Active) | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | +| 0050: Ad-Hoc Commands(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0054: vcard-temp(Active) | ✗ | ✓ | ✓ | ✓ | ☠ | ✓ | ✓ | ✗ | +| 0055: Jabber Search(Active) | ✗ | ✗ | ✗ | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0059: Result Set Management(Draft) | ✗ | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ | ✗ | +| 0060: Publish-Subscribe(Draft) | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | +| 0065: SOCKS5 Bytestreams(Draft) | ✗ | ✗ | ✗ | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0066: Out of Band Data(Draft) | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | +| 0070: Verifying HTTP Requests via XMPP(Draft) | ✗ | ✗ | ✗ | ✓ | ☠ | ✓ | ✓ | ✗ | +| 0071: XHTML-IM(Deprecated) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0077: In-Band Registration(Final) | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0080: User Location(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0082: XMPP Date and Time Profiles(Active) | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0083: Nested Roster Groups(Active) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0084: User Avatar(Draft) | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | +| 0085: Chat State Notifications(Final) | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | +| 0091: Legacy Delayed Delivery(Obsolete) | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| 0092: Software Version(Draft) | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0095: Stream Initiation(Deprecated) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0100: Gateway Interaction(Active) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0106: JID Escaping(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0107: User Mood(Draft) | ✗ | ✗ | ✗ | ✓ | ☠ | ✓ | ✓ | ✗ | +| 0108: User Activity(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0115: Entity Capabilities(Draft) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0118: User Tune(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0144: Roster Item Exchange(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0145: Annotations(Active) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0146: Remote Controlling Clients(Obsolete) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0147: XMPP URI Scheme Query Components(Active) | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | +| 0153: vCard-Based Avatars(Active) | ✗ | ✓ | ? | ✓ | ☠ | ✓ | ✓ | ✗ | +| 0156: Discovering Alternative XMPP Connection Methods(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0157: Contact Addresses for XMPP Services(Active) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0158: CAPTCHA Forms(Draft) | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | +| 0162: Best Practices for Roster and Subscription Management(Deferred) | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | +| 0163: Personal Eventing Protocol(Draft) | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | +| 0166: Jingle(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0167: Jingle RTP Sessions(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0172: User Nickname(Draft) | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0174: Serverless Messaging(Final) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0175: Best Practices for Use of SASL ANONYMOUS(Active) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | +| 0176: Jingle ICE-UDP Transport Method(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0178: Best Practices for Use of SASL EXTERNAL with Certificates(Active) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | +| 0184: Message Delivery Receipts(Draft) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0191: Blocking Command(Draft) | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ | ✗ | +| 0196: User Gaming(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | +| 0198: Stream Management(Draft) | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | +| 0199: XMPP Ping(Final) | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | +| 0200: Stanza Encryption(Deferred) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0202: Entity Time(Final) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | +| 0203: Delayed Delivery(Final) | ✓ | ✗ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | +| 0209: Metacontacts(Deferred) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0215: External Service Discovery(Deferred) | ✗ | ✓ | ? | ✗ | ⧗ | ✓ | ✗ | ✗ | +| 0221: Data Forms Media Element(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0222: Persistent Storage of Public Data via PubSub(Active) | ✗ | ✗ | ? | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0223: Persistent Storage of Private Data via PubSub(Active) | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | +| 0224: Attention(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | +| 0231: Bits of Binary(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0234: Jingle File Transfer(Deferred) | ✗ | ✓ | ? | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0237: Roster Versioning(Obsolete) | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | +| 0245: The /me Command(Active) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0249: Direct MUC Invitations(Draft) | ✓ | ✓ | ? | ✓ | ⧗ | ✗ | ✓ | ✓ | +| 0256: Last Activity in Presence(Draft) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0257: Client Certificate Management for SASL EXTERNAL(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | +| 0258: Security Labels in XMPP(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0260: Jingle SOCKS5 Bytestreams Transport Method(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0261: Jingle In-Band Bytestreams Transport Method(Draft) | ✗ | ✓ | ✓ | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0277: Microblogging over XMPP(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0280: Message Carbons(Experimental) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0284: Shared XML Editing(Deferred) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0286: Mobile Considerations on LTE Networks(Active) | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | +| 0292: vCard4 Over XMPP(Deferred) | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ | +| 0293: Jingle RTP Feedback Negotiation(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0294: Jingle RTP Header Extensions Negotiation(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0296: Best Practices for Resource Locking(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | +| 0297: Stanza Forwarding(Draft) | ✓ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | ✓ | +| 0300: Use of Cryptographic Hash Functions in XMPP(Draft) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0306: Extensible Status Conditions for Multi-User Chat(Deferred) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0308: Last Message Correction(Draft) | ✓ | ✓ | ? | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0313: Message Archive Management(Experimental) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0319: Last User Interaction in Presence(Draft) | ✗ | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ | +| 0320: Use of DTLS-SRTP in Jingle Sessions(Draft) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0330: Pubsub Subscription(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0333: Chat Markers(Deferred) | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | +| 0334: Message Processing Hints(Deferred) | ✗ | ✗ | ? | ✓ | ✗ | ✓ | ✓ | ✗ | +| 0338: Jingle Grouping Framework(Draft) | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0339: Source-Specific Media Attributes in Jingle(Draft) | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0343: Signaling WebRTC datachannels in Jingle(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0352: Client State Indication(Draft) | ✓ | ✓ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ | +| 0353: Jingle Message Initiation(Deferred) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0357: Push Notifications(Deferred) | ✓ | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | +| 0359: Unique and Stable Stanza IDs(Deferred) | ✓ | ✗ | ? | ✓ | ✗ | ✓ | ✗ | ✓ | +| 0363: HTTP File Upload(Draft) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 0364: Current Off-the-Record Messaging Usage(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | +| 0367: Message Attaching(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0368: SRV records for XMPP over TLS(Draft) | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | +| 0369: Mediated Information eXchange (MIX)(Experimental) | ✗ | ✗ | ✗ | ✗ | ⧗ | ✗ | ✗ | ✗ | +| 0372: References(Experimental) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0373: OpenPGP for XMPP(Experimental) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0374: OpenPGP for XMPP Instant Messaging(Deferred) | ✗ | ✗ | ✗ | ✗ | ⧗ | ✗ | ✗ | ✗ | +| 0377: Spam Reporting(Experimental) | ✗ | ✓ | ✗ | ✓ | ☠ | ✗ | ✗ | ✗ | +| 0378: OTR Discovery(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | +| 0379: Pre-Authenticated Roster Subscription(Deferred) | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | +| 0380: Explicit Message Encryption(Deferred) | ✗ | ✗ | ✓ | ✓ | ⧗ | ✓ | ✓ | ✗ | +| 0384: OMEMO Encryption(Experimental) | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ | ✗ | +| 0385: Stateless Inline Media Sharing (SIMS)(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0386: Bind 2.0(Deferred) | ✗ | ✗ | ✗ | ✗ | ☠ | ✗ | ✗ | ✗ | +| 0390: Entity Capabilities 2.0(Deferred) | ✗ | ✗ | ✗ | ✗ | ☠ | ✗ | ✗ | ✗ | +| 0391: Jingle Encrypted Transports(Deferred) | ✗ | ✓ | ? | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0392: Consistent Color Generation(Deferred) | ✓ | ✓ | ✗ | ✓ | ⧗ | ✗ | ✓ | ✓ | +| 0393: Message Styling(Draft) | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | +| 0396: Jingle Encrypted Transports - OMEMO(Deferred) | ✗ | ✓ | ✗ | ✗ | ☠ | ✗ | ✗ | ✗ | +| 0397: Instant Stream Resumption(Deferred) | ✗ | ✗ | ✗ | ✗ | ☠ | ✗ | ✗ | ✗ | +| 0398: User Avatar to vCard-Based Avatars Conversion(Deferred) | ✗ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0401: Easy User Onboarding(Deferred) | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | +| 0402: PEP Native Bookmarks(Draft) | ✗ | ✗ | ✗ | ✗ | ⧗ | ✓ | ✗ | ✗ | +| 0409: IM Routing-NG(Deferred) | ✗ | ✗ | ✗ | ✗ | ☠ | ✗ | ✗ | ✗ | +| 0410: MUC Self-Ping (Schrödinger's Chat)(Draft) | ✓ | ✓ | ? | ✗ | ☠ | ✗ | ✗ | ✓ | +| 0411: Bookmarks Conversion(Draft) | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | +| 0420: Stanza Content Encryption(Experimental) | ✗ | ✗ | ✗ | ✗ | ☠ | ✗ | ✗ | ✗ | +| 0422: Message Fastening(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0423: XMPP Compliance Suites 2020(Obsolete) | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | +| 0424: Message Retraction(Deferred) | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | +| 0441: Message Archive Management Preferences(Experimental) | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | +| 0447: Stateless file sharing(Experimental) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0449: Stickers(Experimental) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +| 0454: OMEMO Media sharing(Experimental) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ++-------------------------------------------------------------------------+------------------------+---------------+------+-------+----------+-------+--------+-------+ diff --git a/README.org b/README.org index d1ab7a2..1a2959e 100644 --- a/README.org +++ b/README.org @@ -28,6 +28,8 @@ A weechat plugin in C to extend the chat client to support XMPP and a currently minimal but ideally maximal set of XEPs. + I'm gonna rewrite this in C++ at some point when I have a feel + for the full behaviour of an average client. * Usage @@ -44,9 +46,8 @@ - libstrophe (dynamic, dependency) - libxml2 (dynamic, dependency) - - glib (dynamic, dependency of libomemo) - - sqlite (dynamic, dependency of libomemo/axc) - - libsignal-protocol-c (dynamic, dependency of axc) + - libsignal-protocol-c (dynamic, dependency) + - rnp (dynamic, dependency) - weechat (>= v3.0) .. or just use the guix spec in .envrc @@ -125,11 +126,14 @@ * [ ] Announce * [ ] Messages * [ ] [#C] MUC PMs - * [ ] [#A] Send typing notifications - * [ ] [#A] Recv typing notifications - * [ ] [#C] Read receipts - * [ ] Message Carbons + * [X] [#A] Send typing notifications + * [X] [#A] Recv typing notifications + * [X] [#C] Read receipts + * [X] Chat Markers (XEP-0333) + * [X] Message Delivery (XEP-0184) + * [X] Message Carbons * [ ] Service Disco + * [X] MAM Fetching * [-] Bookmarks / Roster * [X] Autojoin bookmarks * [ ] Add bookmarks @@ -142,10 +146,10 @@ * [X] Decryption * [X] Encryption * [X] Custom set/clear key (/pgp) + * [ ] OOB data and media * [ ] Room Explorer (https://search.jabber.network/docs/api) ** TODO [#C] Implement completion engine (milestone v0.3) ** TODO [#D] Close all issues (milestone v1.0) - * [ ] Absorb libomemo / axc, and drop glib * Contributing diff --git a/account.c b/account.c index cb437e9..3e4a213 100644 --- a/account.c +++ b/account.c @@ -90,9 +90,9 @@ int account__search_option(const char *option_name) return -1; } -struct t_device *account__search_device(struct t_account *account, int id) +struct t_account_device *account__search_device(struct t_account *account, int id) { - struct t_device *ptr_device; + struct t_account_device *ptr_device; if (!account) return NULL; @@ -108,9 +108,9 @@ struct t_device *account__search_device(struct t_account *account, int id) } void account__add_device(struct t_account *account, - struct t_device *device) + struct t_account_device *device) { - struct t_device *new_device; + struct t_account_device *new_device; new_device = account__search_device(account, device->id); if (!new_device) @@ -129,9 +129,9 @@ void account__add_device(struct t_account *account, } } -void account__free_device(struct t_account *account, struct t_device *device) +void account__free_device(struct t_account *account, struct t_account_device *device) { - struct t_device *new_devices; + struct t_account_device *new_devices; if (!account || !device) return; diff --git a/account.h b/account.h index b66a20a..575996f 100644 --- a/account.h +++ b/account.h @@ -64,13 +64,13 @@ enum t_account_option #define account_pgp_keyid(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_PGP_KEYID]) -struct t_device +struct t_account_device { int id; char *name; - struct t_device *prev_device; - struct t_device *next_device; + struct t_account_device *prev_device; + struct t_account_device *next_device; }; struct t_account @@ -97,8 +97,8 @@ struct t_account struct t_omemo *omemo; struct t_pgp *pgp; - struct t_device *devices; - struct t_device *last_device; + struct t_account_device *devices; + struct t_account_device *last_device; struct t_user *users; struct t_user *last_user; struct t_channel *channels; @@ -113,9 +113,9 @@ 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_device *account__search_device(struct t_account *account, int id); -void account__add_device(struct t_account *account, struct t_device *device); -void account__free_device(struct t_account *account, struct t_device *device); +struct t_account_device *account__search_device(struct t_account *account, int 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); struct t_account *account__alloc(const char *name); void account__free_data(struct t_account *account); diff --git a/channel.c b/channel.c index ab918ab..4932079 100644 --- a/channel.c +++ b/channel.c @@ -19,6 +19,21 @@ #include "buffer.h" #include "pgp.h" +const char *channel__transport_name(enum t_channel_transport transport) +{ + switch (transport) + { + case CHANNEL_TRANSPORT_PLAINTEXT: + return "PLAINTEXT"; + case CHANNEL_TRANSPORT_OMEMO: + return "OMEMO"; + case CHANNEL_TRANSPORT_PGP: + return "PGP"; + default: + return NULL; + } +} + struct t_account *channel__account(struct t_channel *channel) { struct t_account *ptr_account; @@ -158,6 +173,7 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, account_nickname(account)); weechat_buffer_set(ptr_buffer, "localvar_set_server", account->name); weechat_buffer_set(ptr_buffer, "localvar_set_channel", name); + weechat_buffer_set(ptr_buffer, "input_multiline", "1"); if (buffer_created) { @@ -240,6 +256,7 @@ struct t_channel *channel__new(struct t_account *account, new_channel->type = type; new_channel->id = strdup(id); new_channel->name = strdup(name); + new_channel->transport = CHANNEL_TRANSPORT_PLAINTEXT; new_channel->pgp_id = NULL; new_channel->topic.value = NULL; @@ -255,6 +272,7 @@ struct t_channel *channel__new(struct t_account *account, 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; @@ -272,6 +290,15 @@ struct t_channel *channel__new(struct t_account *account, account->channels = new_channel; account->last_channel = new_channel; + if (type != CHANNEL_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, &start, NULL); + } + return new_channel; } @@ -356,7 +383,7 @@ void channel__member_speaking_rename_if_present(struct t_account *account, list_size = weechat_list_size(channel->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(channel->members_speaking[i], j); if (ptr_item && (weechat_strcasecmp(weechat_list_string(ptr_item), nick) == 0)) weechat_list_set(ptr_item, nick); @@ -629,6 +656,41 @@ int channel__add_self_typing(struct t_channel *channel, 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 = 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) { @@ -702,6 +764,7 @@ void channel__free(struct t_account *account, 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) @@ -923,10 +986,17 @@ struct t_channel_member *channel__remove_member(struct t_account *account, void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body) { + channel__send_reads(account, channel); + xmpp_stanza_t *message = xmpp_message_new(account->context, channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", to, NULL); + + char *id = xmpp_uuid_gen(account->context); + xmpp_stanza_set_id(message, id); + xmpp_free(account->context, id); + xmpp_message_set_body(message, body); char *url = strstr(body, "http"); @@ -950,8 +1020,22 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_message_set_body(message, PGP_ADVICE); - weechat_printf(channel->buffer, "[~]\t%s%s: PGP", weechat_color("gray"), account_jid(account)); + if (ciphertext && channel->transport != CHANNEL_TRANSPORT_PGP) + { + channel->transport = CHANNEL_TRANSPORT_PGP; + weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s", + weechat_prefix("network"), weechat_color("gray"), + channel__transport_name(channel->transport)); + } + } + else if (channel->transport != CHANNEL_TRANSPORT_PLAINTEXT) + { + channel->transport = CHANNEL_TRANSPORT_PLAINTEXT; + weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s", + weechat_prefix("network"), weechat_color("gray"), + channel__transport_name(channel->transport)); } + if (url) { xmpp_stanza_t *message__x = xmpp_stanza_new(account->context); @@ -983,6 +1067,55 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, body); } +void channel__send_reads(struct t_account *account, struct t_channel *channel) +{ + 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 = weechat_list_user_data(ptr_item); + + xmpp_stanza_t *message = xmpp_message_new(account->context, NULL, + channel->id, NULL); + + 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__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__thread); + xmpp_stanza_release(message__thread); + } + + xmpp_stanza_add_child(message, message__displayed); + xmpp_stanza_release(message__displayed); + + xmpp_send(account->connection, message); + xmpp_stanza_release(message); + + channel__unread_free(unread); + + weechat_list_remove(channel->unreads, ptr_item); + } + } + } +} + void channel__send_typing(struct t_account *account, struct t_channel *channel, struct t_user *user) { @@ -1023,3 +1156,116 @@ void channel__send_paused(struct t_account *account, struct t_channel *channel, xmpp_send(account->connection, message); xmpp_stanza_release(message); } + +void channel__fetch_mam(struct t_account *account, struct t_channel *channel, + time_t *start, time_t *end) +{ + xmpp_stanza_t *iq = xmpp_iq_new(account->context, "set", "juliet1"); + + 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_set_name(x, "x"); + xmpp_stanza_set_ns(x, "jabber:x:data"); + xmpp_stanza_set_attribute(x, "type", "result"); + + xmpp_stanza_t *field, *value, *text; + + { + 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); + xmpp_stanza_set_name(value, "value"); + + 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); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + { + 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); + xmpp_stanza_set_name(value, "value"); + + text = xmpp_stanza_new(account->context); + xmpp_stanza_set_text(text, channel->id); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + if (start) + { + 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); + xmpp_stanza_set_name(value, "value"); + + 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); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + if (end) + { + 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); + xmpp_stanza_set_name(value, "value"); + + 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); + xmpp_stanza_add_child(value, text); + xmpp_stanza_release(text); + + xmpp_stanza_add_child(field, value); + xmpp_stanza_release(value); + + xmpp_stanza_add_child(x, field); + xmpp_stanza_release(field); + } + + xmpp_stanza_add_child(query, x); + xmpp_stanza_release(x); + + xmpp_stanza_add_child(iq, query); + xmpp_stanza_release(query); + + xmpp_send(account->connection, iq); + xmpp_stanza_release(iq); +} diff --git a/channel.h b/channel.h index 4bb4a93..52d799d 100644 --- a/channel.h +++ b/channel.h @@ -13,6 +13,13 @@ enum t_channel_type CHANNEL_TYPE_PM, }; +enum t_channel_transport +{ + CHANNEL_TRANSPORT_PLAINTEXT, + CHANNEL_TRANSPORT_OMEMO, + CHANNEL_TRANSPORT_PGP, +}; + struct t_channel_typing { union { @@ -44,11 +51,18 @@ struct t_channel_topic 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; char *pgp_id; struct t_channel_topic topic; @@ -62,6 +76,7 @@ struct t_channel 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; @@ -75,6 +90,8 @@ struct t_channel struct t_channel *next_channel; }; +const char *channel__transport_name(enum t_channel_transport transport); + struct t_account *channel__account(struct t_channel *channel); struct t_channel *channel__search(struct t_account *account, @@ -128,6 +145,14 @@ struct t_channel_typing *channel__self_typing_search(struct t_channel *channel, 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); @@ -163,10 +188,15 @@ struct t_channel_member *channel__remove_member(struct t_account *account, void 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, + time_t *start, time_t *end); + #endif /*WEECHAT_XMPP_CHANNEL_H*/ diff --git a/completion.c b/completion.c index 7a98152..9fb976a 100644 --- a/completion.c +++ b/completion.c @@ -30,7 +30,7 @@ void completion__channel_nicks_add_speakers(struct t_gui_completion *completion, list_size = weechat_list_size(channel->members_speaking[highlight]); for (i = 0; i < list_size; i++) { - member = weechat_list_string ( + member = weechat_list_string( weechat_list_get(channel->members_speaking[highlight], i)); if (member) { diff --git a/connection.c b/connection.c index 34146f0..e3a6c39 100644 --- a/connection.c +++ b/connection.c @@ -87,7 +87,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void struct t_user *user; struct t_channel *channel; xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *iq__x__item, *iq__c, *iq__status; - const char *from, *from_bare, *from_res, *role = NULL, *affiliation = NULL, *jid = NULL; + const char *from, *from_bare, *from_res, *type, *role = NULL, *affiliation = NULL, *jid = NULL; const char *certificate = NULL, *node = NULL, *ver = NULL; char *clientid = NULL, *status; @@ -96,6 +96,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void return 1; from_bare = xmpp_jid_bare(account->context, from); from_res = xmpp_jid_resource(account->context, from); + type = xmpp_stanza_get_type(stanza); iq__x_signed = xmpp_stanza_get_child_by_name_and_ns( stanza, "x", "jabber:x:signed"); if (iq__x_signed) @@ -130,11 +131,12 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL; channel = channel__search(account, from_bare); - if (!iq__x_muc_user && !channel) + if (weechat_strcasecmp(type, "unavailable") && !iq__x_muc_user && !channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - if (certificate) + if (certificate && channel) { - channel->pgp_id = pgp__verify(channel->buffer, account->pgp, certificate); + if (channel->type != CHANNEL_TYPE_MUC) + channel->pgp_id = pgp__verify(channel->buffer, account->pgp, certificate); weechat_printf(channel->buffer, "[PGP]\t%sKey %s from %s", weechat_color("gray"), channel->pgp_id, from); } @@ -145,7 +147,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void channel && weechat_strcasecmp(from_bare, channel->id) == 0 ? from_res : from); - if (!iq__x_muc_user) + if (!iq__x_muc_user && channel) { channel__add_member(account, channel, from, clientid, status); } @@ -171,8 +173,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * struct t_account *account = (struct t_account *)userdata; struct t_channel *channel; - xmpp_stanza_t *x, *body, *delay, *topic, *replace, *composing, *sent, *received, *forwarded; - const char *type, *from, *nick, *from_bare, *to, *to_bare, *id, *replace_id, *timestamp; + xmpp_stanza_t *x, *body, *delay, *topic, *replace, *request, *markable, *composing, *sent, *received, *result, *forwarded; + 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; @@ -237,6 +239,29 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * return connection__message_handler(conn, message, userdata); } + result = xmpp_stanza_get_child_by_name_and_ns( + stanza, "result", "urn:xmpp:mam:2"); + if (result) + { + forwarded = xmpp_stanza_get_child_by_name_and_ns( + result, "forwarded", "urn:xmpp:forward:0"); + if (forwarded != NULL) + { + xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, "message"); + if (message) + { + message = xmpp_stanza_copy(message); + delay = xmpp_stanza_get_child_by_name_and_ns( + 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); + xmpp_stanza_release(message); + return ret; + } + } + } + return 1; } type = xmpp_stanza_get_type(stanza); @@ -247,11 +272,18 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * return 1; 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; id = xmpp_stanza_get_id(stanza); + thread = xmpp_stanza_get_attribute(stanza, "thread"); replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", "urn:xmpp:message-correct:0"); replace_id = replace ? xmpp_stanza_get_id(replace) : NULL; + request = xmpp_stanza_get_child_by_name_and_ns(stanza, "request", + "urn:xmpp:receipts"); + 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; @@ -262,6 +294,59 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * ? CHANNEL_TYPE_MUC : CHANNEL_TYPE_PM, channel_id, channel_id); + if (id && (markable || request)) + { + struct t_channel_unread *unread = malloc(sizeof(struct t_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); + + if (request) + { + 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); + + xmpp_stanza_add_child(message, message__received); + xmpp_stanza_release(message__received); + } + + if (markable) + { + 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); + + xmpp_stanza_add_child(message, message__received); + xmpp_stanza_release(message__received); + } + + if (unread->thread) + { + 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_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__thread); + xmpp_stanza_release(message__thread); + } + + 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); + } + x = xmpp_stanza_get_child_by_name_and_ns(stanza, "x", "jabber:x:encrypted"); intext = xmpp_stanza_get_text(body); if (x) @@ -446,8 +531,20 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * weechat_string_dyn_concat(dyn_tags, ",log1", -1); const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly - if (x && text == cleartext) - weechat_printf(channel->buffer, "[~]\t%s%s: PGP", weechat_color("gray"), nick); + if (x && text == cleartext && channel->transport != CHANNEL_TRANSPORT_PGP) + { + channel->transport = 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)); + } + else if (!x && text == intext && channel->transport != CHANNEL_TRANSPORT_PLAINTEXT) + { + channel->transport = CHANNEL_TRANSPORT_PLAINTEXT; + weechat_printf_date_tags(channel->buffer, date, NULL, "%s%sTransport: %s", + weechat_prefix("network"), weechat_color("gray"), + channel__transport_name(channel->transport)); + } if (channel_id == from_bare && strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", edit, user__as_prefix_raw(account, nick), @@ -726,7 +823,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd { account__free_device_all(account); - struct t_device *dev = malloc(sizeof(dev)); + struct t_account_device *dev = malloc(sizeof(struct t_account_device)); char id[64] = {0}; dev->id = account->omemo->device_id; @@ -751,7 +848,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd device_id = xmpp_stanza_get_id(device); - dev = malloc(sizeof(dev)); + dev = malloc(sizeof(struct t_account_device)); dev->id = atoi(device_id); dev->name = strdup(device_id); account__add_device(account, dev); @@ -1032,12 +1129,12 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, uint8_t identity[128] = {0}; if (b64_id && *b64_id) weechat_string_base_decode(64, b64_id, (char*)identity); - struct t_identity id_key = { + struct t_omemo_identity id_key = { .key = identity, .length = 4, }; - omemo__init(&account->omemo, dev_id, b64_id && *b64_id ? &id_key : NULL); + omemo__init(account->buffer, &account->omemo, dev_id, b64_id && *b64_id ? &id_key : NULL); char account_id[64] = {0}; snprintf(account_id, sizeof(account_id), "%d", account->omemo->device_id); diff --git a/input.c b/input.c index a57ad4b..dc9fd6f 100644 --- a/input.c +++ b/input.c @@ -64,6 +64,7 @@ int input__typing(struct t_gui_buffer *buffer) if (account && account->is_connected && channel) { + channel__send_reads(account, channel); channel__send_typing(account, channel, NULL); } diff --git a/omemo.c b/omemo.c index c8e7795..0c10673 100644 --- a/omemo.c +++ b/omemo.c @@ -7,108 +7,472 @@ #include #include #include +#include +#include +#include +#include "plugin.h" +#include "account.h" #include "omemo.h" -/* -char *omemo__signal_init() -{ - signal_protocol_store_context *store_context_p = NULL; - - signal_protocol_session_store session_store = { - .load_session_func = &axc_db_session_load, - .get_sub_device_sessions_func = &axc_db_session_get_sub_device_sessions, - .store_session_func = &axc_db_session_store, - .contains_session_func = &axc_db_session_contains, - .delete_session_func = &axc_db_session_delete, - .delete_all_sessions_func = &axc_db_session_delete_all, - .destroy_func = &axc_db_session_destroy_store_ctx, - .user_data = ctx_p - }; - signal_protocol_pre_key_store pre_key_store = { - .load_pre_key = &axc_db_pre_key_load, - .store_pre_key = &axc_db_pre_key_store, - .contains_pre_key = &axc_db_pre_key_contains, - .remove_pre_key = &axc_db_pre_key_remove, - .destroy_func = &axc_db_pre_key_destroy_ctx, - .user_data = ctx_p - }; - signal_protocol_signed_pre_key_store signed_pre_key_store = { - .load_signed_pre_key = &axc_db_signed_pre_key_load, - .store_signed_pre_key = &axc_db_signed_pre_key_store, - .contains_signed_pre_key = &axc_db_signed_pre_key_contains, - .remove_signed_pre_key = &axc_db_signed_pre_key_remove, - .destroy_func = &axc_db_signed_pre_key_destroy_ctx, - .user_data = ctx_p - }; - signal_protocol_identity_key_store identity_key_store = { - .get_identity_key_pair = &axc_db_identity_get_key_pair, - .get_local_registration_id = &axc_db_identity_get_local_registration_id, - .save_identity = &axc_db_identity_save, - .is_trusted_identity = &axc_db_identity_always_trusted, - .destroy_func = &axc_db_identity_destroy_ctx, - .user_data = ctx_p - }; +const char *OMEMO_ADVICE = "[OMEMO encrypted message (XEP-0384)]"; - if (signal_context_create(&(ctx_p->axolotl_global_context_p), ctx_p)) { - return "failed to create global axolotl context"; - } - - signal_crypto_provider crypto_provider = { - .random_func = random_bytes, - .hmac_sha256_init_func = hmac_sha256_init, - .hmac_sha256_update_func = hmac_sha256_update, - .hmac_sha256_final_func = hmac_sha256_final, - .sha512_digest_init_func = sha512_digest_init, - .sha512_digest_update_func = sha512_digest_update, - .sha512_digest_final_func = sha512_digest_final, - .encrypt_func = aes_encrypt, - .decrypt_func = aes_decrypt, - .user_data = ctx_p - }; - if (signal_context_set_crypto_provider(ctx_p->axolotl_global_context_p, &crypto_provider)) { - return "failed to set crypto provider"; +signal_type_base* signal_type_ref_vapi(void* instance) { + if (!(instance != NULL)) + return NULL; + signal_type_ref(instance); + return instance; +} + +signal_type_base* signal_type_unref_vapi(void* instance) { + if (!(instance != NULL)) + return NULL; + signal_type_unref(instance); + return NULL; +} + +void signal_protocol_address_free(signal_protocol_address* ptr) { + if (!(ptr != NULL)) + return; + if (ptr->name) { + free((void*)ptr->name); + } + return free(ptr); +} + +void signal_protocol_address_set_name(signal_protocol_address* self, const char* name) { + if (!(self != NULL)) + return; + if (!(name != NULL)) + return; + char* n = malloc(strlen(name)+1); + memcpy(n, name, strlen(name)); + n[strlen(name)] = 0; + if (self->name) { + free((void*)self->name); + } + self->name = n; + self->name_len = strlen(n); +} + +char* signal_protocol_address_get_name(signal_protocol_address* self) { + if (!(self != NULL)) + return NULL; + if (!(self->name != NULL)) + return 0; + char* res = malloc(sizeof(char) * (self->name_len + 1)); + memcpy(res, self->name, self->name_len); + res[self->name_len] = 0; + return res; +} + +int32_t signal_protocol_address_get_device_id(signal_protocol_address* self) { + if (!(self != NULL)) + return -1; + return self->device_id; +} + +void signal_protocol_address_set_device_id(signal_protocol_address* self, int32_t device_id) { + if (!(self != NULL)) + return; + self->device_id = device_id; +} + +signal_protocol_address* signal_protocol_address_new(const char* name, int32_t device_id) { + if (!(name != NULL)) + return NULL; + signal_protocol_address* address = malloc(sizeof(signal_protocol_address)); + address->device_id = -1; + address->name = NULL; + signal_protocol_address_set_name(address, name); + signal_protocol_address_set_device_id(address, device_id); + return address; +} + +int signal_randomize(uint8_t *data, size_t len) { + gcry_randomize(data, len, GCRY_STRONG_RANDOM); + return SG_SUCCESS; +} + +int signal_random_generator(uint8_t *data, size_t len, void *user_data) { + (void) user_data; + + gcry_randomize(data, len, GCRY_STRONG_RANDOM); + return SG_SUCCESS; +} + +int signal_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data) { + (void) user_data; + + gcry_mac_hd_t* ctx = malloc(sizeof(gcry_mac_hd_t)); + if (!ctx) return SG_ERR_NOMEM; + + if (gcry_mac_open(ctx, GCRY_MAC_HMAC_SHA256, 0, 0)) { + free(ctx); + return SG_ERR_UNKNOWN; + } + + if (gcry_mac_setkey(*ctx, key, key_len)) { + free(ctx); + return SG_ERR_UNKNOWN; + } + + *hmac_context = ctx; + + return SG_SUCCESS; +} + +int signal_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data) { + (void) user_data; + + gcry_mac_hd_t* ctx = hmac_context; + + if (gcry_mac_write(*ctx, data, data_len)) return SG_ERR_UNKNOWN; + + return SG_SUCCESS; +} + +int signal_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data) { + (void) user_data; + + size_t len = gcry_mac_get_algo_maclen(GCRY_MAC_HMAC_SHA256); + uint8_t md[len]; + gcry_mac_hd_t* ctx = hmac_context; + + if (gcry_mac_read(*ctx, md, &len)) return SG_ERR_UNKNOWN; + + signal_buffer *output_buffer = signal_buffer_create(md, len); + if (!output_buffer) return SG_ERR_NOMEM; + + *output = output_buffer; + + return SG_SUCCESS; +} + +void signal_hmac_sha256_cleanup(void *hmac_context, void *user_data) { + (void) user_data; + + gcry_mac_hd_t* ctx = hmac_context; + if (ctx) { + gcry_mac_close(*ctx); + free(ctx); + } +} + +int signal_sha512_digest_init(void **digest_context, void *user_data) { + (void) user_data; + + gcry_md_hd_t* ctx = malloc(sizeof(gcry_mac_hd_t)); + if (!ctx) return SG_ERR_NOMEM; + + if (gcry_md_open(ctx, GCRY_MD_SHA512, 0)) { + free(ctx); + return SG_ERR_UNKNOWN; + } + + *digest_context = ctx; + + return SG_SUCCESS; +} + +int signal_sha512_digest_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data) { + (void) user_data; + + gcry_md_hd_t* ctx = digest_context; + + gcry_md_write(*ctx, data, data_len); + + return SG_SUCCESS; +} + +int signal_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data) { + (void) user_data; + + size_t len = gcry_md_get_algo_dlen(GCRY_MD_SHA512); + gcry_md_hd_t* ctx = digest_context; + + uint8_t* md = gcry_md_read(*ctx, GCRY_MD_SHA512); + if (!md) return SG_ERR_UNKNOWN; + + gcry_md_reset(*ctx); + + signal_buffer *output_buffer = signal_buffer_create(md, len); + free(md); + if (!output_buffer) return SG_ERR_NOMEM; + + *output = output_buffer; + + return SG_SUCCESS; +} + +void signal_sha512_digest_cleanup(void *digest_context, void *user_data) { + (void) user_data; + + gcry_md_hd_t* ctx = digest_context; + if (ctx) { + gcry_md_close(*ctx); + free(ctx); + } +} + +int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) { + switch (key_len) { + case 16: + *algo = GCRY_CIPHER_AES128; + break; + case 24: + *algo = GCRY_CIPHER_AES192; + break; + case 32: + *algo = GCRY_CIPHER_AES256; + break; + default: + return SG_ERR_UNKNOWN; + } + switch (cipher) { + case SG_CIPHER_AES_CBC_PKCS5: + *mode = GCRY_CIPHER_MODE_CBC; + break; + case SG_CIPHER_AES_CTR_NOPADDING: + *mode = GCRY_CIPHER_MODE_CTR; + break; + default: + return SG_ERR_UNKNOWN; + } + return SG_SUCCESS; +} + +int signal_encrypt(signal_buffer **output, + int cipher, + const uint8_t *key, size_t key_len, + const uint8_t *iv, size_t iv_len, + const uint8_t *plaintext, size_t plaintext_len, + void *user_data) { + (void) user_data; + + int algo, mode, error_code = SG_ERR_UNKNOWN; + if (aes_cipher(cipher, key_len, &algo, &mode)) return SG_ERR_INVAL; + + gcry_cipher_hd_t ctx = {0}; + + if (gcry_cipher_open(&ctx, algo, mode, 0)) return SG_ERR_NOMEM; + + signal_buffer* padded = 0; + signal_buffer* out_buf = 0; + goto no_error; +error: + gcry_cipher_close(ctx); + if (padded != 0) { + signal_buffer_bzero_free(padded); + } + if (out_buf != 0) { + signal_buffer_free(out_buf); } + return error_code; +no_error: - if (signal_context_set_locking_functions(ctx_p->axolotl_global_context_p, recursive_mutex_lock, recursive_mutex_unlock)) { - return "failed to set locking functions"; + if (gcry_cipher_setkey(ctx, key, key_len)) goto error; + + uint8_t tag_len = 0, pad_len = 0; + switch (cipher) { + case SG_CIPHER_AES_CBC_PKCS5: + if (gcry_cipher_setiv(ctx, iv, iv_len)) goto error; + pad_len = 16 - (plaintext_len % 16); + if (pad_len == 0) pad_len = 16; + break; + case SG_CIPHER_AES_CTR_NOPADDING: + if (gcry_cipher_setctr(ctx, iv, iv_len)) goto error; + break; + default: + return SG_ERR_UNKNOWN; } - if (signal_protocol_store_context_create(&store_context_p, ctx_p->axolotl_global_context_p)) { - return "failed to create store context"; + size_t padded_len = plaintext_len + pad_len; + padded = signal_buffer_alloc(padded_len); + if (padded == 0) { + error_code = SG_ERR_NOMEM; + goto error; } - if (signal_protocol_store_context_set_session_store(store_context_p, &session_store)) { - return "failed to create session store"; + memset(signal_buffer_data(padded) + plaintext_len, pad_len, pad_len); + memcpy(signal_buffer_data(padded), plaintext, plaintext_len); + + out_buf = signal_buffer_alloc(padded_len + tag_len); + if (out_buf == 0) { + error_code = SG_ERR_NOMEM; + goto error; } - if (signal_protocol_store_context_set_pre_key_store(store_context_p, &pre_key_store)) { - return "failed to set pre key store"; + if (gcry_cipher_encrypt(ctx, signal_buffer_data(out_buf), padded_len, signal_buffer_data(padded), padded_len)) goto error; + + if (tag_len > 0) { + if (gcry_cipher_gettag(ctx, signal_buffer_data(out_buf) + padded_len, tag_len)) goto error; } - if (signal_protocol_store_context_set_signed_pre_key_store(store_context_p, &signed_pre_key_store)) { - return "failed to set signed pre key store"; + *output = out_buf; + out_buf = 0; + + signal_buffer_bzero_free(padded); + padded = 0; + + gcry_cipher_close(ctx); + return SG_SUCCESS; +} + +int signal_decrypt(signal_buffer **output, + int cipher, + const uint8_t *key, size_t key_len, + const uint8_t *iv, size_t iv_len, + const uint8_t *ciphertext, size_t ciphertext_len, + void *user_data) { + (void) user_data; + + int algo, mode, error_code = SG_ERR_UNKNOWN; + *output = 0; + if (aes_cipher(cipher, key_len, &algo, &mode)) return SG_ERR_INVAL; + if (ciphertext_len == 0) return SG_ERR_INVAL; + + gcry_cipher_hd_t ctx = {0}; + + if (gcry_cipher_open(&ctx, algo, mode, 0)) return SG_ERR_NOMEM; + + signal_buffer* out_buf = 0; + goto no_error; +error: + gcry_cipher_close(ctx); + if (out_buf != 0) { + signal_buffer_bzero_free(out_buf); } + return error_code; +no_error: + + if (gcry_cipher_setkey(ctx, key, key_len)) goto error; - if (signal_protocol_store_context_set_identity_key_store(store_context_p, &identity_key_store)) { - return "failed to set identity key store"; + uint8_t tag_len = 0, pkcs_pad = 0; + switch (cipher) { + case SG_CIPHER_AES_CBC_PKCS5: + if (gcry_cipher_setiv(ctx, iv, iv_len)) goto error; + pkcs_pad = 1; + break; + case SG_CIPHER_AES_CTR_NOPADDING: + if (gcry_cipher_setctr(ctx, iv, iv_len)) goto error; + break; + default: + goto error; } - ctx_p->axolotl_store_context_p = store_context_p; + size_t padded_len = ciphertext_len - tag_len; + out_buf = signal_buffer_alloc(padded_len); + if (out_buf == 0) { + error_code = SG_ERR_NOMEM; + goto error; + } - return NULL; + if (gcry_cipher_decrypt(ctx, signal_buffer_data(out_buf), signal_buffer_len(out_buf), ciphertext, padded_len)) goto error; + + if (tag_len > 0) { + if (gcry_cipher_checktag(ctx, ciphertext + padded_len, tag_len)) goto error; + } + + if (pkcs_pad) { + uint8_t pad_len = signal_buffer_data(out_buf)[padded_len - 1]; + if (pad_len > 16 || pad_len > padded_len) goto error; + *output = signal_buffer_create(signal_buffer_data(out_buf), padded_len - pad_len); + signal_buffer_bzero_free(out_buf); + out_buf = 0; + } else { + *output = out_buf; + out_buf = 0; + } + + gcry_cipher_close(ctx); + return SG_SUCCESS; } -*/ -void omemo__init(struct t_omemo **omemo, uint32_t device, - struct t_identity *const identity) +void lock_function(void *user_data) { - struct t_omemo *new_omemo; + (void) user_data; +} + +void unlock_function(void *user_data) +{ + (void) user_data; +} + +void omemo__log_emit_weechat(int level, const char *message, size_t len, void *user_data) +{ + struct t_gui_buffer *buffer = (struct t_gui_buffer*)user_data; + + static const char *log_level_name[5] = {"error", "warn", "notice", "info", "debug"}; + + const char *tags = level < SG_LOG_DEBUG ? "no_log" : NULL; + + weechat_printf_date_tags( + buffer, 0, tags, + _("%somemo (%s): %.*s"), + weechat_prefix("network"), + log_level_name[level], len, message); +} + +int omemo__signal_init(struct t_gui_buffer *buffer, struct t_omemo *omemo) +{ + signal_context *global_context; + + gcry_check_version(NULL); + + signal_context_create(&global_context, buffer); + signal_context_set_log_function(global_context, &omemo__log_emit_weechat); + + struct signal_crypto_provider provider = { + .random_func = &signal_random_generator, + .hmac_sha256_init_func = &signal_hmac_sha256_init, + .hmac_sha256_update_func = &signal_hmac_sha256_update, + .hmac_sha256_final_func = &signal_hmac_sha256_final, + .hmac_sha256_cleanup_func = &signal_hmac_sha256_cleanup, + .sha512_digest_init_func = &signal_sha512_digest_init, + .sha512_digest_update_func = &signal_sha512_digest_update, + .sha512_digest_final_func = &signal_sha512_digest_final, + .sha512_digest_cleanup_func = &signal_sha512_digest_cleanup, + .encrypt_func = &signal_encrypt, + .decrypt_func = &signal_decrypt, + .user_data = buffer, + }; + + signal_context_set_crypto_provider(global_context, &provider); + signal_context_set_locking_functions(global_context, &lock_function, &unlock_function); + + ratchet_identity_key_pair *identity_key_pair; + uint32_t registration_id; + signal_protocol_key_helper_pre_key_list_node *pre_keys_head; + session_signed_pre_key *signed_pre_key; + int start_id = 0; + time_t timestamp = time(NULL); + + signal_protocol_key_helper_generate_identity_key_pair(&identity_key_pair, global_context); + signal_protocol_key_helper_generate_registration_id(®istration_id, 0, global_context); + signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, global_context); + signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, identity_key_pair, 5, timestamp, global_context); + + /* Store identity_key_pair somewhere durable and safe. */ + /* Store registration_id somewhere durable and safe. */ - srandom(time(NULL)); + /* Store pre keys in the pre key store. */ + /* Store signed pre key in the signed pre key store. */ + + omemo->context = global_context; + + return SG_SUCCESS; +} + +void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, + uint32_t device, struct t_omemo_identity *const identity) +{ + struct t_omemo *new_omemo; new_omemo = calloc(1, sizeof(**omemo)); + omemo__signal_init(buffer, new_omemo); + new_omemo->identity = malloc(sizeof(*identity)); if (identity) { @@ -120,7 +484,7 @@ void omemo__init(struct t_omemo **omemo, uint32_t device, else { new_omemo->identity->length = 4; - new_omemo->identity->key = calloc(identity->length, sizeof(*identity->key)); + new_omemo->identity->key = calloc(new_omemo->identity->length, sizeof(*new_omemo->identity->key)); new_omemo->identity->key[0] = random(); new_omemo->identity->key[1] = random(); @@ -137,6 +501,8 @@ void omemo__free(struct t_omemo *omemo) { if (omemo) { + if (omemo->context) + signal_context_destroy(omemo->context); if (omemo->identity->key) free(omemo->identity->key); if (omemo->identity) diff --git a/omemo.h b/omemo.h index 2ce48fa..96d7885 100644 --- a/omemo.h +++ b/omemo.h @@ -7,7 +7,7 @@ extern const char *OMEMO_ADVICE; -struct t_identity +struct t_omemo_identity { uint8_t *key; size_t length; @@ -15,18 +15,19 @@ struct t_identity struct t_omemo { + struct signal_context *context; //omemo_crypto_provider provider; //axc_context *context; //axc_bundle *a_bundle; //omemo_bundle *o_bundle; - struct t_identity *identity; + struct t_omemo_identity *identity; uint32_t device_id; }; -void omemo__init(struct t_omemo **omemo, uint32_t device, - struct t_identity *identity); +void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, + uint32_t device, struct t_omemo_identity *identity); void omemo__free(struct t_omemo *omemo); diff --git a/pgp.c b/pgp.c index dc1c65c..a879e81 100644 --- a/pgp.c +++ b/pgp.c @@ -240,6 +240,7 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce for (size_t i = 0; i < sigcount; i++) { rnp_op_verify_signature_t sig = NULL; rnp_key_handle_t key = NULL; + rnp_signature_handle_t signature = NULL; char * keyid = NULL; if ((ret = rnp_op_verify_get_signature_at(verify, i, &sig)) != RNP_SUCCESS) { @@ -248,28 +249,36 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce goto verify_finish; } - if ((ret = rnp_op_verify_signature_get_key(sig, &key)) != RNP_SUCCESS) { - const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get signature's %d key: %s\n", (int)i, reason); - goto verify_finish; - } + if ((ret = rnp_op_verify_signature_get_key(sig, &key)) == RNP_SUCCESS) { + if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(buffer, "[PGP]\tfailed to get key id %d: %s\n", (int)i, reason); + rnp_key_handle_destroy(key); + goto verify_finish; + } - if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) { - const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get key id %d: %s\n", (int)i, reason); - rnp_key_handle_destroy(key); - goto verify_finish; - } + if ((ret = rnp_key_get_signature_at(key, 0, &signature)) == RNP_SUCCESS) { + if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason); + rnp_key_handle_destroy(key); + goto verify_finish; + } + rnp_signature_handle_destroy(signature); + } + } else { + if ((ret = rnp_op_verify_signature_get_handle(sig, &signature)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(buffer, "[PGP]\tfailed to get signature's %d handle: %s\n", (int)i, reason); + goto verify_finish; + } - rnp_signature_handle_t signature = NULL; - if ((ret = rnp_key_get_signature_at(key, 0, &signature)) == RNP_SUCCESS) { if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason); rnp_key_handle_destroy(key); goto verify_finish; } - rnp_signature_handle_destroy(signature); } result = strdup(keyid); diff --git a/user.c b/user.c index 6698c50..50abe1c 100644 --- a/user.c +++ b/user.c @@ -95,7 +95,7 @@ void user__nicklist_add(struct t_account *account, { struct t_gui_nick_group *ptr_group; struct t_gui_buffer *ptr_buffer; - char *name = user->profile.display_name; + char *name = channel ? user->profile.display_name : user->id; if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name), channel->id) == 0) name = xmpp_jid_resource(account->context, name); diff --git a/util.c b/util.c index 15972a8..382ee05 100644 --- a/util.c +++ b/util.c @@ -2,7 +2,9 @@ // 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 "plugin.h" @@ -12,3 +14,36 @@ int char_cmp(const void *p1, const void *p2) { return *(const char *)p1 == *(const char *)p2; } + +char *exec(const char *command) +{ + // use hook_process instead! + char buffer[128]; + char **result = weechat_string_dyn_alloc(256); + + // Open pipe to file + FILE* pipe = popen(command, "r"); + if (!pipe) { + return "popen failed!"; + } + + // read till end of process: + while (!feof(pipe)) { + + // use buffer to read and add to result + if (fgets(buffer, 128, pipe) != NULL) + weechat_string_dyn_concat(result, buffer, -1); + } + + pclose(pipe); + weechat_string_dyn_free(result, 0); + return *result; +} + +char *stanza_xml(xmpp_stanza_t *stanza) +{ + char *result; + size_t len; + xmpp_stanza_to_text(stanza, &result, &len); + return result; +} diff --git a/util.h b/util.h index 2226299..0c23aa9 100644 --- a/util.h +++ b/util.h @@ -7,4 +7,8 @@ int char_cmp(const void *p1, const void *p2); +char *exec(const char *command); + +char *stanza_xml(struct _xmpp_stanza_t *stanza); + #endif /*WEECHAT_XMPP_UTIL_H*/ From d566f45c6ad25526adfe3a4820dc1a52c87fd4f3 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Sun, 25 Jul 2021 19:28:34 +0100 Subject: [PATCH 116/118] signal-ish --- connection.c | 33 ++++++++-------------- omemo.c | 78 ++++++++++++++++++++++++++++++++++------------------ omemo.h | 20 ++++++-------- 3 files changed, 70 insertions(+), 61 deletions(-) diff --git a/connection.c b/connection.c index e3a6c39..4125951 100644 --- a/connection.c +++ b/connection.c @@ -1118,48 +1118,37 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, WEECHAT_HASHTABLE_STRING, NULL, NULL); weechat_hashtable_set(variables, "account", account->name); - char *dev_str = weechat_string_eval_expression( + char *device_r = weechat_string_eval_expression( "${sec.data.xmpp_device_${account}}", NULL, variables, NULL); - char *b64_id = weechat_string_eval_expression( + char *device_w = device_r; + char *account_r = weechat_string_eval_expression( "${sec.data.xmpp_identity_${account}}", NULL, variables, NULL); + char *account_w = account_r; weechat_hashtable_free(variables); - uint32_t dev_id = dev_str[0] ? atoi(dev_str) : 0; - uint8_t identity[128] = {0}; - if (b64_id && *b64_id) - weechat_string_base_decode(64, b64_id, (char*)identity); - struct t_omemo_identity id_key = { - .key = identity, - .length = 4, - }; - - omemo__init(account->buffer, &account->omemo, dev_id, b64_id && *b64_id ? &id_key : NULL); - - char account_id[64] = {0}; - snprintf(account_id, sizeof(account_id), "%d", account->omemo->device_id); - if (weechat_strcasecmp(dev_str, account_id) != 0) + + omemo__init(account->buffer, &account->omemo, &device_w, &account_w); + + if (weechat_strcasecmp(device_w, device_r) != 0) { char **command = weechat_string_dyn_alloc(256); weechat_string_dyn_concat(command, "/secure set ", -1); weechat_string_dyn_concat(command, "xmpp_device_", -1); weechat_string_dyn_concat(command, account->name, -1); weechat_string_dyn_concat(command, " ", -1); - weechat_string_dyn_concat(command, account_id, -1); + weechat_string_dyn_concat(command, device_w, -1); weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); } - char account_key[64] = {0}; - weechat_string_base_encode(64, (char*)account->omemo->identity->key, - account->omemo->identity->length, account_key); - if (weechat_strcasecmp(b64_id, account_key) != 0) + if (weechat_strcasecmp(account_w, account_r) != 0) { char **command = weechat_string_dyn_alloc(256); weechat_string_dyn_concat(command, "/secure set ", -1); weechat_string_dyn_concat(command, "xmpp_identity_", -1); weechat_string_dyn_concat(command, account->name, -1); weechat_string_dyn_concat(command, " ", -1); - weechat_string_dyn_concat(command, account_key, -1); + weechat_string_dyn_concat(command, account_w, -1); weechat_command(account->buffer, *command); weechat_string_dyn_free(command, 1); } diff --git a/omemo.c b/omemo.c index 0c10673..17983b7 100644 --- a/omemo.c +++ b/omemo.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -441,20 +442,15 @@ int omemo__signal_init(struct t_gui_buffer *buffer, struct t_omemo *omemo) signal_context_set_crypto_provider(global_context, &provider); signal_context_set_locking_functions(global_context, &lock_function, &unlock_function); - ratchet_identity_key_pair *identity_key_pair; - uint32_t registration_id; signal_protocol_key_helper_pre_key_list_node *pre_keys_head; session_signed_pre_key *signed_pre_key; int start_id = 0; time_t timestamp = time(NULL); - signal_protocol_key_helper_generate_identity_key_pair(&identity_key_pair, global_context); - signal_protocol_key_helper_generate_registration_id(®istration_id, 0, global_context); + signal_protocol_key_helper_generate_identity_key_pair(&omemo->identity, global_context); + signal_protocol_key_helper_generate_registration_id(&omemo->device_id, 0, global_context); signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, global_context); - signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, identity_key_pair, 5, timestamp, global_context); - - /* Store identity_key_pair somewhere durable and safe. */ - /* Store registration_id somewhere durable and safe. */ + signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, omemo->identity, 5, timestamp, global_context); /* Store pre keys in the pre key store. */ /* Store signed pre key in the signed pre key store. */ @@ -465,36 +461,65 @@ int omemo__signal_init(struct t_gui_buffer *buffer, struct t_omemo *omemo) } void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, - uint32_t device, struct t_omemo_identity *const identity) + char **device, char **identity) { struct t_omemo *new_omemo; new_omemo = calloc(1, sizeof(**omemo)); + omemo__deserialize(new_omemo, *device, *identity, strlen(*identity)); + omemo__signal_init(buffer, new_omemo); - new_omemo->identity = malloc(sizeof(*identity)); - if (identity) + omemo__serialize(new_omemo, device, identity, NULL); + + *omemo = new_omemo; +} + +void omemo__serialize(struct t_omemo *omemo, char **device, + char **identity, size_t *identity_len) +{ + if (device) { - new_omemo->identity->length = identity->length; - new_omemo->identity->key = calloc(identity->length, sizeof(*identity->key)); - memcpy(new_omemo->identity->key, identity->key, - identity->length * sizeof(*identity->key)); + size_t id_slen = log10(omemo->device_id) * 2; + char *id = malloc(sizeof(char) * id_slen); + snprintf(id, id_slen, "%d", omemo->device_id); + + *device = id; } - else + if (identity) { - new_omemo->identity->length = 4; - new_omemo->identity->key = calloc(new_omemo->identity->length, sizeof(*new_omemo->identity->key)); + signal_buffer *buffer; + ratchet_identity_key_pair_serialize(&buffer, omemo->identity); - new_omemo->identity->key[0] = random(); - new_omemo->identity->key[1] = random(); - new_omemo->identity->key[2] = random(); - new_omemo->identity->key[3] = random(); + size_t key_slen = signal_buffer_len(buffer) * 2; + char *key = malloc(sizeof(char) * key_slen); + size_t length = weechat_string_base_encode(64, (char*)signal_buffer_data(buffer), + signal_buffer_len(buffer), key); + + *identity = key; + if (identity_len) + *identity_len = length; } +} - new_omemo->device_id = device ? device : random(); +void omemo__deserialize(struct t_omemo *omemo, const char *device, + const char *identity, size_t identity_len) +{ + if (device) + { + uint32_t id = device[0] ? atoi(device) : 0; - *omemo = new_omemo; + omemo->device_id = id; + } + if (identity) + { + uint8_t *key = malloc(sizeof(uint8_t) * identity_len); + size_t length = weechat_string_base_decode(64, identity, (char*)key); + + ratchet_identity_key_pair_deserialize(&omemo->identity, + key, length, omemo->context); + } } void omemo__free(struct t_omemo *omemo) @@ -503,10 +528,9 @@ void omemo__free(struct t_omemo *omemo) { if (omemo->context) signal_context_destroy(omemo->context); - if (omemo->identity->key) - free(omemo->identity->key); if (omemo->identity) - free(omemo->identity); + ratchet_identity_key_pair_destroy( + (signal_type_base *)omemo->identity); free(omemo); } } diff --git a/omemo.h b/omemo.h index 96d7885..db6d4b1 100644 --- a/omemo.h +++ b/omemo.h @@ -7,27 +7,23 @@ extern const char *OMEMO_ADVICE; -struct t_omemo_identity -{ - uint8_t *key; - size_t length; -}; - struct t_omemo { struct signal_context *context; - //omemo_crypto_provider provider; - //axc_context *context; - //axc_bundle *a_bundle; - //omemo_bundle *o_bundle; - struct t_omemo_identity *identity; + struct ratchet_identity_key_pair *identity; uint32_t device_id; }; void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, - uint32_t device, struct t_omemo_identity *identity); + char **device, char **identity); + +void omemo__serialize(struct t_omemo *omemo, char **device, + char **identity, size_t *identity_len); + +void omemo__deserialize(struct t_omemo *omemo, const char *device, + const char *identity, size_t identity_len); void omemo__free(struct t_omemo *omemo); From d3ffc1937871d157bf464c4fd6fd7bca6a0a2b64 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Tue, 27 Jul 2021 22:27:03 +0100 Subject: [PATCH 117/118] nicklist stuff --- .envrc | 2 + Makefile | 2 +- README.org | 10 +-- account.c | 7 +-- buffer.c | 6 +- channel.c | 157 ++++++++++++++++++++++++----------------------- channel.h | 14 ++--- command.c | 152 ++++++++++++++++++++++++++++++++++++++------- connection.c | 157 ++++++++++++++++++++++++----------------------- omemo.c | 169 ++++++++++++++++++++++++++++++++++++--------------- omemo.h | 8 ++- pgp.c | 50 +++++++-------- user.c | 58 ++++++++++-------- user.h | 11 ++-- 14 files changed, 495 insertions(+), 308 deletions(-) diff --git a/.envrc b/.envrc index d474ea8..f2874d4 100644 --- a/.envrc +++ b/.envrc @@ -50,6 +50,7 @@ use_guix() libstrophe # Dep (strophe) libgcrypt # Dep (gcrypt) libsignal-protocol-c # Dep (libsignal) + lmdb # Dep (lmdb) rnp # Dep (rnpgp) ) @@ -63,5 +64,6 @@ use guix \ --with-debug-info=weechat\ --with-debug-info=libstrophe\ --with-debug-info=libsignal-protocol-c\ + --with-debug-info=lmdb\ --with-debug-info=rnp\ clang:extra gdb diff --git a/Makefile b/Makefile index 60f4fe1..1e89f09 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ FIND=find INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags librnp-0) $(shell pkg-config --cflags libsignal-protocol-c) CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -gdwarf-4 -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES) LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS) -LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs librnp-0) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs librnp-0) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt -llmdb PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib diff --git a/README.org b/README.org index 1a2959e..d4815c5 100644 --- a/README.org +++ b/README.org @@ -116,14 +116,16 @@ * [X] [#B] Leaves * [X] [#B] Tracking * [X] [#B] Set/show topic - * [-] OMEMO (libsignal-protocol-c / axc) + * [-] OMEMO (libsignal-protocol-c) * [-] Presence * [X] Disco * [X] Disco response - * [-] Key Generation / storage (secured_data?) + * [-] Key Generation / storage (lmdb) * [X] Generation - * [X] Storage - * [ ] Announce + * [?] Storage + * [-] Announce + * [X] Device ID + * [ ] Bundles * [ ] Messages * [ ] [#C] MUC PMs * [X] [#A] Send typing notifications diff --git a/account.c b/account.c index 3e4a213..ab4464c 100644 --- a/account.c +++ b/account.c @@ -507,7 +507,7 @@ void account__disconnect(struct t_account *account, int reconnect) account__set_lag(account); */ // lag based on xmpp ping - account->disconnected = 1; + account->disconnected = !reconnect; /* send signal "account_disconnected" with account name */ (void) weechat_hook_signal_send("xmpp_account_disconnected", @@ -572,8 +572,6 @@ void account__close_connection(struct t_account *account) int account__connect(struct t_account *account) { - account->disconnected = 0; - if (!account->buffer) { if (!account__create_buffer(account)) @@ -587,7 +585,7 @@ int account__connect(struct t_account *account) connection__connect(account, &account->connection, account_jid(account), account_password(account), account_tls(account)); - (void) weechat_hook_signal_send("xmpp_account_connected", + (void) weechat_hook_signal_send("xmpp_account_connecting", WEECHAT_HOOK_SIGNAL_STRING, account->name); return account->is_connected; @@ -608,6 +606,7 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls) && (xmpp_conn_is_connecting(ptr_account->connection) || xmpp_conn_is_connected(ptr_account->connection))) connection__process(ptr_account->context, ptr_account->connection, 10); + else if (ptr_account->disconnected); else if (ptr_account->reconnect_start > 0 && ptr_account->reconnect_start < time(NULL)) { diff --git a/buffer.c b/buffer.c index 25fa3f6..3d5ed3e 100644 --- a/buffer.c +++ b/buffer.c @@ -155,7 +155,7 @@ int buffer__close_cb(const void *pointer, void *data, { if (ptr_account) { - if (!ptr_account->disconnected) + if (ptr_account->is_connected) { account__disconnect(ptr_account, 0); } @@ -167,7 +167,7 @@ int buffer__close_cb(const void *pointer, void *data, { if (ptr_account && ptr_channel) { - if (!ptr_account->disconnected) + if (ptr_account->is_connected) { channel__free(ptr_account, ptr_channel); } @@ -177,7 +177,7 @@ int buffer__close_cb(const void *pointer, void *data, { if (ptr_account && ptr_channel) { - if (!ptr_account->disconnected) + if (ptr_account->is_connected) { channel__free(ptr_account, ptr_channel); } diff --git a/channel.c b/channel.c index 4932079..a60b21f 100644 --- a/channel.c +++ b/channel.c @@ -211,12 +211,28 @@ void channel__add_nicklist_groups(struct t_account *account, ptr_buffer = channel ? channel->buffer : account->buffer; - snprintf(str_group, sizeof(str_group), "%03d|%s", - 000, "+"); + snprintf(str_group, sizeof(str_group), "%03d|%s", 000, "~"); weechat_nicklist_add_group(ptr_buffer, NULL, str_group, "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", - 999, "..."); + snprintf(str_group, sizeof(str_group), "%03d|%s", 001, "&"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", 002, "@"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", 003, "%"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", 004, "+"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", 005, "?"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", 006, "!"); + weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + snprintf(str_group, sizeof(str_group), "%03d|%s", 999, "..."); weechat_nicklist_add_group(ptr_buffer, NULL, str_group, "weechat.color.nicklist_group", 1); } @@ -290,6 +306,8 @@ struct t_channel *channel__new(struct t_account *account, account->channels = new_channel; account->last_channel = new_channel; + channel__add_nicklist_groups(account, new_channel); + if (type != CHANNEL_TYPE_MUC) { time_t start = time(NULL); @@ -818,15 +836,14 @@ void channel__update_topic(struct t_channel *channel, struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel *channel, - const char *id, const char *client, - const char *status) + const char *id, const char *client) { struct t_channel_member *member; struct t_user *user; user = user__search(account, id); - if (weechat_strcasecmp(user->id, channel->id) == 0 + if (user && weechat_strcasecmp(user->id, channel->id) == 0 && channel->type == CHANNEL_TYPE_MUC) { weechat_printf_date_tags(channel->buffer, 0, "log2", "%sMUC: %s", @@ -835,19 +852,24 @@ struct t_channel_member *channel__add_member(struct t_account *account, return NULL; } - member = malloc(sizeof(struct t_channel_member)); - member->id = strdup(id); + if (!(member = channel__member_search(channel, id))) + { + member = malloc(sizeof(struct t_channel_member)); + member->id = strdup(id); - member->role = NULL; - member->affiliation = NULL; + 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; + 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); if (user) user__nicklist_add(account, channel, user); @@ -856,28 +878,45 @@ struct t_channel_member *channel__add_member(struct t_account *account, 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 %sentered%s %s %s%s%s", + 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", weechat_prefix("join"), user__as_prefix_raw(account, jid_resource), - client ? "(" : "", client, client ? ")" : "", + client ? " (" : "", + client ? client : "", + client ? ")" : "", + user->profile.status ? "is " : "", weechat_color("irc.color.message_join"), + user->profile.status ? user->profile.status : "entered", weechat_color("reset"), channel->id, - status ? "[" : "", - status ? status : "", - status ? "]" : ""); + user->profile.status_text ? " [" : "", + user->profile.status_text ? user->profile.status_text : "", + user->profile.status_text ? "]" : "", + weechat_color("yellow"), " as ", weechat_color("reset"), + user->profile.affiliation ? user->profile.affiliation : "", + user->profile.affiliation ? " " : "", + user->profile.role, + user->profile.pgp_id ? weechat_color("gray") : "", + user->profile.pgp_id ? " with PGP:" : "", + 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) %sentered%s %s %s%s%s", + 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", weechat_prefix("join"), - user__as_prefix_raw(account, - xmpp_jid_bare(account->context, user->id)), - xmpp_jid_resource(account->context, user->id), + jid_resource ? user__as_prefix_raw(account, jid_bare) : "You", + jid_resource ? jid_resource : user__as_prefix_raw(account, jid_bare), + user->profile.status ? "is " : "", weechat_color("irc.color.message_join"), + user->profile.status ? user->profile.status : "entered", weechat_color("reset"), channel->id, - status ? "[" : "", - status ? status : "", - status ? "]" : ""); + user->profile.status_text ? " [" : "", + user->profile.status_text ? user->profile.status_text : "", + user->profile.status_text ? "]" : "", + user->profile.pgp_id ? weechat_color("gray") : "", + user->profile.pgp_id ? " with PGP:" : "", + user->profile.pgp_id ? user->profile.pgp_id : "", + user->profile.pgp_id ? weechat_color("reset") : ""); return member; } @@ -900,56 +939,16 @@ struct t_channel_member *channel__member_search(struct t_channel *channel, return NULL; } -int channel__set_member_role(struct t_account *account, - struct t_channel *channel, - const char *id, const char *role) -{ - struct t_channel_member *member; - struct t_user *user; - - user = user__search(account, id); - if (!user) - return 0; - - member = channel__member_search(channel, id); - if (!member) - return 0; - - member->role = strdup(role); - - return 1; -} - -int channel__set_member_affiliation(struct t_account *account, - struct t_channel *channel, - const char *id, const char *affiliation) -{ - struct t_channel_member *member; - struct t_user *user; - - user = user__search(account, id); - if (!user) - return 0; - - member = channel__member_search(channel, id); - if (!member) - return 0; - - member->affiliation = strdup(affiliation); - - return 1; -} - struct t_channel_member *channel__remove_member(struct t_account *account, struct t_channel *channel, - const char *id, const char *status) + const char *id, const char *reason) { struct t_channel_member *member; struct t_user *user; user = user__search(account, id); - //if (user) - // user__nicklist_remove(account, channel, user); + if (user) + user__nicklist_remove(account, channel, user); member = channel__member_search(channel, id); if (member) @@ -965,9 +964,9 @@ struct t_channel_member *channel__remove_member(struct t_account *account, weechat_color("irc.color.message_quit"), weechat_color("reset"), channel->id, - status ? "[" : "", - status ? status : "", - status ? "]" : ""); + 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_prefix("quit"), @@ -976,9 +975,9 @@ struct t_channel_member *channel__remove_member(struct t_account *account, weechat_color("irc.color.message_quit"), weechat_color("reset"), channel->id, - status ? "[" : "", - status ? status : "", - status ? "]" : ""); + reason ? "[" : "", + reason ? reason : "", + reason ? "]" : ""); return member; } diff --git a/channel.h b/channel.h index 52d799d..c336ee2 100644 --- a/channel.h +++ b/channel.h @@ -170,20 +170,14 @@ void channel__update_purpose(struct t_channel *channel, struct t_channel_member *channel__add_member(struct t_account *account, struct t_channel *channel, - const char *id, const char *client, - const char *status); + const char *id, const char *client); -int channel__set_member_role(struct t_account *account, - struct t_channel *channel, - const char *id, const char *role); - -int channel__set_member_affiliation(struct t_account *account, - struct t_channel *channel, - const char *id, const char *affiliation); +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 *status); + const char *id, const char *reason); void channel__send_message(struct t_account *account, struct t_channel *channel, const char *to, const char *body); diff --git a/command.c b/command.c index 2b60858..84c90ed 100644 --- a/command.c +++ b/command.c @@ -6,11 +6,11 @@ #include #include #include +#include #include #include "plugin.h" //#include "oauth.h" -//#include "teaminfo.h" #include "account.h" #include "user.h" #include "channel.h" @@ -18,6 +18,9 @@ #include "message.h" #include "command.h" +#define MAM_DEFAULT_DAYS 2 +#define STR(X) #X + void command__display_account(struct t_account *account) { int num_channels, num_pv; @@ -147,7 +150,7 @@ void command__add_account(const char *name, const char *jid, const char *passwor account_option_set(account, ACCOUNT_OPTION_NICKNAME, strdup(xmpp_jid_node(account->context, jid))); - weechat_printf ( + weechat_printf( NULL, _("%s: account %s%s%s %s(%s%s%s)%s added"), WEECHAT_XMPP_PLUGIN_NAME, @@ -161,10 +164,12 @@ void command__add_account(const char *name, const char *jid, const char *passwor weechat_color("reset")); } -void command__account_add(int argc, char **argv) +void command__account_add(struct t_gui_buffer *buffer, int argc, char **argv) { char *name, *jid = NULL, *password = NULL; + (void) buffer; + switch (argc) { case 5: @@ -202,11 +207,12 @@ int command__connect_account(struct t_account *account) return 1; } -int command__account_connect(int argc, char **argv) +int command__account_connect(struct t_gui_buffer *buffer, int argc, char **argv) { int i, nb_connect, connect_ok; struct t_account *ptr_account; + (void) buffer; (void) argc; (void) argv; @@ -257,7 +263,7 @@ int command__disconnect_account(struct t_account *account) return 1; } -int command__account_disconnect(int argc, char **argv) +int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **argv) { int i, nb_disconnect, disconnect_ok; struct t_account *ptr_account; @@ -268,6 +274,20 @@ int command__account_disconnect(int argc, char **argv) disconnect_ok = 1; nb_disconnect = 0; + if (argc < 2) + { + struct t_channel *ptr_channel; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (ptr_account) + { + if (!command__disconnect_account(ptr_account)) + { + disconnect_ok = 0; + } + } + } for (i = 2; i < argc; i++) { nb_disconnect++; @@ -292,14 +312,16 @@ int command__account_disconnect(int argc, char **argv) return (disconnect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; } -int command__account_reconnect(int argc, char **argv) +int command__account_reconnect(struct t_gui_buffer *buffer, int argc, char **argv) { - command__account_disconnect(argc, argv); - return command__account_connect(argc, argv); + command__account_disconnect(buffer, argc, argv); + return command__account_connect(buffer, argc, argv); } -void command__account_delete(int argc, char **argv) +void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv) { + (void) buffer; + struct t_account *account; char *account_name; @@ -337,7 +359,7 @@ void command__account_delete(int argc, char **argv) account_name = strdup(account->name); account__free(account); - weechat_printf ( + weechat_printf( NULL, _("%s: account %s%s%s has been deleted"), WEECHAT_XMPP_PLUGIN_NAME, @@ -349,8 +371,8 @@ void command__account_delete(int argc, char **argv) } int command__account(const void *pointer, void *data, - struct t_gui_buffer *buffer, int argc, - char **argv, char **argv_eol) + struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) { (void) pointer; @@ -367,31 +389,31 @@ int command__account(const void *pointer, void *data, { if (weechat_strcasecmp(argv[1], "add") == 0) { - command__account_add(argc, argv); + command__account_add(buffer, argc, argv); return WEECHAT_RC_OK; } if (weechat_strcasecmp(argv[1], "connect") == 0) { - command__account_connect(argc, argv); + command__account_connect(buffer, argc, argv); return WEECHAT_RC_OK; } if (weechat_strcasecmp(argv[1], "disconnect") == 0) { - command__account_disconnect(argc, argv); + command__account_disconnect(buffer, argc, argv); return WEECHAT_RC_OK; } if (weechat_strcasecmp(argv[1], "reconnect") == 0) { - command__account_reconnect(argc, argv); + command__account_reconnect(buffer, argc, argv); return WEECHAT_RC_OK; } if (weechat_strcasecmp(argv[1], "delete") == 0) { - command__account_delete(argc, argv); + command__account_delete(buffer, argc, argv); return WEECHAT_RC_OK; } @@ -478,6 +500,33 @@ int command__enter(const void *pointer, void *data, } weechat_string_free_split(jids); } + else + { + const char *buffer_jid = weechat_buffer_get_string(buffer, "localvar_channel"); + + pres_jid = xmpp_jid_new( + ptr_account->context, + xmpp_jid_node(ptr_account->context, buffer_jid), + 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); + + 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_t *pres__x = xmpp_stanza_new(ptr_account->context); + xmpp_stanza_set_name(pres__x, "x"); + xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc"); + xmpp_stanza_add_child(pres, pres__x); + xmpp_stanza_release(pres__x); + + xmpp_send(ptr_account->connection, pres); + xmpp_stanza_release(pres); + } return WEECHAT_RC_OK; } @@ -564,7 +613,7 @@ int command__msg(const void *pointer, void *data, if (!ptr_channel) { - weechat_printf ( + weechat_printf( ptr_account->buffer, _("%s%s: \"%s\" command can not be executed on a account buffer"), weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "msg"); @@ -619,7 +668,7 @@ int command__me(const void *pointer, void *data, if (!ptr_channel) { - weechat_printf ( + weechat_printf( ptr_account->buffer, _("%s%s: \"%s\" command can not be executed on a account buffer"), weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "me"); @@ -656,6 +705,58 @@ int command__me(const void *pointer, void *data, return WEECHAT_RC_OK; } +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; + int days; + + (void) pointer; + (void) data; + (void) argv_eol; + + buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); + + if (!ptr_account) + return WEECHAT_RC_ERROR; + + if (!ptr_channel) + { + weechat_printf( + ptr_account->buffer, + _("%s%s: \"%s\" command can not be executed on a account buffer"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "mam"); + return WEECHAT_RC_OK; + } + + time_t start = time(NULL); + struct tm *ago = gmtime(&start); + if (argc > 1) + { + errno = 0; + days = strtol(argv[1], NULL, 10); + + if (errno == 0) + ago->tm_mday -= days; + else + { + weechat_printf( + ptr_channel->buffer, + _("%s%s: \"%s\" is not a valid number of %s for %s"), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "days", "mam"); + ago->tm_mday -= MAM_DEFAULT_DAYS; + } + } + else + ago->tm_mday -= MAM_DEFAULT_DAYS; + start = mktime(ago); + channel__fetch_mam(ptr_account, ptr_channel, &start, NULL); + + return WEECHAT_RC_OK; +} + int command__pgp(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) @@ -675,10 +776,10 @@ int command__pgp(const void *pointer, void *data, if (!ptr_channel) { - weechat_printf ( + weechat_printf( ptr_account->buffer, _("%s%s: \"%s\" command can not be executed on a account buffer"), - weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "me"); + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "pgp"); return WEECHAT_RC_OK; } @@ -797,6 +898,15 @@ void command__init() if (!hook) weechat_printf(NULL, "Failed to setup command /me"); + hook = weechat_hook_command( + "mam", + N_("retrieve mam messages for the current channel"), + N_("[days]"), + N_("days: number of days to fetch (default: " STR(MAM_DEFAULT_DAYS) ")"), + NULL, &command__mam, NULL, NULL); + if (!hook) + weechat_printf(NULL, "Failed to setup command /mam"); + hook = weechat_hook_command( "pgp", N_("set the target pgp key for the current channel"), diff --git a/connection.c b/connection.c index 4125951..afb0683 100644 --- a/connection.c +++ b/connection.c @@ -86,9 +86,9 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void struct t_account *account = (struct t_account *)userdata; struct t_user *user; struct t_channel *channel; - xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *iq__x__item, *iq__c, *iq__status; + xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *show, *iq__x__item, *iq__c, *iq__status; const char *from, *from_bare, *from_res, *type, *role = NULL, *affiliation = NULL, *jid = NULL; - const char *certificate = NULL, *node = NULL, *ver = NULL; + const char *show__text = NULL, *certificate = NULL, *node = NULL, *ver = NULL; char *clientid = NULL, *status; from = xmpp_stanza_get_from(stanza); @@ -97,30 +97,21 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void from_bare = xmpp_jid_bare(account->context, from); from_res = xmpp_jid_resource(account->context, from); type = xmpp_stanza_get_type(stanza); + show = xmpp_stanza_get_child_by_name(stanza, "show"); + show__text = show ? xmpp_stanza_get_text(show) : NULL; iq__x_signed = xmpp_stanza_get_child_by_name_and_ns( stanza, "x", "jabber:x:signed"); if (iq__x_signed) { certificate = xmpp_stanza_get_text(iq__x_signed); } - iq__x_muc_user = xmpp_stanza_get_child_by_name_and_ns( - stanza, "x", "http://jabber.org/protocol/muc#user"); - if (iq__x_muc_user) - { - iq__x__item = xmpp_stanza_get_child_by_name(iq__x_muc_user, "item"); - role = xmpp_stanza_get_attribute(iq__x__item, "role"); - affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation"); - jid = xmpp_stanza_get_attribute(iq__x__item, "jid"); - } iq__c = xmpp_stanza_get_child_by_name_and_ns( stanza, "c", "http://jabber.org/protocol/caps"); if (iq__c) { node = xmpp_stanza_get_attribute(iq__c, "node"); ver = xmpp_stanza_get_attribute(iq__c, "ver"); - if (jid) - clientid = strdup(jid); - else if (node && ver) + if (node && ver) { int len = strlen(node)+1+strlen(ver); clientid = malloc(sizeof(char)*len); @@ -129,36 +120,76 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void } iq__status = xmpp_stanza_get_child_by_name(stanza, "status"); status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL; + iq__x_muc_user = xmpp_stanza_get_child_by_name_and_ns( + stanza, "x", "http://jabber.org/protocol/muc#user"); channel = channel__search(account, from_bare); if (weechat_strcasecmp(type, "unavailable") && !iq__x_muc_user && !channel) channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); - if (certificate && channel) + + if (iq__x_muc_user) + for (iq__x__item = xmpp_stanza_get_children(iq__x_muc_user); + iq__x__item; iq__x__item = xmpp_stanza_get_next(iq__x__item)) { - if (channel->type != CHANNEL_TYPE_MUC) - channel->pgp_id = pgp__verify(channel->buffer, account->pgp, certificate); - weechat_printf(channel->buffer, "[PGP]\t%sKey %s from %s", - weechat_color("gray"), channel->pgp_id, from); - } + if (weechat_strcasecmp(xmpp_stanza_get_name(iq__x__item), "item") != 0) + continue; - user = user__search(account, from); - if (!user) - user = user__new(account, from, - channel && weechat_strcasecmp(from_bare, channel->id) == 0 - ? from_res : from); + role = xmpp_stanza_get_attribute(iq__x__item, "role"); + affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation"); + jid = xmpp_stanza_get_attribute(iq__x__item, "jid"); - if (!iq__x_muc_user && channel) - { - channel__add_member(account, channel, from, clientid, status); + user = user__search(account, from); + if (!user) + user = user__new(account, from, + channel && weechat_strcasecmp(from_bare, channel->id) == 0 + ? from_res : from); + user->profile.status_text = status ? strdup(status) : NULL; + user->profile.status = show ? strdup(show__text) : NULL; + user->is_away = show ? weechat_strcasecmp(show__text, "away") == 0 : 0; + user->profile.role = role ? strdup(role) : NULL; + user->profile.affiliation = affiliation && strcmp(affiliation, "none") != 0 + ? strdup(affiliation) : NULL; + if (certificate && channel) + { + user->profile.pgp_id = pgp__verify(channel->buffer, account->pgp, certificate); + if (channel->type != CHANNEL_TYPE_MUC) + channel->pgp_id = user->profile.pgp_id; + } + + if (channel) + { + if (weechat_strcasecmp(role, "none") == 0) + channel__remove_member(account, channel, from, status); + else + channel__add_member(account, channel, from, jid ? jid : clientid); + } } - else if (channel) + else { - channel__set_member_role(account, channel, from, role); - channel__set_member_affiliation(account, channel, from, affiliation); - if (weechat_strcasecmp(role, "none") == 0) - channel__remove_member(account, channel, from, status); - else - channel__add_member(account, channel, from, clientid, status); + user = user__search(account, from); + if (!user) + user = user__new(account, from, + channel && weechat_strcasecmp(from_bare, channel->id) == 0 + ? from_res : from); + user->profile.status_text = status ? strdup(status) : NULL; + user->profile.status = show ? strdup(show__text) : NULL; + user->profile.role = role ? strdup(role) : NULL; + user->profile.affiliation = affiliation && strcmp(affiliation, "none") != 0 + ? strdup(affiliation) : NULL; + if (certificate && channel) + { + user->profile.pgp_id = pgp__verify(channel->buffer, account->pgp, certificate); + if (channel->type != CHANNEL_TYPE_MUC) + channel->pgp_id = user->profile.pgp_id; + } + + if (channel) + { + if (weechat_strcasecmp(type, "unavailable") == 0) + channel__remove_member(account, channel, from, status); + else + channel__add_member(account, channel, from, clientid); + } } if (clientid) @@ -219,8 +250,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * channel__add_typing(channel, user); weechat_printf(channel->buffer, "...\t%s%s typing", weechat_color("gray"), - weechat_strcasecmp(from_bare, channel->id) == 0 - ? nick : from); + channel->type == CHANNEL_TYPE_MUC ? nick : from); } sent = xmpp_stanza_get_child_by_name_and_ns( @@ -819,19 +849,21 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd { list = xmpp_stanza_get_child_by_name_and_ns( item, "list", "eu.siacs.conversations.axolotl"); - if (list) + if (list && account->omemo) { account__free_device_all(account); - struct t_account_device *dev = malloc(sizeof(struct t_account_device)); + struct t_account_device *dev; char id[64] = {0}; + int i = 0; + + dev = malloc(sizeof(struct t_account_device)); dev->id = account->omemo->device_id; snprintf(id, sizeof(id), "%d", dev->id); dev->name = strdup(id); account__add_device(account, dev); - int i = 0; children = malloc(sizeof(xmpp_stanza_t *) * 128); children[i++] = stanza__iq_pubsub_publish_item_list_device( account->context, NULL, with_noop(dev->name)); @@ -1005,6 +1037,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, if (status == XMPP_CONN_CONNECT) { + account->disconnected = 0; + xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, *pres__x, *pres__x__text, **children; char cap_hash[28+1] = {0}; @@ -1113,45 +1147,10 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, children[0]); xmpp_stanza_release(children[0]); - struct t_hashtable *variables = weechat_hashtable_new (8, - WEECHAT_HASHTABLE_STRING, - WEECHAT_HASHTABLE_STRING, - NULL, NULL); - weechat_hashtable_set(variables, "account", account->name); - char *device_r = weechat_string_eval_expression( - "${sec.data.xmpp_device_${account}}", - NULL, variables, NULL); - char *device_w = device_r; - char *account_r = weechat_string_eval_expression( - "${sec.data.xmpp_identity_${account}}", - NULL, variables, NULL); - char *account_w = account_r; - weechat_hashtable_free(variables); - - omemo__init(account->buffer, &account->omemo, &device_w, &account_w); - - if (weechat_strcasecmp(device_w, device_r) != 0) - { - char **command = weechat_string_dyn_alloc(256); - weechat_string_dyn_concat(command, "/secure set ", -1); - weechat_string_dyn_concat(command, "xmpp_device_", -1); - weechat_string_dyn_concat(command, account->name, -1); - weechat_string_dyn_concat(command, " ", -1); - weechat_string_dyn_concat(command, device_w, -1); - weechat_command(account->buffer, *command); - weechat_string_dyn_free(command, 1); - } - if (weechat_strcasecmp(account_w, account_r) != 0) - { - char **command = weechat_string_dyn_alloc(256); - weechat_string_dyn_concat(command, "/secure set ", -1); - weechat_string_dyn_concat(command, "xmpp_identity_", -1); - weechat_string_dyn_concat(command, account->name, -1); - weechat_string_dyn_concat(command, " ", -1); - weechat_string_dyn_concat(command, account_w, -1); - weechat_command(account->buffer, *command); - weechat_string_dyn_free(command, 1); - } + omemo__init(account->buffer, &account->omemo, account->name); + + (void) weechat_hook_signal_send("xmpp_account_connected", + WEECHAT_HOOK_SIGNAL_STRING, account->name); } else { diff --git a/omemo.c b/omemo.c index 17983b7..63134cc 100644 --- a/omemo.c +++ b/omemo.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -90,19 +91,19 @@ signal_protocol_address* signal_protocol_address_new(const char* name, int32_t d return address; } -int signal_randomize(uint8_t *data, size_t len) { +int cp_randomize(uint8_t *data, size_t len) { gcry_randomize(data, len, GCRY_STRONG_RANDOM); return SG_SUCCESS; } -int signal_random_generator(uint8_t *data, size_t len, void *user_data) { +int cp_random_generator(uint8_t *data, size_t len, void *user_data) { (void) user_data; gcry_randomize(data, len, GCRY_STRONG_RANDOM); return SG_SUCCESS; } -int signal_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data) { +int cp_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data) { (void) user_data; gcry_mac_hd_t* ctx = malloc(sizeof(gcry_mac_hd_t)); @@ -123,7 +124,7 @@ int signal_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_ return SG_SUCCESS; } -int signal_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data) { +int cp_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data) { (void) user_data; gcry_mac_hd_t* ctx = hmac_context; @@ -133,7 +134,7 @@ int signal_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t da return SG_SUCCESS; } -int signal_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data) { +int cp_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data) { (void) user_data; size_t len = gcry_mac_get_algo_maclen(GCRY_MAC_HMAC_SHA256); @@ -150,7 +151,7 @@ int signal_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *u return SG_SUCCESS; } -void signal_hmac_sha256_cleanup(void *hmac_context, void *user_data) { +void cp_hmac_sha256_cleanup(void *hmac_context, void *user_data) { (void) user_data; gcry_mac_hd_t* ctx = hmac_context; @@ -160,7 +161,7 @@ void signal_hmac_sha256_cleanup(void *hmac_context, void *user_data) { } } -int signal_sha512_digest_init(void **digest_context, void *user_data) { +int cp_sha512_digest_init(void **digest_context, void *user_data) { (void) user_data; gcry_md_hd_t* ctx = malloc(sizeof(gcry_mac_hd_t)); @@ -176,7 +177,7 @@ int signal_sha512_digest_init(void **digest_context, void *user_data) { return SG_SUCCESS; } -int signal_sha512_digest_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data) { +int cp_sha512_digest_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data) { (void) user_data; gcry_md_hd_t* ctx = digest_context; @@ -186,7 +187,7 @@ int signal_sha512_digest_update(void *digest_context, const uint8_t *data, size_ return SG_SUCCESS; } -int signal_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data) { +int cp_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data) { (void) user_data; size_t len = gcry_md_get_algo_dlen(GCRY_MD_SHA512); @@ -206,7 +207,7 @@ int signal_sha512_digest_final(void *digest_context, signal_buffer **output, voi return SG_SUCCESS; } -void signal_sha512_digest_cleanup(void *digest_context, void *user_data) { +void cp_sha512_digest_cleanup(void *digest_context, void *user_data) { (void) user_data; gcry_md_hd_t* ctx = digest_context; @@ -243,7 +244,7 @@ int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) { return SG_SUCCESS; } -int signal_encrypt(signal_buffer **output, +int cp_encrypt(signal_buffer **output, int cipher, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, @@ -320,7 +321,7 @@ no_error: return SG_SUCCESS; } -int signal_decrypt(signal_buffer **output, +int cp_decrypt(signal_buffer **output, int cipher, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, @@ -415,63 +416,131 @@ void omemo__log_emit_weechat(int level, const char *message, size_t len, void *u log_level_name[level], len, message); } -int omemo__signal_init(struct t_gui_buffer *buffer, struct t_omemo *omemo) +int iks_get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data) { - signal_context *global_context; + (void) public_data; + (void) private_data; + (void) user_data; + // Get the local client's identity key pair +} + +int iks_get_local_registration_id(void *user_data, uint32_t *registration_id) +{ + (void) user_data; + (void) registration_id; + // Return the local client's registration ID +} + +int iks_save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data) +{ + (void) address; + (void) key_data; + (void) key_len; + (void) user_data; + // Save a remote client's identity key +} + +int iks_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data) +{ + (void) address; + (void) key_data; + (void) key_len; + (void) user_data; + // Verify a remote client's identity key +} + +void iks_destroy_func(void *user_data) +{ + (void) user_data; + // Function called to perform cleanup when the data store context is being destroyed +} + + +void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, + const char *account_name) +{ + struct t_omemo *new_omemo; gcry_check_version(NULL); - signal_context_create(&global_context, buffer); - signal_context_set_log_function(global_context, &omemo__log_emit_weechat); - - struct signal_crypto_provider provider = { - .random_func = &signal_random_generator, - .hmac_sha256_init_func = &signal_hmac_sha256_init, - .hmac_sha256_update_func = &signal_hmac_sha256_update, - .hmac_sha256_final_func = &signal_hmac_sha256_final, - .hmac_sha256_cleanup_func = &signal_hmac_sha256_cleanup, - .sha512_digest_init_func = &signal_sha512_digest_init, - .sha512_digest_update_func = &signal_sha512_digest_update, - .sha512_digest_final_func = &signal_sha512_digest_final, - .sha512_digest_cleanup_func = &signal_sha512_digest_cleanup, - .encrypt_func = &signal_encrypt, - .decrypt_func = &signal_decrypt, + new_omemo = calloc(1, sizeof(**omemo)); + + signal_context_create(&new_omemo->context, buffer); + signal_context_set_log_function(new_omemo->context, &omemo__log_emit_weechat); + + mdb_env_create(&new_omemo->db.env); + mdb_env_set_maxdbs(new_omemo->db.env, 50); + mdb_env_set_mapsize(new_omemo->db.env, (size_t)1048576 * 100000); // 1MB * 100000 + char *path = weechat_string_eval_expression("${weechat_data_dir}/xmpp.omemo.db", + NULL, NULL, NULL); + if (mdb_env_open(new_omemo->db.env, path, MDB_NOSUBDIR, 0664) != 0) + { + return; + } + free(path); + + MDB_txn *parentTransaction = NULL; + MDB_txn *transaction; + if (mdb_txn_begin(new_omemo->db.env, parentTransaction, 0 ? MDB_RDONLY : 0, &transaction)) { + //Error + } + + if (0) { + mdb_txn_abort(transaction); + } else { + mdb_txn_commit(transaction); + } + + if (mdb_dbi_open(transaction, "databasename", MDB_DUPSORT | MDB_CREATE, new_omemo->db.dbi)) { + //Error + } + + struct signal_crypto_provider crypto_provider = { + .random_func = &cp_random_generator, + .hmac_sha256_init_func = &cp_hmac_sha256_init, + .hmac_sha256_update_func = &cp_hmac_sha256_update, + .hmac_sha256_final_func = &cp_hmac_sha256_final, + .hmac_sha256_cleanup_func = &cp_hmac_sha256_cleanup, + .sha512_digest_init_func = &cp_sha512_digest_init, + .sha512_digest_update_func = &cp_sha512_digest_update, + .sha512_digest_final_func = &cp_sha512_digest_final, + .sha512_digest_cleanup_func = &cp_sha512_digest_cleanup, + .encrypt_func = &cp_encrypt, + .decrypt_func = &cp_decrypt, .user_data = buffer, }; - signal_context_set_crypto_provider(global_context, &provider); - signal_context_set_locking_functions(global_context, &lock_function, &unlock_function); + signal_context_set_crypto_provider(new_omemo->context, &crypto_provider); + signal_context_set_locking_functions(new_omemo->context, &lock_function, &unlock_function); signal_protocol_key_helper_pre_key_list_node *pre_keys_head; session_signed_pre_key *signed_pre_key; int start_id = 0; time_t timestamp = time(NULL); - signal_protocol_key_helper_generate_identity_key_pair(&omemo->identity, global_context); - signal_protocol_key_helper_generate_registration_id(&omemo->device_id, 0, global_context); - signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, global_context); - signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, omemo->identity, 5, timestamp, global_context); + if (new_omemo->identity) + 0; + else + signal_protocol_key_helper_generate_identity_key_pair(&new_omemo->identity, new_omemo->context); + signal_protocol_key_helper_generate_registration_id(&new_omemo->device_id, 0, new_omemo->context); + signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, new_omemo->context); + signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, new_omemo->identity, 5, timestamp, new_omemo->context); /* Store pre keys in the pre key store. */ /* Store signed pre key in the signed pre key store. */ - omemo->context = global_context; - - return SG_SUCCESS; -} - -void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, - char **device, char **identity) -{ - struct t_omemo *new_omemo; - - new_omemo = calloc(1, sizeof(**omemo)); - - omemo__deserialize(new_omemo, *device, *identity, strlen(*identity)); + signal_protocol_store_context_create(&new_omemo->store_context, new_omemo->context); - omemo__signal_init(buffer, new_omemo); + struct signal_protocol_identity_key_store identity_key_store = { + .get_identity_key_pair = &iks_get_identity_key_pair, + .get_local_registration_id = &iks_get_local_registration_id, + .save_identity = &iks_save_identity, + .is_trusted_identity = &iks_is_trusted_identity, + .destroy_func = &iks_destroy_func, + .user_data = account_name, + }; - omemo__serialize(new_omemo, device, identity, NULL); + signal_protocol_store_context_set_identity_key_store(new_omemo->store_context, &identity_key_store); *omemo = new_omemo; } diff --git a/omemo.h b/omemo.h index db6d4b1..5a28254 100644 --- a/omemo.h +++ b/omemo.h @@ -10,6 +10,12 @@ extern const char *OMEMO_ADVICE; struct t_omemo { struct signal_context *context; + struct signal_protocol_store_context *store_context; + + struct { + struct MDB_env *env; + struct MDB_dbi *dbi; + } db; struct ratchet_identity_key_pair *identity; @@ -17,7 +23,7 @@ struct t_omemo }; void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, - char **device, char **identity); + const char *account_name); void omemo__serialize(struct t_omemo *omemo, char **device, char **identity, size_t *identity_len); diff --git a/pgp.c b/pgp.c index a879e81..9d4aed0 100644 --- a/pgp.c +++ b/pgp.c @@ -75,20 +75,20 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t if ((ret = rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason); goto encrypt_finish; } if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create output object: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create output object: %s\n", weechat_prefix("error"), reason); goto encrypt_finish; } /* create encryption operation */ if ((ret = rnp_op_encrypt_create(&encrypt, pgp->context, input, output)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create encrypt operation: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create encrypt operation: %s\n", weechat_prefix("error"), reason); goto encrypt_finish; } @@ -103,13 +103,13 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t /* locate recipient's key and add it to the operation context. */ if ((ret = rnp_locate_key(pgp->context, "keyid", target, &key)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to locate recipient key: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to locate recipient key: %s\n", weechat_prefix("error"), reason); goto encrypt_finish; } if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to add recipient: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to add recipient: %s\n", weechat_prefix("error"), reason); goto encrypt_finish; } rnp_key_handle_destroy(key); @@ -118,7 +118,7 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t /* execute encryption operation */ if ((ret = rnp_op_encrypt_execute(encrypt)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tencryption failed: %s\n", reason); + weechat_printf(buffer, "%spgp: encryption failed: %s\n", weechat_prefix("error"), reason); goto encrypt_finish; } @@ -156,19 +156,19 @@ char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *c * message */ if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason); goto decrypt_finish; } if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create output object: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create output object: %s\n", weechat_prefix("error"), reason); goto decrypt_finish; } if ((ret = rnp_decrypt(pgp->context, input, output)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tpublic-key decryption failed: %s\n", reason); + weechat_printf(buffer, "%spgp: public-key decryption failed: %s\n", weechat_prefix("error"), reason); goto decrypt_finish; } free(buf); @@ -204,19 +204,19 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce /* create file input memory objects for the signed message and verified message */ if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason); goto verify_finish; } if ((ret = rnp_input_from_memory(&signature, buf, buf_len, false)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason); goto verify_finish; } if ((ret = rnp_op_verify_detached_create(&verify, pgp->context, input, signature)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to create verification context: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to create verification context: %s\n", weechat_prefix("error"), reason); goto verify_finish; } @@ -226,14 +226,14 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce // ) != RNP_ERROR_SIGNATURE_INVALID) // if (ret != RNP_ERROR_SIGNATURE_INVALID) { // const char *reason = rnp_result_to_string(ret); - // weechat_printf(buffer, "[PGP]\tfailed to execute verification operation: %s\n", reason); + // weechat_printf(buffer, "%spgp: failed to execute verification operation: %s\n", weechat_prefix("error"), reason); // goto verify_finish; // } /* now check signatures and get some info about them */ if ((ret = rnp_op_verify_get_signature_count(verify, &sigcount)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get signature count: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to get signature count: %s\n", weechat_prefix("error"), reason); goto verify_finish; } @@ -245,14 +245,14 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce if ((ret = rnp_op_verify_get_signature_at(verify, i, &sig)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get signature %d: %s\n", (int)i, reason); + weechat_printf(buffer, "%spgp: failed to get signature %d: %s\n", weechat_prefix("error"), (int)i, reason); goto verify_finish; } if ((ret = rnp_op_verify_signature_get_key(sig, &key)) == RNP_SUCCESS) { if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get key id %d: %s\n", (int)i, reason); + weechat_printf(buffer, "%spgp: failed to get key id %d: %s\n", weechat_prefix("error"), (int)i, reason); rnp_key_handle_destroy(key); goto verify_finish; } @@ -260,7 +260,7 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce if ((ret = rnp_key_get_signature_at(key, 0, &signature)) == RNP_SUCCESS) { if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to get key id: %s\n", weechat_prefix("error"), reason); rnp_key_handle_destroy(key); goto verify_finish; } @@ -269,13 +269,13 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce } else { if ((ret = rnp_op_verify_signature_get_handle(sig, &signature)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get signature's %d handle: %s\n", (int)i, reason); + weechat_printf(buffer, "%spgp: failed to get signature's %d handle: %s\n", weechat_prefix("error"), (int)i, reason); goto verify_finish; } if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); - weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason); + weechat_printf(buffer, "%spgp: failed to get key id: %s\n", weechat_prefix("error"), reason); rnp_key_handle_destroy(key); goto verify_finish; } @@ -309,18 +309,18 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour * message */ if (rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false) != RNP_SUCCESS) { - weechat_printf(buffer, "[PGP]\tfailed to create input object\n"); + weechat_printf(buffer, "%spgp: failed to create input object\n", weechat_prefix("error")); goto sign_finish; } if (rnp_output_to_memory(&output, 0) != RNP_SUCCESS) { - weechat_printf(buffer, "[PGP]\tfailed to create output object\n"); + weechat_printf(buffer, "%spgp: failed to create output object\n", weechat_prefix("error")); goto sign_finish; } /* initialize and configure sign operation */ if (rnp_op_sign_detached_create(&sign, pgp->context, input, output) != RNP_SUCCESS) { - weechat_printf(buffer, "[PGP]\tfailed to create sign operation\n"); + weechat_printf(buffer, "%spgp: failed to create sign operation\n", weechat_prefix("error")); goto sign_finish; } @@ -338,12 +338,12 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour /* now add signatures. First locate the signing key, then add and setup signature */ if (rnp_locate_key(pgp->context, "keyid", source, &key) != RNP_SUCCESS) { - weechat_printf(buffer, "[PGP]\tfailed to locate signing key: %s\n", source); + weechat_printf(buffer, "%spgp: failed to locate signing key: %s\n", weechat_prefix("error"), source); goto sign_finish; } if (rnp_op_sign_add_signature(sign, key, NULL) != RNP_SUCCESS) { - weechat_printf(buffer, "[PGP]\tfailed to add signature for key: %s\n", source); + weechat_printf(buffer, "%spgp: failed to add signature for key: %s\n", weechat_prefix("error"), source); goto sign_finish; } @@ -352,7 +352,7 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour /* finally do signing */ if (rnp_op_sign_execute(sign) != RNP_SUCCESS) { - weechat_printf(buffer, "[PGP]\tfailed to sign with key: %s\n", source); + weechat_printf(buffer, "%spgp: failed to sign with key: %s\n", weechat_prefix("error"), source); goto sign_finish; } diff --git a/user.c b/user.c index 50abe1c..5d9ed62 100644 --- a/user.c +++ b/user.c @@ -53,18 +53,18 @@ const char *user__as_prefix(struct t_account *account, } struct t_user *user__bot_search(struct t_account *account, - const char *bot_id) + const char *pgp_id) { struct t_user *ptr_user; - if (!account || !bot_id) + if (!account || !pgp_id) return NULL; for (ptr_user = account->users; ptr_user; ptr_user = ptr_user->next_user) { - if (ptr_user->profile.bot_id && - weechat_strcasecmp(ptr_user->profile.bot_id, bot_id) == 0) + if (ptr_user->profile.pgp_id && + weechat_strcasecmp(ptr_user->profile.pgp_id, pgp_id) == 0) return ptr_user; } @@ -102,15 +102,28 @@ void user__nicklist_add(struct t_account *account, ptr_buffer = channel ? channel->buffer : account->buffer; - ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, - user->is_away ? - "+" : "..."); + char *group = "..."; + if (weechat_strcasecmp(user->profile.affiliation, "outcast") == 0) + group = "!"; + if (weechat_strcasecmp(user->profile.role, "visitor") == 0) + group = "?"; + if (weechat_strcasecmp(user->profile.role, "participant") == 0) + group = "+"; + if (weechat_strcasecmp(user->profile.affiliation, "member") == 0) + group = "%"; + if (weechat_strcasecmp(user->profile.role, "moderator") == 0) + group = "@"; + if (weechat_strcasecmp(user->profile.affiliation, "admin") == 0) + group = "&"; + if (weechat_strcasecmp(user->profile.affiliation, "owner") == 0) + group = "~"; + ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, group); weechat_nicklist_add_nick(ptr_buffer, ptr_group, name, user->is_away ? "weechat.color.nicklist_away" : user__get_colour_for_nicklist(user), - user->is_away ? "+" : "", + group, "bar_fg", 1); } @@ -119,7 +132,7 @@ void user__nicklist_remove(struct t_account *account, struct t_channel *channel, struct t_user *user) { - struct t_gui_nick_group *ptr_group; + struct t_gui_nick *ptr_nick; struct t_gui_buffer *ptr_buffer; char *name = user->profile.display_name; if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name), @@ -128,11 +141,8 @@ void user__nicklist_remove(struct t_account *account, ptr_buffer = channel ? channel->buffer : account->buffer; - ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, - user->is_away ? - "+" : "..."); - weechat_nicklist_remove_nick(ptr_buffer, - weechat_nicklist_search_nick(ptr_buffer, ptr_group, name)); + if ((ptr_nick = weechat_nicklist_search_nick(ptr_buffer, NULL, name))) + weechat_nicklist_remove_nick(ptr_buffer, ptr_nick); } struct t_user *user__new(struct t_account *account, @@ -173,14 +183,14 @@ struct t_user *user__new(struct t_account *account, new_user->profile.avatar_hash = NULL; new_user->profile.status_text = NULL; - new_user->profile.status_emoji = NULL; + new_user->profile.status = NULL; new_user->profile.real_name = NULL; new_user->profile.display_name = display_name ? strdup(display_name) : strdup(""); - new_user->profile.real_name_normalized = NULL; + new_user->profile.affiliation = NULL; new_user->profile.email = NULL; - new_user->profile.team = NULL; - new_user->profile.bot_id = NULL; + new_user->profile.role = NULL; + new_user->profile.pgp_id = NULL; new_user->updated = 0; new_user->is_away = 0; @@ -220,18 +230,18 @@ void user__free(struct t_account *account, free(user->profile.avatar_hash); if (user->profile.status_text) free(user->profile.status_text); - if (user->profile.status_emoji) - free(user->profile.status_emoji); + if (user->profile.status) + free(user->profile.status); if (user->profile.real_name) free(user->profile.real_name); if (user->profile.display_name) free(user->profile.display_name); - if (user->profile.real_name_normalized) - free(user->profile.real_name_normalized); + if (user->profile.affiliation) + free(user->profile.affiliation); if (user->profile.email) free(user->profile.email); - if (user->profile.team) - free(user->profile.team); + if (user->profile.role) + free(user->profile.role); free(user); diff --git a/user.h b/user.h index 30c6440..74c3654 100644 --- a/user.h +++ b/user.h @@ -9,13 +9,13 @@ struct t_user_profile { char *avatar_hash; char *status_text; - char *status_emoji; + char *status; char *real_name; char *display_name; - char *real_name_normalized; char *email; - char *team; - char *bot_id; + char *role; + char *affiliation; + char *pgp_id; }; struct t_user @@ -41,9 +41,6 @@ const char *user__as_prefix(struct t_account *account, struct t_user *user, const char *name); -struct t_user *user__bot_search(struct t_account *account, - const char *bot_id); - struct t_user *user__search(struct t_account *account, const char *id); From 5eca4ac37cb207c4989a9259c1be0ccb203439d6 Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Thu, 29 Jul 2021 04:06:48 +0100 Subject: [PATCH 118/118] omemo progress++ --- .envrc | 2 +- README.org | 8 + account.c | 93 +++++++ account.h | 24 ++ channel.c | 74 +++++- channel.h | 2 +- command.c | 2 +- config.c | 29 +- connection.c | 46 +++- omemo.c | 740 +++++++++++++++++++++++++++++++++++++++++++-------- omemo.h | 5 +- pgp.c | 17 +- pgp.h | 2 +- user.c | 6 +- user.h | 2 +- 15 files changed, 908 insertions(+), 144 deletions(-) diff --git a/.envrc b/.envrc index f2874d4..aeb2bc0 100644 --- a/.envrc +++ b/.envrc @@ -40,7 +40,7 @@ use_guix() libtool # Deps with libtool make # Makefile and deps with makefiles cmake # Deps with cmake - gcc-toolchain # Compilation + gcc-toolchain@11 # Compilation pkg-config # Deps configuration and configuration of deps deps patchelf # Fix linkage (guix) bear # Generate compile_commands.json for language servers diff --git a/README.org b/README.org index d4815c5..200c7c1 100644 --- a/README.org +++ b/README.org @@ -28,6 +28,9 @@ A weechat plugin in C to extend the chat client to support XMPP and a currently minimal but ideally maximal set of XEPs. + My priority here is to have an android-available XMPP client + that hides as little as possible from the user. To use this with + android, set up a relay (`/relay`) and see weechat-android. I'm gonna rewrite this in C++ at some point when I have a feel for the full behaviour of an average client. @@ -132,6 +135,11 @@ * [X] [#A] Recv typing notifications * [X] [#C] Read receipts * [X] Chat Markers (XEP-0333) + * [X] Composing + * [X] Paused + * [?] Active + * [ ] Inactive + * [ ] Gone * [X] Message Delivery (XEP-0184) * [X] Message Carbons * [ ] Service Disco diff --git a/account.c b/account.c index ab4464c..d6a449e 100644 --- a/account.c +++ b/account.c @@ -165,6 +165,95 @@ void account__free_device_all(struct t_account *account) account__free_device(account, account->devices); } +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 = 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) { @@ -304,6 +393,8 @@ struct t_account *account__alloc(const char *name) 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; @@ -364,6 +455,8 @@ void account__free_data(struct t_account *account) 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); diff --git a/account.h b/account.h index 575996f..4234749 100644 --- a/account.h +++ b/account.h @@ -73,6 +73,19 @@ struct t_account_device struct t_account_device *next_device; }; +struct t_account_mam_query +{ + char *id; + char *with; + int has_start; + time_t start; + int has_end; + time_t end; + + struct t_account_mam_query *prev_mam_query; + struct t_account_mam_query *next_mam_query; +}; + struct t_account { char *name; @@ -99,6 +112,8 @@ struct t_account 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; @@ -117,6 +132,15 @@ struct t_account_device *account__search_device(struct t_account *account, int i 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); +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); diff --git a/channel.c b/channel.c index a60b21f..8577aae 100644 --- a/channel.c +++ b/channel.c @@ -314,7 +314,7 @@ struct t_channel *channel__new(struct t_account *account, struct tm *ago = gmtime(&start); ago->tm_mday -= 7; start = mktime(ago); - channel__fetch_mam(account, new_channel, &start, NULL); + channel__fetch_mam(account, new_channel, NULL, &start, NULL, NULL); } return new_channel; @@ -886,7 +886,7 @@ struct t_channel_member *channel__add_member(struct t_account *account, client ? ")" : "", user->profile.status ? "is " : "", weechat_color("irc.color.message_join"), - user->profile.status ? user->profile.status : "entered", + user->profile.status ? user->profile.status : (user->profile.idle ? "idle" : "entered"), weechat_color("reset"), channel->id, user->profile.status_text ? " [" : "", @@ -901,15 +901,16 @@ 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", + 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_prefix("join"), jid_resource ? user__as_prefix_raw(account, jid_bare) : "You", jid_resource ? jid_resource : user__as_prefix_raw(account, jid_bare), user->profile.status ? "is " : "", weechat_color("irc.color.message_join"), - user->profile.status ? user->profile.status : "entered", + user->profile.status ? user->profile.status : (user->profile.idle ? "idle" : "entered"), weechat_color("reset"), - channel->id, + user->profile.idle ? "since " : "", + user->profile.idle ? user->profile.idle : "", user->profile.status_text ? " [" : "", user->profile.status_text ? user->profile.status_text : "", user->profile.status_text ? "]" : "", @@ -996,8 +997,6 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_set_id(message, id); xmpp_free(account->context, id); - xmpp_message_set_body(message, body); - char *url = strstr(body, "http"); if (channel->pgp_id) { @@ -1006,7 +1005,7 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, 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, channel->pgp_id, body); + char *ciphertext = pgp__encrypt(channel->buffer, account->pgp, account_pgp_keyid(account), channel->pgp_id, body); if (ciphertext) xmpp_stanza_set_text(message__x__text, ciphertext); free(ciphertext); @@ -1017,6 +1016,14 @@ void 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_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"); + + xmpp_stanza_add_child(message, message__encryption); + xmpp_stanza_release(message__encryption); + xmpp_message_set_body(message, PGP_ADVICE); if (ciphertext && channel->transport != CHANNEL_TRANSPORT_PGP) @@ -1027,12 +1034,17 @@ void channel__send_message(struct t_account *account, struct t_channel *channel, channel__transport_name(channel->transport)); } } - else if (channel->transport != CHANNEL_TRANSPORT_PLAINTEXT) + else { - channel->transport = CHANNEL_TRANSPORT_PLAINTEXT; - weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s", - weechat_prefix("network"), weechat_color("gray"), - channel__transport_name(channel->transport)); + xmpp_message_set_body(message, body); + + if (channel->transport != CHANNEL_TRANSPORT_PLAINTEXT) + { + channel->transport = CHANNEL_TRANSPORT_PLAINTEXT; + weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s", + weechat_prefix("network"), weechat_color("gray"), + channel__transport_name(channel->transport)); + } } if (url) @@ -1056,6 +1068,13 @@ void 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_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_send(account->connection, message); xmpp_stanza_release(message); if (channel->type != CHANNEL_TYPE_MUC) @@ -1157,9 +1176,10 @@ void channel__send_paused(struct t_account *account, struct t_channel *channel, } void channel__fetch_mam(struct t_account *account, struct t_channel *channel, - time_t *start, time_t *end) + 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 *query = xmpp_stanza_new(account->context); xmpp_stanza_set_name(query, "query"); @@ -1262,6 +1282,32 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, xmpp_stanza_add_child(query, x); xmpp_stanza_release(x); + if (after) + { + xmpp_stanza_t *set, *set__after, *set__after__text; + + 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); + xmpp_stanza_set_name(set__after, "after"); + + 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); + + xmpp_stanza_add_child(set, set__after); + xmpp_stanza_release(set__after); + + xmpp_stanza_add_child(query, set); + xmpp_stanza_release(set); + } + else + account__add_mam_query(account, channel, + xmpp_stanza_get_id(iq), start, end); + xmpp_stanza_add_child(iq, query); xmpp_stanza_release(query); diff --git a/channel.h b/channel.h index c336ee2..37863f1 100644 --- a/channel.h +++ b/channel.h @@ -191,6 +191,6 @@ 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, - time_t *start, time_t *end); + const char *id, time_t *start, time_t *end, const char *after); #endif /*WEECHAT_XMPP_CHANNEL_H*/ diff --git a/command.c b/command.c index 84c90ed..57c7019 100644 --- a/command.c +++ b/command.c @@ -752,7 +752,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, &start, NULL); + channel__fetch_mam(ptr_account, ptr_channel, NULL, &start, NULL, NULL); return WEECHAT_RC_OK; } diff --git a/config.c b/config.c index 0686d10..fc89b78 100644 --- a/config.c +++ b/config.c @@ -21,8 +21,8 @@ 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) + struct t_config_option *option, + const char *value) { (void) pointer; (void) data; @@ -33,15 +33,32 @@ int config__account_check_value_cb(const void *pointer, void *data, } void config__account_change_cb(const void *pointer, void *data, - struct t_config_option *option) + struct t_config_option *option) { (void) pointer; (void) data; - (void) option; + + const char *name = + weechat_config_option_get_string(option, "name"); + const char *value = + weechat_config_option_get_string(option, "value"); + + int split_num; + char **split = weechat_string_split(name, ".", NULL, 0, 2, &split_num); + struct t_account *account = account__search(split[0]); + if (split_num >= 2 && account) + { + const char *key = split[1]; + + (void) key; + (void) value; + } + + weechat_string_free_split(split); } void config__account_default_change_cb(const void *pointer, void *data, - struct t_config_option *option) + struct t_config_option *option) { (void) pointer; (void) data; @@ -346,7 +363,7 @@ int config__account_read_cb (const void *pointer, void *data, return rc; } -int config__account_write_cb (const void *pointer, void *data, +int config__account_write_cb(const void *pointer, void *data, struct t_config_file *config_file, const char *section_name) { diff --git a/connection.c b/connection.c index afb0683..16b5dbb 100644 --- a/connection.c +++ b/connection.c @@ -86,9 +86,9 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void struct t_account *account = (struct t_account *)userdata; struct t_user *user; struct t_channel *channel; - xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *show, *iq__x__item, *iq__c, *iq__status; + xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *show, *idle, *iq__x__item, *iq__c, *iq__status; const char *from, *from_bare, *from_res, *type, *role = NULL, *affiliation = NULL, *jid = NULL; - const char *show__text = NULL, *certificate = NULL, *node = NULL, *ver = NULL; + const char *show__text = NULL, *idle__since = NULL, *certificate = NULL, *node = NULL, *ver = NULL; char *clientid = NULL, *status; from = xmpp_stanza_get_from(stanza); @@ -99,6 +99,8 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void type = xmpp_stanza_get_type(stanza); show = xmpp_stanza_get_child_by_name(stanza, "show"); show__text = show ? xmpp_stanza_get_text(show) : NULL; + idle = xmpp_stanza_get_child_by_name_and_ns(stanza, "idle", "urn:xmpp:idle:1"); + idle__since = idle ? xmpp_stanza_get_attribute(idle, "since") : NULL; iq__x_signed = xmpp_stanza_get_child_by_name_and_ns( stanza, "x", "jabber:x:signed"); if (iq__x_signed) @@ -145,6 +147,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void ? from_res : from); user->profile.status_text = status ? strdup(status) : NULL; user->profile.status = show ? strdup(show__text) : NULL; + user->profile.idle = idle ? strdup(idle__since) : NULL; user->is_away = show ? weechat_strcasecmp(show__text, "away") == 0 : 0; user->profile.role = role ? strdup(role) : NULL; user->profile.affiliation = affiliation && strcmp(affiliation, "none") != 0 @@ -173,6 +176,8 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void ? from_res : from); user->profile.status_text = status ? strdup(status) : NULL; user->profile.status = show ? strdup(show__text) : NULL; + user->profile.idle = idle ? strdup(idle__since) : NULL; + user->is_away = show ? weechat_strcasecmp(show__text, "away") == 0 : 0; user->profile.role = role ? strdup(role) : NULL; user->profile.affiliation = affiliation && strcmp(affiliation, "none") != 0 ? strdup(affiliation) : NULL; @@ -602,14 +607,13 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { - (void) conn; - struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; + xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text, *fin; xmpp_stanza_t *pubsub, *items, *item, *list, *device, **children; xmpp_stanza_t *storage, *conference, *nick; static struct utsname osinfo; + const char *id = xmpp_stanza_get_id(stanza); query = xmpp_stanza_get_child_by_name_and_ns( stanza, "query", "http://jabber.org/protocol/disco#info"); const char *type = xmpp_stanza_get_attribute(stanza, "type"); @@ -1023,6 +1027,38 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd } } + fin = xmpp_stanza_get_child_by_name_and_ns( + stanza, "fin", "urn:xmpp:mam:2"); + if (fin) + { + xmpp_stanza_t *set, *set__last; + char *set__last__text; + struct t_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) + { + struct t_channel *channel = channel__search(account, + mam_query->with); + + 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) + { + channel__fetch_mam(account, channel, id, + mam_query->has_start ? &mam_query->start : NULL, + mam_query->has_end ? &mam_query->end : NULL, + set__last__text); + } + else if (!set__last) + account__mam_query_free(account, mam_query); + } + } + return 1; } diff --git a/omemo.c b/omemo.c index 63134cc..811a508 100644 --- a/omemo.c +++ b/omemo.c @@ -9,32 +9,36 @@ #include #include #include +#include #include #include #include +struct t_omemo_db { + MDB_env *env; + MDB_dbi dbi_omemo; +}; + #include "plugin.h" #include "account.h" #include "omemo.h" -const char *OMEMO_ADVICE = "[OMEMO encrypted message (XEP-0384)]"; +#define mdb_val_str(s) { \ + .mv_data = s, .mv_size = strlen(s), \ +} -signal_type_base* signal_type_ref_vapi(void* instance) { - if (!(instance != NULL)) - return NULL; - signal_type_ref(instance); - return instance; +#define mdb_val_intptr(i) { \ + .mv_data = i, .mv_size = sizeof(*i), \ } -signal_type_base* signal_type_unref_vapi(void* instance) { - if (!(instance != NULL)) - return NULL; - signal_type_unref(instance); - return NULL; +#define mdb_val_sizeof(t) { \ + .mv_data = NULL, .mv_size = sizeof(t), \ } +const char *OMEMO_ADVICE = "[OMEMO encrypted message (XEP-0384)]"; + void signal_protocol_address_free(signal_protocol_address* ptr) { - if (!(ptr != NULL)) + if (!ptr) return; if (ptr->name) { free((void*)ptr->name); @@ -43,9 +47,9 @@ void signal_protocol_address_free(signal_protocol_address* ptr) { } void signal_protocol_address_set_name(signal_protocol_address* self, const char* name) { - if (!(self != NULL)) + if (!self) return; - if (!(name != NULL)) + if (!name) return; char* n = malloc(strlen(name)+1); memcpy(n, name, strlen(name)); @@ -58,9 +62,9 @@ void signal_protocol_address_set_name(signal_protocol_address* self, const char* } char* signal_protocol_address_get_name(signal_protocol_address* self) { - if (!(self != NULL)) + if (!self) return NULL; - if (!(self->name != NULL)) + if (!self->name) return 0; char* res = malloc(sizeof(char) * (self->name_len + 1)); memcpy(res, self->name, self->name_len); @@ -69,19 +73,19 @@ char* signal_protocol_address_get_name(signal_protocol_address* self) { } int32_t signal_protocol_address_get_device_id(signal_protocol_address* self) { - if (!(self != NULL)) + if (!self) return -1; return self->device_id; } void signal_protocol_address_set_device_id(signal_protocol_address* self, int32_t device_id) { - if (!(self != NULL)) + if (!self) return; self->device_id = device_id; } signal_protocol_address* signal_protocol_address_new(const char* name, int32_t device_id) { - if (!(name != NULL)) + if (!name) return NULL; signal_protocol_address* address = malloc(sizeof(signal_protocol_address)); address->device_id = -1; @@ -91,6 +95,43 @@ signal_protocol_address* signal_protocol_address_new(const char* name, int32_t d return address; } +int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) { + switch (key_len) { + case 16: + *algo = GCRY_CIPHER_AES128; + break; + case 24: + *algo = GCRY_CIPHER_AES192; + break; + case 32: + *algo = GCRY_CIPHER_AES256; + break; + default: + return SG_ERR_UNKNOWN; + } + switch (cipher) { + case SG_CIPHER_AES_CBC_PKCS5: + *mode = GCRY_CIPHER_MODE_CBC; + break; + case SG_CIPHER_AES_CTR_NOPADDING: + *mode = GCRY_CIPHER_MODE_CTR; + break; + default: + return SG_ERR_UNKNOWN; + } + return SG_SUCCESS; +} + +void lock_function(void *user_data) +{ + (void) user_data; +} + +void unlock_function(void *user_data) +{ + (void) user_data; +} + int cp_randomize(uint8_t *data, size_t len) { gcry_randomize(data, len, GCRY_STRONG_RANDOM); return SG_SUCCESS; @@ -217,33 +258,6 @@ void cp_sha512_digest_cleanup(void *digest_context, void *user_data) { } } -int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) { - switch (key_len) { - case 16: - *algo = GCRY_CIPHER_AES128; - break; - case 24: - *algo = GCRY_CIPHER_AES192; - break; - case 32: - *algo = GCRY_CIPHER_AES256; - break; - default: - return SG_ERR_UNKNOWN; - } - switch (cipher) { - case SG_CIPHER_AES_CBC_PKCS5: - *mode = GCRY_CIPHER_MODE_CBC; - break; - case SG_CIPHER_AES_CTR_NOPADDING: - *mode = GCRY_CIPHER_MODE_CTR; - break; - default: - return SG_ERR_UNKNOWN; - } - return SG_SUCCESS; -} - int cp_encrypt(signal_buffer **output, int cipher, const uint8_t *key, size_t key_len, @@ -391,70 +405,548 @@ no_error: return SG_SUCCESS; } -void lock_function(void *user_data) +int iks_get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data) +{ + struct t_omemo *omemo = (struct t_omemo *)user_data; + MDB_txn *transaction; + MDB_val k_local_private_key = mdb_val_str("local_private_key"); + MDB_val k_local_public_key = mdb_val_str("local_public_key"); + MDB_val v_local_private_key, v_local_public_key; + + // Get the local client's identity key pair + if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + } + + if (mdb_get(transaction, omemo->db->dbi_omemo, + &k_local_private_key, &v_local_private_key) && + mdb_get(transaction, omemo->db->dbi_omemo, + &k_local_public_key, &v_local_public_key)) + { + *private_data = signal_buffer_create(v_local_private_key.mv_data, v_local_private_key.mv_size); + *public_data = signal_buffer_create(v_local_public_key.mv_data, v_local_public_key.mv_size); + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + } + else + { + struct ratchet_identity_key_pair *identity; + + mdb_txn_abort(transaction); + + if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + signal_protocol_key_helper_generate_identity_key_pair( + &identity, omemo->context); + ec_private_key *private_key = ratchet_identity_key_pair_get_private(identity); + ec_public_key *public_key = ratchet_identity_key_pair_get_public(identity); + + ec_private_key_serialize(private_data, private_key); + ec_public_key_serialize(public_data, public_key); + + v_local_private_key.mv_data = signal_buffer_data(*private_data); + v_local_private_key.mv_size = signal_buffer_len(*private_data); + v_local_public_key.mv_data = signal_buffer_data(*public_data); + v_local_public_key.mv_size = signal_buffer_len(*public_data); + + if (mdb_put(transaction, omemo->db->dbi_omemo, + &k_local_private_key, &v_local_private_key, MDB_NOOVERWRITE) && + mdb_put(transaction, omemo->db->dbi_omemo, + &k_local_public_key, &v_local_public_key, MDB_NOOVERWRITE)) + { + weechat_printf(NULL, "%sxmpp: failed to write lmdb value", + weechat_prefix("error")); + return -1; + }; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + } + + return 0; +} + +int iks_get_local_registration_id(void *user_data, uint32_t *registration_id) +{ + struct t_omemo *omemo = (struct t_omemo *)user_data; + MDB_txn *transaction; + MDB_val k_local_registration_id = mdb_val_str("local_registration_id"); + MDB_val v_local_registration_id = mdb_val_sizeof(uint32_t); + + // Return the local client's registration ID + if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + if (mdb_get(transaction, omemo->db->dbi_omemo, + &k_local_registration_id, + &v_local_registration_id)) + { + *registration_id = *(uint32_t*)v_local_registration_id.mv_data; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + } + else + { + mdb_txn_abort(transaction); + + if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + signal_protocol_key_helper_generate_registration_id( + (uint32_t*)&v_local_registration_id.mv_data, 0, omemo->context); + + if (mdb_put(transaction, omemo->db->dbi_omemo, + &k_local_registration_id, + &v_local_registration_id, MDB_NOOVERWRITE)) + { + weechat_printf(NULL, "%sxmpp: failed to write lmdb value", + weechat_prefix("error")); + return -1; + }; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + } + + return 0; +} + +int iks_save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data) +{ + struct t_omemo *omemo = (struct t_omemo *)user_data; + MDB_txn *transaction; + MDB_val k_registration_id = { + .mv_data = NULL, + .mv_size = strlen("registration_id_") + address->name_len, + }; + MDB_val v_registration_id = mdb_val_intptr((uint32_t*)&address->device_id); + MDB_val k_identity_key = { + .mv_data = NULL, + .mv_size = strlen("identity_key_") + address->name_len, + }; + MDB_val v_identity_key = {.mv_data = key_data, .mv_size = key_len}; + + k_registration_id.mv_data = malloc(sizeof(char) * ( + k_registration_id.mv_size + 1)); + snprintf(k_registration_id.mv_data, k_registration_id.mv_size, + "registration_id_%s", address->name); + k_identity_key.mv_data = malloc(sizeof(char) * ( + k_identity_key.mv_size + 1)); + snprintf(k_identity_key.mv_data, k_identity_key.mv_size, + "identity_key_%s", address->name); + + // Save a remote client's identity key + if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + if (mdb_put(transaction, omemo->db->dbi_omemo, &k_registration_id, + &v_registration_id, 0) || + mdb_put(transaction, omemo->db->dbi_omemo, &k_identity_key, + &v_identity_key, 0)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb value", + weechat_prefix("error")); + return -1; + }; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + + return 0; +} + +int iks_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data) +{ + struct t_omemo *omemo = (struct t_omemo *)user_data; + MDB_txn *transaction; + MDB_val k_registration_id = { + .mv_data = NULL, + .mv_size = strlen("registration_id_") + address->name_len, + }; + MDB_val v_registration_id = mdb_val_intptr((uint32_t*)&address->device_id); + MDB_val k_identity_key = { + .mv_data = NULL, + .mv_size = strlen("identity_key_") + address->name_len, + }; + MDB_val v_identity_key = {.mv_data = key_data, .mv_size = key_len}; + int trusted = 1; + + k_registration_id.mv_data = malloc(sizeof(char) * ( + k_registration_id.mv_size + 1)); + snprintf(k_registration_id.mv_data, k_registration_id.mv_size, + "registration_id_%s", address->name); + k_identity_key.mv_data = malloc(sizeof(char) * ( + k_identity_key.mv_size + 1)); + snprintf(k_identity_key.mv_data, k_identity_key.mv_size, + "identity_key_%s", address->name); + + // Verify a remote client's identity key + if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + if (mdb_get(transaction, omemo->db->dbi_omemo, &k_registration_id, + &v_registration_id) || + mdb_get(transaction, omemo->db->dbi_omemo, &k_identity_key, + &v_identity_key)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb value", + weechat_prefix("error")); + return -1; + }; + + if (*(uint32_t*)v_registration_id.mv_data != (uint32_t)address->device_id) + trusted = 0; + if (v_identity_key.mv_size != key_len || + memcmp(v_identity_key.mv_data, key_data, key_len) != 0) + trusted = 0; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + + return trusted; +} + +void iks_destroy_func(void *user_data) +{ + struct t_omemo *omemo = (struct t_omemo *)user_data; + (void) omemo; + // Function called to perform cleanup when the data store context is being destroyed +} + +int pks_load_pre_key(signal_buffer **record, uint32_t pre_key_id, void *user_data) { + struct t_omemo *omemo = (struct t_omemo *)user_data; + MDB_txn *transaction; + MDB_val k_pre_key = mdb_val_str("pre_key"); + MDB_val v_pre_key; + + if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + } + + if (mdb_get(transaction, omemo->db->dbi_omemo, + &k_pre_key, &v_pre_key)) + { + *record = signal_buffer_create(v_pre_key.mv_data, v_pre_key.mv_size); + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to close lmdb transaction", + weechat_prefix("error")); + return -1; + }; + } + else + { + signal_protocol_key_helper_pre_key_list_node *pre_keys_list; + session_pre_key *pre_key = NULL; + + mdb_txn_abort(transaction); + + /* + signal_protocol_key_helper_generate_pre_keys( + &pre_keys_list, 0, 100, omemo->context); + pre_key = signal_protocol_key_helper_key_list_element(pre_keys_list); + signal_protocol_key_helper_key_list_next(pre_keys_list); + + uint32_t id = session_pre_key_get_id(pre_key); + session_pre_key_serialize(&record, pre_key); + + signal_protocol_key_helper_key_list_free(pre_keys_list); + + if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + v_pre_key.mv_data = signal_buffer_data(*record); + v_pre_key.mv_size = signal_buffer_len(*record); + + if (mdb_put(transaction, omemo->db->dbi_omemo, + &k_pre_key, &v_pre_key, MDB_NOOVERWRITE)) + { + weechat_printf(NULL, "%sxmpp: failed to write lmdb value", + weechat_prefix("error")); + return -1; + }; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + */ + return -1; + } + + return 0; +} + +int pks_store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len, void *user_data) +{ + (void) pre_key_id; + (void) record; + (void) record_len; (void) user_data; + return -1; + struct t_omemo *omemo = (struct t_omemo *)user_data; + MDB_txn *transaction; + MDB_val k_pre_key = mdb_val_str("pre_key"); + MDB_val v_pre_key; + + if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + } + + if (mdb_get(transaction, omemo->db->dbi_omemo, + &k_pre_key, &v_pre_key)) + { + *record = signal_buffer_create(v_pre_key.mv_data, v_pre_key.mv_size); + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to close lmdb transaction", + weechat_prefix("error")); + return -1; + }; + } + else + { + signal_protocol_key_helper_pre_key_list_node *pre_keys_list; + session_pre_key *pre_key = NULL; + + mdb_txn_abort(transaction); + + /* + signal_protocol_key_helper_generate_pre_keys( + &pre_keys_list, 0, 100, omemo->context); + pre_key = signal_protocol_key_helper_key_list_element(pre_keys_list); + signal_protocol_key_helper_key_list_next(pre_keys_list); + + uint32_t id = session_pre_key_get_id(pre_key); + session_pre_key_serialize(&record, pre_key); + + signal_protocol_key_helper_key_list_free(pre_keys_list); + + if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); + return -1; + } + + v_pre_key.mv_data = signal_buffer_data(*record); + v_pre_key.mv_size = signal_buffer_len(*record); + + if (mdb_put(transaction, omemo->db->dbi_omemo, + &k_pre_key, &v_pre_key, MDB_NOOVERWRITE)) + { + weechat_printf(NULL, "%sxmpp: failed to write lmdb value", + weechat_prefix("error")); + return -1; + }; + + if (mdb_txn_commit(transaction)) { + weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction", + weechat_prefix("error")); + return -1; + }; + */ + return -1; + } + + return 0; } -void unlock_function(void *user_data) +int pks_contains_pre_key(uint32_t pre_key_id, void *user_data) { + (void) pre_key_id; (void) user_data; + return -1; } -void omemo__log_emit_weechat(int level, const char *message, size_t len, void *user_data) +int pks_remove_pre_key(uint32_t pre_key_id, void *user_data) { - struct t_gui_buffer *buffer = (struct t_gui_buffer*)user_data; + (void) pre_key_id; + (void) user_data; + return -1; +} - static const char *log_level_name[5] = {"error", "warn", "notice", "info", "debug"}; +void pks_destroy_func(void *user_data) +{ + (void) user_data; +} - const char *tags = level < SG_LOG_DEBUG ? "no_log" : NULL; +int spks_load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_id, void *user_data) +{ + (void) record; + (void) signed_pre_key_id; + (void) user_data; + return -1; + //session_signed_pre_key *signed_pre_key; + //int start_id = 0; + //time_t timestamp = time(NULL); + //signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, new_omemo->identity, 5, timestamp, new_omemo->context); +} - weechat_printf_date_tags( - buffer, 0, tags, - _("%somemo (%s): %.*s"), - weechat_prefix("network"), - log_level_name[level], len, message); +int spks_store_signed_pre_key(uint32_t signed_pre_key_id, uint8_t *record, size_t record_len, void *user_data) +{ + (void) signed_pre_key_id; + (void) record; + (void) record_len; + (void) user_data; + return -1; } -int iks_get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data) +int spks_contains_signed_pre_key(uint32_t signed_pre_key_id, void *user_data) { - (void) public_data; - (void) private_data; + (void) signed_pre_key_id; (void) user_data; - // Get the local client's identity key pair + return -1; } -int iks_get_local_registration_id(void *user_data, uint32_t *registration_id) +int spks_remove_signed_pre_key(uint32_t signed_pre_key_id, void *user_data) { + (void) signed_pre_key_id; (void) user_data; - (void) registration_id; - // Return the local client's registration ID + return -1; } -int iks_save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data) +void spks_destroy_func(void *user_data) { + (void) user_data; +} + +int ss_load_session_func(signal_buffer **record, signal_buffer **user_record, const signal_protocol_address *address, void *user_data) +{ + (void) record; + (void) user_record; (void) address; - (void) key_data; - (void) key_len; (void) user_data; - // Save a remote client's identity key + return -1; } -int iks_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data) +int ss_get_sub_device_sessions_func(signal_int_list **sessions, const char *name, size_t name_len, void *user_data) +{ + (void) sessions; + (void) name; + (void) name_len; + (void) user_data; + return -1; +} + +int ss_store_session_func(const signal_protocol_address *address, uint8_t *record, size_t record_len, uint8_t *user_record, size_t user_record_len, void *user_data) { (void) address; - (void) key_data; - (void) key_len; + (void) record; + (void) record_len; + (void) user_record; + (void) user_record_len; (void) user_data; - // Verify a remote client's identity key + return -1; } -void iks_destroy_func(void *user_data) +int ss_contains_session_func(const signal_protocol_address *address, void *user_data) { + (void) address; (void) user_data; - // Function called to perform cleanup when the data store context is being destroyed + return -1; } +int ss_delete_session_func(const signal_protocol_address *address, void *user_data) +{ + (void) address; + (void) user_data; + return -1; +} + +int ss_delete_all_sessions_func(const char *name, size_t name_len, void *user_data) +{ + (void) name; + (void) name_len; + (void) user_data; + return -1; +} + +void ss_destroy_func(void *user_data) +{ + (void) user_data; +} + +int sks_store_sender_key(const signal_protocol_sender_key_name *sender_key_name, uint8_t *record, size_t record_len, uint8_t *user_record, size_t user_record_len, void *user_data) +{ + (void) sender_key_name; + (void) record; + (void) record_len; + (void) user_record; + (void) user_record_len; + (void) user_data; + return -1; +} + +int sks_load_sender_key(signal_buffer **record, signal_buffer **user_record, const signal_protocol_sender_key_name *sender_key_name, void *user_data) +{ + (void) record; + (void) user_record; + (void) sender_key_name; + (void) user_data; + return -1; +} + +void sks_destroy_func(void *user_data) +{ + (void) user_data; +} + +void omemo__log_emit_weechat(int level, const char *message, size_t len, void *user_data) +{ + struct t_gui_buffer *buffer = (struct t_gui_buffer*)user_data; + + static const char *log_level_name[5] = {"error", "warn", "notice", "info", "debug"}; + + const char *tags = level < SG_LOG_DEBUG ? "no_log" : NULL; + + weechat_printf_date_tags( + buffer, 0, tags, + _("%somemo (%s): %.*s"), + weechat_prefix("network"), + log_level_name[level], len, message); +} void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, const char *account_name) @@ -465,15 +957,17 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, new_omemo = calloc(1, sizeof(**omemo)); + new_omemo->db = malloc(sizeof(struct t_omemo_db)); + signal_context_create(&new_omemo->context, buffer); signal_context_set_log_function(new_omemo->context, &omemo__log_emit_weechat); - mdb_env_create(&new_omemo->db.env); - mdb_env_set_maxdbs(new_omemo->db.env, 50); - mdb_env_set_mapsize(new_omemo->db.env, (size_t)1048576 * 100000); // 1MB * 100000 + mdb_env_create(&new_omemo->db->env); + mdb_env_set_maxdbs(new_omemo->db->env, 50); + mdb_env_set_mapsize(new_omemo->db->env, (size_t)1048576 * 100000); // 1MB * 100000 char *path = weechat_string_eval_expression("${weechat_data_dir}/xmpp.omemo.db", NULL, NULL, NULL); - if (mdb_env_open(new_omemo->db.env, path, MDB_NOSUBDIR, 0664) != 0) + if (mdb_env_open(new_omemo->db->env, path, MDB_NOSUBDIR, 0664) != 0) { return; } @@ -481,19 +975,20 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, MDB_txn *parentTransaction = NULL; MDB_txn *transaction; - if (mdb_txn_begin(new_omemo->db.env, parentTransaction, 0 ? MDB_RDONLY : 0, &transaction)) { - //Error + if (mdb_txn_begin(new_omemo->db->env, parentTransaction, 0 ? MDB_RDONLY : 0, &transaction)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction", + weechat_prefix("error")); } - if (0) { - mdb_txn_abort(transaction); - } else { - mdb_txn_commit(transaction); + size_t db_name_len = strlen("omemo_") + strlen(account_name); + char *db_name = malloc(sizeof(char) * (db_name_len + 1)); + snprintf(db_name, db_name_len+1, "identity_key_%s", account_name); + if (mdb_dbi_open(transaction, db_name, MDB_DUPSORT | MDB_CREATE, &new_omemo->db->dbi_omemo)) { + weechat_printf(NULL, "%sxmpp: failed to open lmdb database", + weechat_prefix("error")); } - if (mdb_dbi_open(transaction, "databasename", MDB_DUPSORT | MDB_CREATE, new_omemo->db.dbi)) { - //Error - } + mdb_txn_abort(transaction); struct signal_crypto_provider crypto_provider = { .random_func = &cp_random_generator, @@ -507,28 +1002,12 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, .sha512_digest_cleanup_func = &cp_sha512_digest_cleanup, .encrypt_func = &cp_encrypt, .decrypt_func = &cp_decrypt, - .user_data = buffer, + .user_data = new_omemo, }; signal_context_set_crypto_provider(new_omemo->context, &crypto_provider); signal_context_set_locking_functions(new_omemo->context, &lock_function, &unlock_function); - signal_protocol_key_helper_pre_key_list_node *pre_keys_head; - session_signed_pre_key *signed_pre_key; - int start_id = 0; - time_t timestamp = time(NULL); - - if (new_omemo->identity) - 0; - else - signal_protocol_key_helper_generate_identity_key_pair(&new_omemo->identity, new_omemo->context); - signal_protocol_key_helper_generate_registration_id(&new_omemo->device_id, 0, new_omemo->context); - signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, new_omemo->context); - signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, new_omemo->identity, 5, timestamp, new_omemo->context); - - /* Store pre keys in the pre key store. */ - /* Store signed pre key in the signed pre key store. */ - signal_protocol_store_context_create(&new_omemo->store_context, new_omemo->context); struct signal_protocol_identity_key_store identity_key_store = { @@ -537,10 +1016,59 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo, .save_identity = &iks_save_identity, .is_trusted_identity = &iks_is_trusted_identity, .destroy_func = &iks_destroy_func, - .user_data = account_name, + .user_data = new_omemo, + }; + + signal_protocol_store_context_set_identity_key_store( + new_omemo->store_context, &identity_key_store); + + struct signal_protocol_pre_key_store pre_key_store = { + .load_pre_key = &pks_load_pre_key, + .store_pre_key = &pks_store_pre_key, + .contains_pre_key = &pks_contains_pre_key, + .remove_pre_key = &pks_remove_pre_key, + .destroy_func = &pks_destroy_func, + .user_data = new_omemo, + }; + + signal_protocol_store_context_set_pre_key_store( + new_omemo->store_context, &pre_key_store); + + struct signal_protocol_signed_pre_key_store signed_pre_key_store = { + .load_signed_pre_key = &spks_load_signed_pre_key, + .store_signed_pre_key = &spks_store_signed_pre_key, + .contains_signed_pre_key = &spks_contains_signed_pre_key, + .remove_signed_pre_key = &spks_remove_signed_pre_key, + .destroy_func = &spks_destroy_func, + .user_data = new_omemo, + }; + + signal_protocol_store_context_set_signed_pre_key_store( + new_omemo->store_context, &signed_pre_key_store); + + struct signal_protocol_session_store session_store = { + .load_session_func = &ss_load_session_func, + .get_sub_device_sessions_func = &ss_get_sub_device_sessions_func, + .store_session_func = &ss_store_session_func, + .contains_session_func = &ss_contains_session_func, + .delete_session_func = &ss_delete_session_func, + .delete_all_sessions_func = &ss_delete_all_sessions_func, + .destroy_func = &ss_destroy_func, + .user_data = new_omemo, + }; + + signal_protocol_store_context_set_session_store( + new_omemo->store_context, &session_store); + + struct signal_protocol_sender_key_store sender_key_store = { + .store_sender_key = &sks_store_sender_key, + .load_sender_key = &sks_load_sender_key, + .destroy_func = &sks_destroy_func, + .user_data = new_omemo, }; - signal_protocol_store_context_set_identity_key_store(new_omemo->store_context, &identity_key_store); + signal_protocol_store_context_set_sender_key_store( + new_omemo->store_context, &sender_key_store); *omemo = new_omemo; } diff --git a/omemo.h b/omemo.h index 5a28254..03c29b2 100644 --- a/omemo.h +++ b/omemo.h @@ -12,10 +12,7 @@ struct t_omemo struct signal_context *context; struct signal_protocol_store_context *store_context; - struct { - struct MDB_env *env; - struct MDB_dbi *dbi; - } db; + struct t_omemo_db *db; struct ratchet_identity_key_pair *identity; diff --git a/pgp.c b/pgp.c index 9d4aed0..427bf85 100644 --- a/pgp.c +++ b/pgp.c @@ -60,7 +60,7 @@ void pgp__free(struct t_pgp *pgp) } } -char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *target, const char *message) +char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *target, const char *message) { rnp_op_encrypt_t encrypt = NULL; rnp_key_handle_t key = NULL; @@ -115,6 +115,21 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t rnp_key_handle_destroy(key); key = NULL; + /* locate carbon-copy key and add it to the operation context. */ + if ((ret = rnp_locate_key(pgp->context, "keyid", source, &key)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(buffer, "%spgp: failed to locate recipient key: %s\n", weechat_prefix("error"), reason); + goto encrypt_finish; + } + + if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) { + const char *reason = rnp_result_to_string(ret); + weechat_printf(buffer, "%spgp: failed to add recipient: %s\n", weechat_prefix("error"), reason); + goto encrypt_finish; + } + rnp_key_handle_destroy(key); + key = NULL; + /* execute encryption operation */ if ((ret = rnp_op_encrypt_execute(encrypt)) != RNP_SUCCESS) { const char *reason = rnp_result_to_string(ret); diff --git a/pgp.h b/pgp.h index ab73475..0e12e6a 100644 --- a/pgp.h +++ b/pgp.h @@ -19,7 +19,7 @@ void pgp__free(struct t_pgp *pgp); char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ciphertext); -char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *target, const char *message); +char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *target, const char *message); char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate); diff --git a/user.c b/user.c index 5d9ed62..5190f69 100644 --- a/user.c +++ b/user.c @@ -184,7 +184,7 @@ struct t_user *user__new(struct t_account *account, new_user->profile.avatar_hash = NULL; new_user->profile.status_text = NULL; new_user->profile.status = NULL; - new_user->profile.real_name = NULL; + new_user->profile.idle = NULL; new_user->profile.display_name = display_name ? strdup(display_name) : strdup(""); new_user->profile.affiliation = NULL; @@ -232,8 +232,8 @@ void user__free(struct t_account *account, free(user->profile.status_text); if (user->profile.status) free(user->profile.status); - if (user->profile.real_name) - free(user->profile.real_name); + if (user->profile.idle) + free(user->profile.idle); if (user->profile.display_name) free(user->profile.display_name); if (user->profile.affiliation) diff --git a/user.h b/user.h index 74c3654..9c153c5 100644 --- a/user.h +++ b/user.h @@ -10,7 +10,7 @@ struct t_user_profile char *avatar_hash; char *status_text; char *status; - char *real_name; + char *idle; char *display_name; char *email; char *role;