aboutsummaryrefslogtreecommitdiff
path: root/juick-xmpp
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2018-02-17 22:13:12 +0300
committerGravatar Vitaly Takmazov2018-02-17 22:13:12 +0300
commitdd8a51e0f342c183116d8b2af3f12394b0ac53dd (patch)
treeea88db8f0c79256f9527d1220023f2ba5d24994d /juick-xmpp
parentae265f84efc37619411fb21d92b51183a4744478 (diff)
server: merge xmpp
Diffstat (limited to 'juick-xmpp')
-rw-r--r--juick-xmpp/build.gradle29
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/CleaningUp.java60
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/JuickBot.java710
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/XMPPConnection.java413
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/XMPPServer.java409
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/configuration/XmppAppConfiguration.java70
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/configuration/XmppInitializer.java58
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/controllers/StatusController.java46
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/controllers/helpers/XMPPStatus.java48
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/BasicXmppSession.java69
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/CacheEntry.java40
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/Connection.java139
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionIn.java216
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionListener.java14
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java167
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/DNSQueries.java66
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/StanzaListener.java28
-rw-r--r--juick-xmpp/src/main/java/com/juick/components/s2s/util/DialbackUtils.java36
-rw-r--r--juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java162
-rw-r--r--juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java65
-rw-r--r--juick-xmpp/src/main/java/com/juick/xmpp/helpers/JidConverter.java13
-rw-r--r--juick-xmpp/src/main/resources/juick.pngbin2324 -> 0 bytes
-rw-r--r--juick-xmpp/src/main/webapp/WEB-INF/web.xml7
-rw-r--r--juick-xmpp/src/test/java/com/juick/xmpp/server/XMPPServerTests.java189
24 files changed, 0 insertions, 3054 deletions
diff --git a/juick-xmpp/build.gradle b/juick-xmpp/build.gradle
deleted file mode 100644
index 6d7ca2e8..00000000
--- a/juick-xmpp/build.gradle
+++ /dev/null
@@ -1,29 +0,0 @@
-apply plugin: 'java'
-apply plugin: 'war'
-apply plugin: 'org.akhikhl.gretty'
-
-dependencies {
- compile project(':juick-server-jdbc')
- compile project(':juick-server-web')
- compile ('com.github.juick:com.juick.xmpp:658f8cf751') {
- exclude group: 'xmlpull'
- }
- providedCompile 'xpp3:xpp3:1.1.4c'
- testCompile project(path: ':juick-core', configuration: 'testArtifacts')
- testCompile project(path: ':juick-server-web', configuration: 'testArtifacts')
- testCompile project(path: ':juick-server-jdbc', configuration: 'testArtifacts')
-}
-
-compileJava.options.encoding = 'UTF-8'
-
-gretty {
- httpPort = 8080
- contextPath = '/s2s'
- servletContainer = 'tomcat8'
-}
-
-configurations {
- all*.exclude module: 'commons-logging'
- all*.exclude module: 'slf4j-nop'
-}
-
diff --git a/juick-xmpp/src/main/java/com/juick/components/CleaningUp.java b/juick-xmpp/src/main/java/com/juick/components/CleaningUp.java
deleted file mode 100644
index a96b7c35..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/CleaningUp.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import javax.inject.Inject;
-import java.time.Duration;
-import java.time.Instant;
-
-/**
- *
- * @author ugnich
- */
-@Component
-public class CleaningUp {
-
- private static final Logger logger = LoggerFactory.getLogger(CleaningUp.class);
-
- private static final int TIMEOUT_MINUTES = 15;
-
- @Inject
- XMPPServer xmpp;
-
- @Scheduled(fixedDelay = 10000)
- public void cleanUp() {
- Instant now = Instant.now();
- xmpp.getOutConnections().keySet().stream().filter(c -> Duration.between(now, c.getUpdated()).toMinutes() > TIMEOUT_MINUTES)
- .forEach(c -> {
- logger.info("closing idle outgoing connection to {}", c.to);
- c.logoff();
- xmpp.getOutConnections().remove(c);
- });
-
- xmpp.getInConnections().stream().filter(c -> Duration.between(now, c.updated).toMinutes() > TIMEOUT_MINUTES)
- .forEach(c -> {
- logger.info("closing idle incoming connection from {}", c.from);
- c.closeConnection();
- xmpp.getInConnections().remove(c);
- });
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/JuickBot.java b/juick-xmpp/src/main/java/com/juick/components/JuickBot.java
deleted file mode 100644
index ad21b577..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/JuickBot.java
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components;
-
-import com.juick.Tag;
-import com.juick.User;
-import com.juick.components.s2s.StanzaListener;
-import com.juick.formatters.PlainTextFormatter;
-import com.juick.server.helpers.TagStats;
-import com.juick.server.protocol.annotation.UserCommand;
-import com.juick.service.*;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.math.NumberUtils;
-import org.apache.commons.lang3.reflect.MethodUtils;
-import org.ocpsoft.prettytime.PrettyTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import rocks.xmpp.addr.Jid;
-import rocks.xmpp.core.stanza.model.*;
-import rocks.xmpp.core.stanza.model.client.ClientMessage;
-import rocks.xmpp.core.stanza.model.client.ClientPresence;
-import rocks.xmpp.core.stanza.model.errors.Condition;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-/**
- *
- * @author ugnich
- */
-@Component
-public class JuickBot implements StanzaListener, AutoCloseable {
-
- private static final Logger logger = LoggerFactory.getLogger(JuickBot.class);
-
- @Inject
- private XMPPServer xmpp;
- @Inject
- private XMPPConnection router;
- @Value("${xmppbot_jid}")
- private Jid jid;
-
- private PrettyTime pt;
-
- @Inject
- private MessagesService messagesService;
- @Inject
- private UserService userService;
- @Inject
- private TagService tagService;
- @Inject
- private PMQueriesService pmQueriesService;
- @Inject
- private ShowQueriesService showQueriesService;
- @Inject
- private PrivacyQueriesService privacyQueriesService;
- @Inject
- private SubscriptionService subscriptionService;
-
- @PostConstruct
- public void init() {
- xmpp.addStanzaListener(this);
- broadcastPresence(null);
- pt = new PrettyTime(new Locale("ru"));
- }
-
- public Jid getJid() {
- return jid;
- }
-
- public boolean incomingPresence(Presence p) {
- final String username = p.getTo().getLocal();
- final boolean toJuick = username.equals(jid.getLocal());
-
- if (p.getType() == null) {
- Presence reply = new Presence();
- reply.setFrom(p.getTo().asBareJid());
- reply.setTo(p.getFrom().asBareJid());
- reply.setType(Presence.Type.UNSUBSCRIBE);
- xmpp.sendOut(ClientPresence.from(reply));
- return true;
- } else if (p.getType().equals(Presence.Type.PROBE)) {
- int uid_to = 0;
- if (!toJuick) {
- uid_to = userService.getUIDbyName(username);
- }
-
- if (toJuick || uid_to > 0) {
- Presence reply = new Presence();
- reply.setFrom(p.getTo().withResource(jid.getResource()));
- reply.setTo(p.getFrom());
- reply.setPriority((byte)10);
- if (!userService.getActiveJIDs().contains(p.getFrom().asBareJid().toEscapedString())) {
- reply.setStatus("Send ON to enable notifications");
- }
- xmpp.sendOut(ClientPresence.from(reply));
- } else {
- Presence reply = new Presence();
- reply.setFrom(p.getTo());
- reply.setTo(p.getFrom());
- reply.setType(Presence.Type.ERROR);
- reply.setId(p.getId());
- reply.setError(new StanzaError(StanzaError.Type.CANCEL, Condition.ITEM_NOT_FOUND));
- xmpp.sendOut(ClientPresence.from(reply));
- return true;
- }
- return true;
- } else if (p.getType().equals(Presence.Type.SUBSCRIBE)) {
- boolean canSubscribe = false;
- if (toJuick) {
- canSubscribe = true;
- } else {
- int uid_to = userService.getUIDbyName(username);
- if (uid_to > 0) {
- pmQueriesService.addPMinRoster(uid_to, p.getFrom().asBareJid().toEscapedString());
- canSubscribe = true;
- }
- }
-
- if (canSubscribe) {
- Presence reply = new Presence();
- reply.setFrom(p.getTo());
- reply.setTo(p.getFrom());
- reply.setType(Presence.Type.SUBSCRIBED);
- xmpp.sendOut(ClientPresence.from(reply));
-
- reply.setFrom(reply.getFrom().withResource(jid.getResource()));
- reply.setPriority((byte) 10);
- reply.setType(null);
- xmpp.sendOut(ClientPresence.from(reply));
-
- return true;
- } else {
- Presence reply = new Presence();
- reply.setFrom(p.getTo());
- reply.setTo(p.getFrom());
- reply.setType(Presence.Type.ERROR);
- reply.setId(p.getId());
- reply.setError(new StanzaError(StanzaError.Type.CANCEL, Condition.ITEM_NOT_FOUND));
- xmpp.sendOut(ClientPresence.from(reply));
- return true;
- }
- } else if (p.getType().equals(Presence.Type.UNSUBSCRIBE)) {
- if (!toJuick) {
- int uid_to = userService.getUIDbyName(username);
- if (uid_to > 0) {
- pmQueriesService.removePMinRoster(uid_to, p.getFrom().asBareJid().toEscapedString());
- }
- }
-
- Presence reply = new Presence();
- reply.setFrom(p.getTo());
- reply.setTo(p.getFrom());
- reply.setType(Presence.Type.UNSUBSCRIBED);
- xmpp.sendOut(ClientPresence.from(reply));
- }
-
- return false;
- }
-
- public boolean incomingMessage(Message msg) {
- if (msg.getType() != null && msg.getType().equals(Message.Type.ERROR)) {
- StanzaError error = msg.getError();
- if (error != null && error.getCondition().equals(Condition.RESOURCE_CONSTRAINT)) {
- // offline query is full, deactivating this jid
- if (userService.setActiveStatusForJID(msg.getFrom().toEscapedString(), UserService.ActiveStatus.Inactive)) {
- logger.info("{} is inactive now", msg.getFrom());
- return true;
- }
- }
- return false;
- }
- if (StringUtils.isBlank(msg.getBody())) {
- return false;
- }
- String username = msg.getTo().getLocal();
-
- User user_from;
- String signuphash = StringUtils.EMPTY;
- user_from = userService.getUserByJID(msg.getFrom().asBareJid().toEscapedString());
- if (user_from == null) {
- signuphash = userService.getSignUpHashByJID(msg.getFrom().asBareJid().toEscapedString());
- }
-
- if (user_from == null) {
- Message reply = new Message();
- reply.setFrom(msg.getTo());
- reply.setTo(msg.getFrom());
- reply.setType(Message.Type.CHAT);
- if (username.equals(jid.getLocal())) {
- reply.setBody("Для того, чтобы начать пользоваться сервисом, пожалуйста пройдите быструю регистрацию: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nЕсли у вас уже есть учетная запись на Juick, вы сможете присоединить этот JabberID к ней.\n\nTo start using Juick, please sign up: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nIf you already have an account on Juick, you will be proposed to attach this JabberID to your existing account.");
- } else {
- reply.setBody("Внимание, системное сообщение!\nВаш JabberID не обнаружен в списке доверенных. Для того, чтобы отправить сообщение пользователю " + username + "@juick.com, пожалуйста зарегистрируйте свой JabberID в системе: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nЕсли у вас уже есть учетная запись на Juick, вы сможете присоединить этот JabberID к ней.\n\nWarning, system message!\nYour JabberID is not found in our server's white list. To send a message to " + username + "@juick.com, please sign up: http://juick.com/signup?type=xmpp&hash=" + signuphash + "\nIf you already have an account on Juick, you will be proposed to attach this JabberID to your existing account.");
- }
- xmpp.sendOut(ClientMessage.from(reply));
- return true;
- }
-
- if (username.equals(jid.getLocal())) {
- try {
- return incomingMessageJuick(user_from, msg);
- } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
- return false;
- }
- }
-
- int uid_to = userService.getUIDbyName(username);
-
- if (uid_to == 0) {
- Message reply = new Message();
- reply.setFrom(msg.getTo());
- reply.setTo(msg.getFrom());
- reply.setType(Message.Type.ERROR);
- reply.setId(msg.getId());
- reply.setError(new StanzaError(StanzaError.Type.CANCEL, Condition.ITEM_NOT_FOUND));
- xmpp.sendOut(ClientMessage.from(reply));
- return true;
- }
-
- boolean success = false;
- if (!userService.isInBLAny(uid_to, user_from.getUid())) {
- success = pmQueriesService.createPM(user_from.getUid(), uid_to, msg.getBody());
- }
-
- if (success) {
- Message m = new Message();
- m.setFrom(jid.asBareJid());
- m.setTo(Jid.of(Integer.toString(uid_to), "push.juick.com", null));
- com.juick.Message jmsg = new com.juick.Message();
- jmsg.setUser(user_from);
- jmsg.setText(msg.getBody());
- m.addExtension(jmsg);
- router.sendStanza(m);
-
- m.setTo(Jid.of(Integer.toString(uid_to), "ws.juick.com", null));
- router.sendStanza(m);
-
- List<String> jids;
- boolean inroster = false;
- jids = userService.getJIDsbyUID(uid_to);
- for (String userJid : jids) {
- Message mm = new Message();
- mm.setTo(Jid.of(userJid));
- mm.setType(Message.Type.CHAT);
- inroster = pmQueriesService.havePMinRoster(user_from.getUid(), userJid);
- if (inroster) {
- mm.setFrom(Jid.of(jmsg.getUser().getName(), "juick.com", "Juick"));
- mm.setBody(msg.getBody());
- } else {
- mm.setFrom(jid);
- mm.setBody("Private message from @" + jmsg.getUser().getName() + ":\n" + msg.getBody());
- }
- xmpp.sendOut(ClientMessage.from(mm));
- }
- } else {
- Message reply = new Message();
- reply.setFrom(msg.getTo());
- reply.setTo(msg.getFrom());
- reply.setType(Message.Type.ERROR);
- reply.setId(msg.getId());
- reply.setError(new StanzaError(StanzaError.Type.CANCEL, Condition.NOT_ALLOWED));
- xmpp.sendOut(ClientMessage.from(reply));
- }
-
- return false;
- }
-
- public Optional<String> processCommand(User user, Jid from, String input) throws InvocationTargetException,
- IllegalAccessException, NoSuchMethodException {
- Optional<Method> cmd = MethodUtils.getMethodsListWithAnnotation(getClass(), UserCommand.class).stream()
- .filter(m -> Pattern.compile(m.getAnnotation(UserCommand.class).pattern(),
- m.getAnnotation(UserCommand.class).patternFlags()).matcher(input).matches())
- .findFirst();
- if (cmd.isPresent()) {
- Matcher matcher = Pattern.compile(cmd.get().getAnnotation(UserCommand.class).pattern(),
- cmd.get().getAnnotation(UserCommand.class).patternFlags()).matcher(input);
- List<String> groups = new ArrayList<>();
- while (matcher.find()) {
- for (int i = 1; i <= matcher.groupCount(); i++) {
- groups.add(matcher.group(i));
- }
- }
- return Optional.of((String) getClass().getMethod(cmd.get().getName(), User.class, Jid.class, String[].class)
- .invoke(this, user, from, groups.toArray(new String[groups.size()])));
- }
- return Optional.empty();
- }
- public boolean incomingMessageJuick(User user_from, Message msg) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- String command = msg.getBody().trim();
- int commandlen = command.length();
-
- // COMPATIBILITY
- if (commandlen > 7 && command.substring(0, 3).equalsIgnoreCase("PM ")) {
- command = command.substring(3).trim();
- }
-
- Optional<String> result = processCommand(user_from, msg.getFrom(), command);
- result.ifPresent(r -> sendReply(msg.getFrom(), r));
- return result.isPresent();
- }
-
- @UserCommand(pattern = "^ping$", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "PING - returns you a PONG")
- public String commandPing(User user, Jid from, String[] input) {
- Presence p = new Presence(from);
- p.setFrom(jid);
- p.setPriority((byte) 10);
- xmpp.sendOut(ClientPresence.from(p));
- return "PONG";
- }
-
- @UserCommand(pattern = "^help$", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "HELP - returns this help message")
- public String commandHelp(User user, Jid from, String[] input) {
- return Arrays.stream(getClass().getDeclaredMethods())
- .filter(m -> m.isAnnotationPresent(UserCommand.class))
- .map(m -> m.getAnnotation(UserCommand.class).help())
- .collect(Collectors.joining("\n"));
- }
-
- @UserCommand(pattern = "^login$", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "LOGIN - log in to Juick website")
- public String commandLogin(User user_from, Jid from, String[] input) {
- return "http://juick.com/login?hash=" + userService.getHashByUID(user_from.getUid());
- }
- @UserCommand(pattern = "^\\@(\\S+)\\s+([\\s\\S]+)$", help = "@username message - send PM to username")
- public String commandPM(User user_from, Jid from, String... arguments) {
- String body = arguments[1];
- int ret = 0;
-
- User user_to = userService.getUserByName(arguments[0]);
- List<String> jids_to = null;
- boolean haveInRoster = false;
-
- if (user_to.getUid() > 0) {
- if (!userService.isInBLAny(user_to.getUid(), user_from.getUid())) {
- if (pmQueriesService.createPM(user_from.getUid(), user_to.getUid(), body)) {
- jids_to = userService.getJIDsbyUID(user_to.getUid());
- ret = 200;
- } else {
- ret = 500;
- }
- } else {
- ret = 403;
- }
- } else {
- ret = 404;
- }
-
- if (ret == 200) {
- Message msg = new Message();
- msg.setFrom(jid.asBareJid());
- msg.setTo(Jid.of(Integer.toString(user_to.getUid()), "push.juick.com", null));
- com.juick.Message jmsg = new com.juick.Message();
- jmsg.setUser(user_from);
- jmsg.setTo(user_to);
- jmsg.setText(body);
- msg.addExtension(jmsg);
- router.sendStanza(msg);
-
- msg.setTo(Jid.of(Integer.toString(user_to.getUid()), "ws.juick.com", null));
- router.sendStanza(msg);
-
- for (String userJid : jids_to) {
- Message mm = new Message();
- mm.setTo(Jid.of(userJid));
- mm.setType(Message.Type.CHAT);
- haveInRoster = pmQueriesService.havePMinRoster(user_from.getUid(), userJid);
- if (haveInRoster) {
- mm.setFrom(Jid.of(user_from.getName(), "juick.com", "Juick"));
- mm.setBody(body);
- } else {
- mm.setFrom(jid);
- mm.setBody("Private message from @" + user_from.getName() + ":\n" + body);
- }
- xmpp.sendOut(ClientMessage.from(mm));
- }
- }
-
- if (ret == 200) {
- return "Private message sent";
- } else {
- return "Error " + ret;
- }
- }
- @UserCommand(pattern = "^bl$", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "BL - Show your blacklist")
- public String commandBLShow(User user_from, Jid from, String... arguments) {
- List<User> blusers = userService.getUserBLUsers(user_from.getUid());
- List<String> bltags = tagService.getUserBLTags(user_from.getUid());
-
- String txt = StringUtils.EMPTY;
- if (bltags.size() > 0) {
- for (String bltag : bltags) {
- txt += "*" + bltag + "\n";
- }
-
- if (blusers.size() > 0) {
- txt += "\n";
- }
- }
- if (blusers.size() > 0) {
- for (User bluser : blusers) {
- txt += "@" + bluser.getName() + "\n";
- }
- }
- if (txt.isEmpty()) {
- txt = "You don't have any users or tags in your blacklist.";
- }
-
- return txt;
- }
-
- @UserCommand(pattern = "^#\\+$", help = "#+ - Show last Juick messages")
- public String commandLast(User user_from, Jid from, String... arguments) {
- return "Last messages:\n"
- + printMessages(messagesService.getAll(user_from.getUid(), 0), true);
- }
-
- @UserCommand(pattern = "@", help = "@ - Show recommendations and popular personal blogs")
- public String commandUsers(User user_from, Jid from, String... arguments) {
- StringBuilder msg = new StringBuilder();
- msg.append("Recommended blogs");
- List<String> recommendedUsers = showQueriesService.getRecommendedUsers(user_from);
- if (recommendedUsers.size() > 0) {
- for (String user : recommendedUsers) {
- msg.append("\n@").append(user);
- }
- } else {
- msg.append("\nNo recommendations now. Subscribe to more blogs. ;)");
- }
- msg.append("\n\nTop 10 personal blogs:");
- List<String> topUsers = showQueriesService.getTopUsers();
- if (topUsers.size() > 0) {
- for (String user : topUsers) {
- msg.append("\n@").append(user);
- }
- } else {
- msg.append("\nNo top users. Empty DB? ;)");
- }
- return msg.toString();
- }
- @UserCommand(pattern = "^bl\\s+@([^\\s\\n\\+]+)", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "BL @username - add @username to your blacklist")
- public String blacklistUser(User user_from, Jid from, String... arguments) {
- User blUser = userService.getUserByName(arguments[0]);
- if (blUser != null) {
- PrivacyQueriesService.PrivacyResult result = privacyQueriesService.blacklistUser(user_from, blUser);
- if (result == PrivacyQueriesService.PrivacyResult.Added) {
- return "User added to your blacklist";
- } else {
- return "User removed from your blacklist";
- }
- }
- return "User not found";
- }
- @UserCommand(pattern = "^bl\\s\\*(\\S+)$", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "BL *tag - add *tag to your blacklist")
- public String blacklistTag(User user_from, Jid from, String... arguments) {
- User blUser = userService.getUserByName(arguments[0]);
- if (blUser != null) {
- Tag tag = tagService.getTag(arguments[0], false);
- if (tag != null) {
- PrivacyQueriesService.PrivacyResult result = privacyQueriesService.blacklistTag(user_from, tag);
- if (result == PrivacyQueriesService.PrivacyResult.Added) {
- return "Tag added to your blacklist";
- } else {
- return "Tag removed from your blacklist";
- }
- }
- }
- return "Tag not found";
- }
- @UserCommand(pattern = "\\*", help = "* - Show your tags")
- public String commandTags(User currentUser, Jid from, String... args) {
- List<TagStats> tags = tagService.getUserTagStats(currentUser.getUid());
- String msg = "Your tags: (tag - messages)\n" +
- tags.stream()
- .map(t -> String.format("\n*%s - %d", t.getTag().getName(), t.getUsageCount())).collect(Collectors.joining());
- return msg;
- }
- @UserCommand(pattern = "S", help = "S - Show your subscriptions")
- public String commandSubscriptions(User currentUser, Jid from, String... args) {
- List<User> friends = userService.getUserFriends(currentUser.getUid());
- List<String> tags = subscriptionService.getSubscribedTags(currentUser);
- String msg = friends.size() > 0 ? "You are subscribed to users:" + friends.stream().map(u -> "\n@" + u.getName())
- .collect(Collectors.joining())
- : "You are not subscribed to any user.";
- msg += tags.size() > 0 ? "\nYou are subscribed to tags:" + tags.stream().map(t -> "\n*" + t)
- .collect(Collectors.joining())
- : "\nYou are not subscribed to any tag.";
- return msg;
- }
- @UserCommand(pattern = "!", help = "! - Show your favorite messages")
- public String commandFavorites(User currentUser, Jid from, String... args) {
- List<Integer> mids = messagesService.getUserRecommendations(currentUser.getUid(), 0);
- if (mids.size() > 0) {
- return "Favorite messages: \n" + printMessages(mids, false);
- }
- return "No favorite messages, try to \"like\" something ;)";
- }
- // TODO: target notification
- @UserCommand(pattern = "^(s|u)\\s+\\@(\\S+)$", help = "S @username - subscribe to user" +
- "\nU @username - unsubscribe from user", patternFlags = Pattern.CASE_INSENSITIVE)
- public String commandSubscribeUser(User user, Jid from, String... args) {
- boolean subscribe = args[0].equalsIgnoreCase("s");
- User toUser = userService.getUserByName(args[1]);
- if (subscribe) {
- if (subscriptionService.subscribeUser(user, toUser)) {
- return "Subscribed to @" + toUser.getName();
- }
- } else {
- if (subscriptionService.unSubscribeUser(user, toUser)) {
- return "Unsubscribed from @" + toUser.getName();
- }
- return "You was not subscribed to @" + toUser.getName();
- }
- return "Error";
- }
- @UserCommand(pattern = "^(s|u)\\s+\\*(\\S+)$", help = "S *tag - subscribe to tag" +
- "\nU *tag - unsubscribe from tag", patternFlags = Pattern.CASE_INSENSITIVE)
- public String commandSubscribeTag(User user, Jid from, String... args) {
- boolean subscribe = args[0].equalsIgnoreCase("s");
- Tag tag = tagService.getTag(args[1], true);
- if (subscribe) {
- if (subscriptionService.subscribeTag(user, tag)) {
- return "Subscribed";
- }
- } else {
- if (subscriptionService.unSubscribeTag(user, tag)) {
- return "Unsubscribed from " + tag.getName();
- }
- return "You was not subscribed to " + tag.getName();
- }
- return "Error";
- }
- @UserCommand(pattern = "^(s|u)\\s+#(\\d+)$", help = "S #1234 - subscribe to comments" +
- "\nU #1234 - unsubscribe from comments", patternFlags = Pattern.CASE_INSENSITIVE)
- public String commandSubscribeMessage(User user, Jid from, String... args) {
- boolean subscribe = args[0].equalsIgnoreCase("s");
- int mid = NumberUtils.toInt(args[1], 0);
- if (messagesService.getMessage(mid) != null) {
- if (subscribe) {
- if (subscriptionService.subscribeMessage(mid, user.getUid())) {
- return "Subscribed";
- }
- } else {
- if (subscriptionService.unSubscribeMessage(mid, user.getUid())) {
- return "Unsubscribed from #" + mid;
- }
- return "You was not subscribed to #" + mid;
- }
- }
- return "Error";
- }
- @UserCommand(pattern = "^(on|off)$", patternFlags = Pattern.CASE_INSENSITIVE,
- help = "ON/OFF - Enable/disable subscriptions delivery")
- public String commandOnOff(User user, Jid from, String[] input) {
- UserService.ActiveStatus newStatus;
- String retValUpdated;
- if (input[0].toLowerCase().equals("on")) {
- newStatus = UserService.ActiveStatus.Active;
- retValUpdated = "Notifications are activated for " + from.asBareJid().toEscapedString();
- } else {
- newStatus = UserService.ActiveStatus.Inactive;
- retValUpdated = "Notifications are disabled for " + from.asBareJid().toEscapedString();
- }
-
- if (userService.setActiveStatusForJID(from.asBareJid().toEscapedString(), newStatus)) {
- return retValUpdated;
- } else {
- return String.format("Subscriptions status for %s was not changed", from.toEscapedString());
- }
- }
- @UserCommand(pattern = "^\\@([^\\s\\n\\+]+)(\\+?)$",
- help = "@username+ - Show user's info and last 20 messages")
- public String commandUser(User user, Jid from, String... arguments) {
- User blogUser = userService.getUserByName(arguments[0]);
- int page = arguments[1].length();
- if (blogUser.getUid() > 0) {
- List<Integer> mids = messagesService.getUserBlog(blogUser.getUid(), 0, 0);
- return String.format("Last messages from @%s:\n%s", arguments[0],
- printMessages(mids, false));
- }
- return "User not found";
- }
- @UserCommand(pattern = "^#(\\d+)(\\+?)$", help = "#1234 - Show message (#1234+ - message with replies)")
- public String commandShow(User user, Jid from, String... arguments) {
- boolean showReplies = arguments[1].length() > 0;
- int mid = NumberUtils.toInt(arguments[0], 0);
- if (mid == 0) {
- return "Error";
- }
- com.juick.Message msg = messagesService.getMessage(mid);
- if (msg != null) {
- if (showReplies) {
- List<com.juick.Message> replies = messagesService.getReplies(mid);
- replies.add(0, msg);
- return String.join("\n",
- replies.stream().map(PlainTextFormatter::formatPostSummary).collect(Collectors.toList()));
- }
- return PlainTextFormatter.formatPostSummary(msg);
- }
- return "Message not found";
- }
- @UserCommand(pattern = "^D #(\\d+)$", help = "D #1234 - Delete post", patternFlags = Pattern.CASE_INSENSITIVE)
- public String commandDeletePost(User user, Jid from, String... args) {
- int mid = Integer.valueOf(args[0]);
- if (messagesService.deleteMessage(user.getUid(), mid)) {
- return "Message deleted";
- }
- return "This is not your message";
- }
- @UserCommand(pattern = "^D #(\\d+)(\\.|\\-|\\/)(\\d+)$", help = "D #1234/5 - Delete comment", patternFlags = Pattern.CASE_INSENSITIVE)
- public String commandDeleteReply(User user, Jid from, String... args) {
- int mid = Integer.valueOf(args[0]);
- int rid = Integer.valueOf(args[2]);
- if (messagesService.deleteReply(user.getUid(), mid, rid)) {
- return "Reply deleted";
- } else {
- return "This is not your reply";
- }
- }
- /*
- @UserCommand(pattern = "(^(D L|DL|D LAST)$", help = "D #1234/5 - Delete comment", patternFlags = Pattern.CASE_INSENSITIVE)
- public String commandDeleteLast(User user, Jid from, String... args) {
-
- }
- */
- void sendReply(Jid jidTo, String txt) {
- Message reply = new Message();
- reply.setFrom(jid);
- reply.setTo(jidTo);
- reply.setType(Message.Type.CHAT);
- reply.setBody(txt);
- xmpp.sendOut(ClientMessage.from(reply));
- }
-
- void sendNotification(Stanza stanza) {
- xmpp.sendOut(stanza);
- }
-
- @Override
- public void stanzaReceived(Stanza xmlValue) {
- if (xmlValue instanceof Presence) {
- Presence p = (Presence) xmlValue;
- if (p.getType() == null || !p.getType().equals(Presence.Type.ERROR)) {
- incomingPresence(p);
- }
- } else if (xmlValue instanceof Message) {
- Message msg = (Message) xmlValue;
- if (!incomingMessage(msg)) {
- router.sendStanza(msg);
- }
- } else if (xmlValue instanceof IQ) {
- IQ iq = (IQ) xmlValue;
- router.sendStanza(iq);
- }
- }
-
- String printMessages(List<Integer> mids, boolean crop) {
- return messagesService.getMessages(mids).stream()
- .sorted(Collections.reverseOrder())
- .map(PlainTextFormatter::formatPostSummary).collect(Collectors.joining("\n\n"));
- }
-
- void broadcastPresence(Presence.Type type) {
- Presence presence = new Presence();
- presence.setFrom(jid);
- if (type != null) {
- presence.setType(type);
- }
- userService.getActiveJIDs().forEach(j -> {
- try {
- presence.setTo(Jid.of(j));
- xmpp.sendOut(ClientPresence.from(presence));
- } catch (IllegalArgumentException ex) {
- logger.warn("Invalid jid: {}", j, ex);
- }
- });
- }
-
- @Override
- public void close() throws Exception {
- broadcastPresence(Presence.Type.UNAVAILABLE);
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/XMPPConnection.java b/juick-xmpp/src/main/java/com/juick/components/XMPPConnection.java
deleted file mode 100644
index 6bca282c..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/XMPPConnection.java
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components;
-
-import com.juick.Attachment;
-import com.juick.User;
-import com.juick.components.s2s.BasicXmppSession;
-import com.juick.server.helpers.UserInfo;
-import com.juick.service.MessagesService;
-import com.juick.service.SubscriptionService;
-import com.juick.service.UserService;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.DependsOn;
-import org.springframework.stereotype.Component;
-import rocks.xmpp.addr.Jid;
-import rocks.xmpp.core.XmppException;
-import rocks.xmpp.core.stanza.AbstractIQHandler;
-import rocks.xmpp.core.stanza.model.IQ;
-import rocks.xmpp.core.stanza.model.Message;
-import rocks.xmpp.core.stanza.model.Stanza;
-import rocks.xmpp.core.stanza.model.client.ClientMessage;
-import rocks.xmpp.core.stanza.model.errors.Condition;
-import rocks.xmpp.extensions.caps.model.EntityCapabilities;
-import rocks.xmpp.extensions.component.accept.ExternalComponent;
-import rocks.xmpp.extensions.filetransfer.FileTransfer;
-import rocks.xmpp.extensions.filetransfer.FileTransferManager;
-import rocks.xmpp.extensions.nick.model.Nickname;
-import rocks.xmpp.extensions.oob.model.x.OobX;
-import rocks.xmpp.extensions.ping.PingManager;
-import rocks.xmpp.extensions.vcard.temp.model.VCard;
-import rocks.xmpp.extensions.version.SoftwareVersionManager;
-import rocks.xmpp.extensions.version.model.SoftwareVersion;
-import rocks.xmpp.util.XmppUtils;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import javax.xml.bind.JAXBException;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-
-/**
- * @author ugnich
- */
-@Component
-public class XMPPConnection implements AutoCloseable {
-
- private static final Logger logger = LoggerFactory.getLogger(XMPPConnection.class);
-
- private ExternalComponent router;
- @Inject
- private JuickBot bot;
-
- @Value("${componentname:localhost}")
- private String componentName;
- @Value("${component_port:5347}")
- private int componentPort;
- @Value("${xmpp_password:secret}")
- private String password;
- @Value("${upload_tmp_dir:/tmp}")
- private String tmpDir;
-
- @Inject
- public MessagesService messagesService;
- @Inject
- public UserService userService;
- @Inject
- public SubscriptionService subscriptionService;
- @Inject
- private BasicXmppSession session;
- @Inject
- private ExecutorService service;
-
- @PostConstruct
- public void init() {
- logger.info("stream router start connecting to {}", componentPort);
- router = ExternalComponent.create(componentName, password, session.getConfiguration(), "localhost", componentPort);
- PingManager pingManager = router.getManager(PingManager.class);
- pingManager.setEnabled(true);
- router.disableFeature(EntityCapabilities.NAMESPACE);
- SoftwareVersionManager softwareVersionManager = router.getManager(SoftwareVersionManager.class);
- softwareVersionManager.setSoftwareVersion(new SoftwareVersion("Juick", "2.x", System.getProperty("os.name", "generic")));
- VCard vCard = new VCard();
- vCard.setFormattedName("Juick");
- try {
- vCard.setUrl(new URL("http://juick.com/"));
- vCard.setPhoto(new VCard.Image("image/png", IOUtils.toByteArray(getClass().getClassLoader().getResource("juick.png"))));
- } catch (MalformedURLException e) {
- logger.error("invalid url", e);
- } catch (IOException e) {
- logger.warn("invalid resource", e);
- }
- router.addIQHandler(VCard.class, new AbstractIQHandler(IQ.Type.GET) {
- @Override
- protected IQ processRequest(IQ iq) {
- if (iq.getTo().equals(bot.getJid()) || iq.getTo().asBareJid().equals(bot.getJid().asBareJid())
- || iq.getTo().asBareJid().toEscapedString().equals(bot.getJid().getDomain())) {
- return iq.createResult(vCard);
- }
- User user = userService.getUserByName(iq.getTo().getLocal());
- if (user.getUid() > 0) {
- UserInfo info = userService.getUserInfo(user);
- VCard userVCard = new VCard();
- userVCard.setFormattedName(info.getFullName());
- userVCard.setNickname(user.getName());
- try {
- userVCard.setPhoto(new VCard.Image(new URI("http://i.juick.com/a/" + user.getUid() + ".png")));
- if (info.getUrl() != null) {
- userVCard.setUrl(new URL(info.getUrl()));
- }
- } catch (MalformedURLException | URISyntaxException e) {
- logger.warn("url exception", e);
- }
- return iq.createResult(userVCard);
- }
- return iq.createError(Condition.BAD_REQUEST);
- }
- });
- router.addInboundMessageListener(e -> {
- Message message = e.getMessage();
- Jid jid = message.getTo();
- if (jid.getDomain().equals(router.getDomain().toEscapedString())) {
- com.juick.Message jmsg = message.getExtension(com.juick.Message.class);
- if (jmsg != null) {
- if (jid.getLocal().equals("recomm")) {
- sendJuickRecommendation(jmsg);
- } else {
- if (jmsg.getRid() > 0) {
- sendJuickComment(jmsg);
- } else if (jmsg.getMid() > 0) {
- sendJuickMessage(jmsg);
- }
- }
- }
- } else if (jid.getDomain().endsWith(bot.getJid().getDomain()) && (jid.getDomain().equals(bot.getJid().getDomain())
- || jid.getDomain().endsWith("." + bot.getJid().getDomain()))) {
- if (logger.isInfoEnabled()) {
- try {
- logger.info("unhandled message: {}", stanzaToString(message));
- } catch (JAXBException | XMLStreamException ex) {
- logger.error("JAXB exception", ex);
- }
- }
- } else {
- route(ClientMessage.from(message));
- }
- });
- router.addInboundIQListener(e -> {
- IQ iq = e.getIQ();
- Jid jid = iq.getTo();
- if (!jid.getDomain().equals(bot.getJid().getDomain())) {
- route(iq);
- }
- });
- FileTransferManager fileTransferManager = router.getManager(FileTransferManager.class);
- fileTransferManager.addFileTransferOfferListener(e -> {
- try {
- List<String> allowedTypes = new ArrayList<String>() {{
- add("png");
- add("jpg");
- }};
- String attachmentExtension = FilenameUtils.getExtension(e.getName()).toLowerCase();
- String targetFilename = String.format("%s.%s",
- DigestUtils.md5Hex(String.format("%s-%s",
- e.getInitiator().toString(), e.getSessionId()).getBytes()), attachmentExtension);
- if (allowedTypes.contains(attachmentExtension)) {
- Path filePath = Paths.get(tmpDir, targetFilename);
- FileTransfer ft = e.accept(filePath).get();
- ft.addFileTransferStatusListener(st -> {
- logger.debug("{}: received {} of {}", e.getName(), st.getBytesTransferred(), e.getSize());
- if (st.getStatus().equals(FileTransfer.Status.COMPLETED)) {
- logger.info("transfer completed");
- Message msg = new Message();
- msg.setType(Message.Type.CHAT);
- msg.setFrom(e.getInitiator());
- msg.setTo(bot.getJid());
- msg.setBody(e.getDescription());
- try {
- String attachmentUrl = String.format("juick://%s", targetFilename);
- msg.addExtension(new OobX(new URI(attachmentUrl), "!!!!Juick!!"));
- router.sendMessage(msg);
- } catch (URISyntaxException e1) {
- logger.warn("attachment error", e1);
- }
- } else if (st.getStatus().equals(FileTransfer.Status.FAILED)) {
- logger.info("transfer failed", ft.getException());
- Message msg = new Message();
- msg.setType(Message.Type.CHAT);
- msg.setFrom(bot.getJid());
- msg.setTo(e.getInitiator());
- msg.setBody("File transfer failed, please report to us");
- router.sendMessage(msg);
- } else if (st.getStatus().equals(FileTransfer.Status.CANCELED)) {
- logger.info("transfer cancelled");
- }
- });
- ft.transfer();
- logger.info("transfer started");
- } else {
- e.reject();
- logger.info("transfer rejected");
- }
- } catch (IOException | InterruptedException | ExecutionException e1) {
- logger.error("ft error", e1);
- }
- });
- router.addConnectionListener(event -> {
- if (event.getType().equals(rocks.xmpp.core.session.ConnectionEvent.Type.RECONNECTION_SUCCEEDED)) {
- logger.info("component connected");
- }
- });
- service.submit(() -> {
- try {
- Thread.sleep(3000);
- router.connect();
- } catch (InterruptedException | XmppException e) {
- logger.warn("xmpp exception", e);
- }
- });
- }
-
- String stanzaToString(Stanza stanza) throws XMLStreamException, JAXBException {
- StringWriter stanzaWriter = new StringWriter();
- XMLStreamWriter xmppStreamWriter = XmppUtils.createXmppStreamWriter(
- router.getConfiguration().getXmlOutputFactory().createXMLStreamWriter(stanzaWriter));
- router.createMarshaller().marshal(stanza, xmppStreamWriter);
- xmppStreamWriter.flush();
- xmppStreamWriter.close();
- return stanzaWriter.toString();
- }
-
- void route(Stanza stanza) {
- try {
- String xml = stanzaToString(stanza);
- logger.info("stream router (out): {}", xml);
- bot.sendNotification(stanza);
- } catch (XMLStreamException | JAXBException e) {
- logger.error("JAXB exception", e);
- }
-
- }
-
- public void sendStanza(Stanza xml) {
- router.send(xml);
- }
-
-
-
- public void sendJuickMessage(com.juick.Message jmsg) {
- List<String> jids = new ArrayList<>();
-
- if (jmsg.FriendsOnly) {
- jids = subscriptionService.getJIDSubscribedToUser(jmsg.getUser().getUid(), jmsg.FriendsOnly);
- } else {
- List<User> users = subscriptionService.getSubscribedUsers(jmsg.getUser().getUid(), jmsg.getMid());
- for (User user : users) {
- for (String jid : userService.getJIDsbyUID(user.getUid())) {
- jids.add(jid);
- }
- }
- }
- com.juick.Message fullMsg = messagesService.getMessage(jmsg.getMid());
- String txt = "@" + jmsg.getUser().getName() + ":" + fullMsg.getTagsString() + "\n";
- Attachment attachment = fullMsg.getAttachment();
- if (attachment != null) {
- txt += attachment.getMedium().getUrl() + "\n";
- }
- txt += StringUtils.defaultString(jmsg.getText()) + "\n\n";
- txt += "#" + jmsg.getMid() + " http://juick.com/" + jmsg.getMid();
-
- Nickname nick = new Nickname("@" + jmsg.getUser().getName());
-
- Message msg = new Message();
- msg.setFrom(bot.getJid());
- msg.setBody(txt);
- msg.setType(Message.Type.CHAT);
- msg.setThread("juick-" + jmsg.getMid());
- msg.addExtension(jmsg);
- msg.addExtension(nick);
- if (attachment != null) {
- try {
- OobX oob = new OobX(new URI(attachment.getMedium().getUrl()));
- msg.addExtension(oob);
- } catch (URISyntaxException e) {
- logger.warn("uri exception", e);
- }
- }
- for (String jid : jids) {
- msg.setTo(Jid.of(jid));
- route(ClientMessage.from(msg));
- }
- }
-
- public void sendJuickComment(com.juick.Message jmsg) {
- List<User> users;
- String replyQuote;
- String replyTo;
-
- users = subscriptionService.getUsersSubscribedToComments(jmsg.getMid(), jmsg.getUser().getUid());
- com.juick.Message replyMessage = jmsg.getReplyto() > 0 ? messagesService.getReply(jmsg.getMid(), jmsg.getReplyto())
- : messagesService.getMessage(jmsg.getMid());
- replyTo = replyMessage.getUser().getName();
- com.juick.Message fullReply = messagesService.getReply(jmsg.getMid(), jmsg.getRid());
- replyQuote = fullReply.getReplyQuote();
-
- String txt = "Reply by @" + jmsg.getUser().getName() + ":\n" + replyQuote + "\n@" + replyTo + " ";
- Attachment attachment = jmsg.getAttachment();
- if (attachment != null) {
- txt += attachment.getMedium().getUrl() + "\n";
- }
- txt += StringUtils.defaultString(jmsg.getText()) + "\n\n" + "#" + jmsg.getMid() + "/" + jmsg.getRid() + " http://juick.com/" + jmsg.getMid() + "#" + jmsg.getRid();
-
- Message msg = new Message();
- msg.setFrom(bot.getJid());
- msg.setBody(txt);
- msg.setType(Message.Type.CHAT);
- msg.addExtension(jmsg);
- for (User user : users) {
- for (String jid : userService.getJIDsbyUID(user.getUid())) {
- msg.setTo(Jid.of(jid));
- route(ClientMessage.from(msg));
- }
- }
- }
-
- public void sendJuickRecommendation(com.juick.Message recomm) {
- List<User> users;
- com.juick.Message jmsg = messagesService.getMessage(recomm.getMid());
- users = subscriptionService.getUsersSubscribedToUserRecommendations(recomm.getUser().getUid(),
- recomm.getMid(), jmsg.getUser().getUid());
-
- String txt = "Recommended by @" + recomm.getUser().getName() + ":\n";
- txt += "@" + jmsg.getUser().getName() + ":" + jmsg.getTagsString() + "\n";
- Attachment attachment = jmsg.getAttachment();
- if (attachment != null) {
- txt += attachment.getMedium().getUrl() + "\n";
- }
- txt += StringUtils.defaultString(jmsg.getText()) + "\n\n";
- txt += "#" + jmsg.getMid();
- if (jmsg.getReplies() > 0) {
- if (jmsg.getReplies() % 10 == 1 && jmsg.getReplies() % 100 != 11) {
- txt += " (" + jmsg.getReplies() + " reply)";
- } else {
- txt += " (" + jmsg.getReplies() + " replies)";
- }
- }
- txt += " http://juick.com/" + jmsg.getMid();
-
- Nickname nick = new Nickname("@" + jmsg.getUser().getName());
-
- Message msg = new Message();
- msg.setFrom(bot.getJid());
- msg.setBody(txt);
- msg.setType(Message.Type.CHAT);
- msg.setThread("juick-" + jmsg.getMid());
- msg.addExtension(jmsg);
- msg.addExtension(nick);
- if (attachment != null) {
- try {
- OobX oob = new OobX(new URI(attachment.getMedium().getUrl()));
- msg.addExtension(oob);
- } catch (URISyntaxException e) {
- logger.warn("uri exception", e);
- }
- }
-
- for (User user : users) {
- for (String jid : userService.getJIDsbyUID(user.getUid())) {
- msg.setTo(Jid.of(jid));
- route(ClientMessage.from(msg));
- }
- }
- }
-
- @Override
- public void close() throws Exception {
- if (router != null) {
- router.close();
- }
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/XMPPServer.java b/juick-xmpp/src/main/java/com/juick/components/XMPPServer.java
deleted file mode 100644
index 6206914b..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/XMPPServer.java
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components;
-
-import com.juick.components.s2s.*;
-import com.juick.service.UserService;
-import com.juick.xmpp.extensions.JuickMessage;
-import com.juick.xmpp.extensions.StreamError;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.xmlpull.v1.XmlPullParserException;
-import rocks.xmpp.addr.Jid;
-import rocks.xmpp.core.stanza.model.Stanza;
-import rocks.xmpp.util.XmppUtils;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.net.ssl.*;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import java.io.*;
-import java.net.*;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.SecureRandom;
-import java.time.Instant;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static com.juick.components.s2s.Connection.NS_TLS;
-
-/**
- * @author ugnich
- */
-@Component
-public class XMPPServer implements ConnectionListener, AutoCloseable {
- private static final Logger logger = LoggerFactory.getLogger(XMPPServer.class);
-
- @Inject
- public ExecutorService service;
- @Value("${hostname}")
- private Jid jid;
- @Value("${s2s_port:5269}")
- private int s2sPort;
- @Value("${keystore}")
- public String keystore;
- @Value("${keystore_password}")
- public String keystorePassword;
- @Value("${broken_ssl_hosts}")
- public String[] brokenSSLhosts;
- @Value("${banned_hosts}")
- public String[] bannedHosts;
-
- private final List<ConnectionIn> inConnections = new CopyOnWriteArrayList<>();
- private final Map<ConnectionOut, Optional<Socket>> outConnections = new ConcurrentHashMap<>();
- private final List<CacheEntry> outCache = new CopyOnWriteArrayList<>();
- private final List<StanzaListener> stanzaListeners = new CopyOnWriteArrayList<>();
- private final AtomicBoolean closeFlag = new AtomicBoolean(false);
-
- SSLContext sc;
- private TrustManager[] trustAllCerts = new TrustManager[]{
- new X509TrustManager() {
- public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
- }
-
- public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
- }
- public java.security.cert.X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- }
- };
-
-
- private ServerSocket listener;
-
- @Inject
- private BasicXmppSession session;
- @Inject
- private UserService userService;
-
- @PostConstruct
- public void init() throws KeyStoreException {
- closeFlag.set(false);
- KeyStore ks = KeyStore.getInstance("JKS");
- try (InputStream ksIs = new FileInputStream(keystore)) {
- ks.load(ksIs, keystorePassword.toCharArray());
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
- .getDefaultAlgorithm());
- kmf.init(ks, keystorePassword.toCharArray());
- sc = SSLContext.getInstance("TLSv1.2");
- sc.init(kmf.getKeyManagers(), trustAllCerts, new SecureRandom());
- } catch (Exception e) {
- logger.warn("tls unavailable");
- }
- service.submit(() -> {
- try {
- listener = new ServerSocket(s2sPort);
- logger.info("s2s listener ready");
- while (!listener.isClosed()) {
- if (Thread.currentThread().isInterrupted()) break;
- Socket socket = listener.accept();
- ConnectionIn client = new ConnectionIn(this, socket);
- addConnectionIn(client);
- service.submit(client);
- }
- } catch (SocketException e) {
- // shutdown
- } catch (IOException | XmlPullParserException e) {
- logger.warn("xmpp exception", e);
- }
- });
- }
-
- @Override
- public void close() throws Exception {
- if (!listener.isClosed()) {
- listener.close();
- }
- outConnections.forEach((c, s) -> {
- c.logoff();
- outConnections.remove(c);
- });
- inConnections.forEach(c -> {
- c.closeConnection();
- inConnections.remove(c);
- });
- if (!listener.isClosed()) {
- listener.close();
- }
- service.shutdown();
- logger.info("XMPP server destroyed");
- }
-
- public void addConnectionIn(ConnectionIn c) {
- c.setListener(this);
- inConnections.add(c);
- }
-
- public void addConnectionOut(ConnectionOut c, Optional<Socket> socket) {
- c.setListener(this);
- outConnections.put(c, socket);
- }
-
- public void removeConnectionIn(ConnectionIn c) {
- inConnections.remove(c);
- }
-
- public void removeConnectionOut(ConnectionOut c) {
- outConnections.remove(c);
- }
-
- public String getFromCache(Jid to) {
- final String[] cache = new String[1];
- outCache.stream().filter(c -> c.hostname != null && c.hostname.equals(to)).findFirst().ifPresent(c -> {
- cache[0] = c.xml;
- outCache.remove(c);
- });
- return cache[0];
- }
-
- public Optional<ConnectionOut> getConnectionOut(Jid hostname, boolean needReady) {
- return outConnections.keySet().stream().filter(c -> c.to != null &&
- c.to.equals(hostname) && (!needReady || c.streamReady)).findFirst();
- }
-
- public Optional<ConnectionIn> getConnectionIn(String streamID) {
- return inConnections.stream().filter(c -> c.streamID != null && c.streamID.equals(streamID)).findFirst();
- }
-
- public void sendOut(Stanza s) {
- try {
- StringWriter stanzaWriter = new StringWriter();
- XMLStreamWriter xmppStreamWriter = XmppUtils.createXmppStreamWriter(
- session.getConfiguration().getXmlOutputFactory().createXMLStreamWriter(stanzaWriter));
- session.createMarshaller().marshal(s, xmppStreamWriter);
- xmppStreamWriter.flush();
- xmppStreamWriter.close();
- String xml = stanzaWriter.toString();
- logger.info("s2s (out): {}", xml);
- sendOut(Jid.of(s.getTo().getDomain()), xml);
- } catch (XMLStreamException | JAXBException e1) {
- logger.info("jaxb exception", e1);
- }
- }
-
- public void sendOut(Jid hostname, String xml) {
- boolean haveAnyConn = false;
-
- ConnectionOut connOut = null;
- for (ConnectionOut c : outConnections.keySet()) {
- if (c.to != null && c.to.equals(hostname)) {
- if (c.streamReady) {
- connOut = c;
- break;
- } else {
- haveAnyConn = true;
- break;
- }
- }
- }
- if (connOut != null) {
- connOut.send(xml);
- return;
- }
-
- boolean haveCache = false;
- for (CacheEntry c : outCache) {
- if (c.hostname != null && c.hostname.equals(hostname)) {
- c.xml += xml;
- c.updated = Instant.now();
- haveCache = true;
- break;
- }
- }
- if (!haveCache) {
- outCache.add(new CacheEntry(hostname, xml));
- }
-
- if (!haveAnyConn && !closeFlag.get()) {
- try {
- createDialbackConnection(hostname.toEscapedString(), null, null);
- } catch (Exception e) {
- logger.warn("dialback error", e);
- }
- }
- }
-
- void createDialbackConnection(String to, String checkSID, String dbKey) throws Exception {
- ConnectionOut connectionOut = new ConnectionOut(getJid(), Jid.of(to), null, null, checkSID, dbKey);
- addConnectionOut(connectionOut, Optional.empty());
- service.submit(() -> {
- try {
- Socket socket = new Socket();
- socket.connect(DNSQueries.getServerAddress(to));
- connectionOut.setInputStream(socket.getInputStream());
- connectionOut.setOutputStream(socket.getOutputStream());
- addConnectionOut(connectionOut, Optional.of(socket));
- connectionOut.addChildParser(new JuickMessage());
- connectionOut.connect();
- } catch (IOException e) {
- userService.getActiveJIDs().stream().filter(j -> Jid.of(j).getDomain().equals(to))
- .forEach(j -> {
- userService.setActiveStatusForJID(j, UserService.ActiveStatus.Inactive);
- logger.info("{} is inactive now", j);
- });
- }
- });
- }
-
- public void startDialback(Jid from, String streamId, String dbKey) throws Exception {
- Optional<ConnectionOut> c = getConnectionOut(from, false);
- if (c.isPresent()) {
- c.get().sendDialbackVerify(streamId, dbKey);
- } else {
- createDialbackConnection(from.toEscapedString(), streamId, dbKey);
- }
- }
-
- public void addStanzaListener(StanzaListener listener) {
- stanzaListeners.add(listener);
- }
-
- public void onStanzaReceived(String xmlValue) {
- Stanza stanza = parse(xmlValue);
- stanzaListeners.forEach(l -> l.stanzaReceived(stanza));
- }
-
- public BasicXmppSession getSession() {
- return session;
- }
-
- public List<ConnectionIn> getInConnections() {
- return inConnections;
- }
-
- public Map<ConnectionOut, Optional<Socket>> getOutConnections() {
- return outConnections;
- }
-
- @Override
- public void starttls(ConnectionIn connection) {
- logger.info("stream {} securing", connection.streamID);
- connection.sendStanza("<proceed xmlns=\"" + NS_TLS + "\" />");
- try {
- connection.setSocket(sc.getSocketFactory().createSocket(connection.getSocket(), connection.getSocket().getInetAddress().getHostAddress(),
- connection.getSocket().getPort(), true));
- ((SSLSocket) connection.getSocket()).setUseClientMode(false);
- ((SSLSocket) connection.getSocket()).startHandshake();
- connection.setSecured(true);
- logger.info("stream {} secured", connection.streamID);
- connection.restartParser();
- } catch (XmlPullParserException | IOException sex) {
- logger.warn("stream {} ssl error {}", connection.streamID, sex);
- connection.sendStanza("<failed xmlns\"" + NS_TLS + "\" />");
- removeConnectionIn(connection);
- connection.closeConnection();
- }
- }
-
- @Override
- public void proceed(ConnectionOut connection) {
- try {
- Socket socket = outConnections.get(connection).get();
- socket = sc.getSocketFactory().createSocket(socket, socket.getInetAddress().getHostAddress(),
- socket.getPort(), true);
- ((SSLSocket) socket).startHandshake();
- connection.setSecured(true);
- logger.info("stream {} secured", connection.getStreamID());
- connection.setInputStream(socket.getInputStream());
- connection.setOutputStream(socket.getOutputStream());
- connection.restartStream();
- connection.sendOpenStream();
- } catch (NoSuchElementException | XmlPullParserException | IOException sex) {
- logger.error("s2s ssl error: {} {}, error {}", connection.to, connection.getStreamID(), sex);
- connection.send("<failed xmlns\"" + NS_TLS + "\" />");
- removeConnectionOut(connection);
- connection.logoff();
- }
- }
-
- @Override
- public void verify(ConnectionOut connection, String from, String type, String sid) {
- if (from != null && from.equals(connection.to.toEscapedString()) && sid != null && !sid.isEmpty() && type != null) {
- getConnectionIn(sid).ifPresent(c -> c.sendDialbackResult(Jid.of(from), type));
- }
- }
-
- @Override
- public void dialbackError(ConnectionOut connection, StreamError error) {
- logger.warn("Stream error from {}: {}", connection.getStreamID(), error.getCondition());
- removeConnectionOut(connection);
- connection.logoff();
- }
-
- @Override
- public void finished(ConnectionOut connection, boolean dirty) {
- logger.warn("stream to {} {} finished, dirty={}", connection.to, connection.getStreamID(), dirty);
- removeConnectionOut(connection);
- connection.logoff();
- }
-
- @Override
- public void exception(ConnectionOut connection, Exception ex) {
- logger.error("s2s out exception: {} {}, exception {}", connection.to, connection.getStreamID(), ex);
- removeConnectionOut(connection);
- connection.logoff();
- }
-
- @Override
- public void ready(ConnectionOut connection) {
- logger.info("stream to {} {} ready", connection.to, connection.getStreamID());
- String cache = getFromCache(connection.to);
- if (cache != null) {
- logger.info("stream to {} {} sending cache", connection.to, connection.getStreamID());
- connection.send(cache);
- }
- }
-
- @Override
- public boolean securing(ConnectionOut connection) {
- return !Arrays.asList(brokenSSLhosts).contains(connection.to.toEscapedString());
- }
-
- public Stanza parse(String xml) {
- try {
- Unmarshaller unmarshaller = session.createUnmarshaller();
- return (Stanza)unmarshaller.unmarshal(new StringReader(xml));
- } catch (JAXBException e) {
- logger.error("JAXB exception", e);
- }
- return null;
- }
-
- public Jid getJid() {
- return jid;
- }
- @PreDestroy
- public void preDestroy() {
- closeFlag.set(true);
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/configuration/XmppAppConfiguration.java b/juick-xmpp/src/main/java/com/juick/components/configuration/XmppAppConfiguration.java
deleted file mode 100644
index f14b2b23..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/configuration/XmppAppConfiguration.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.configuration;
-
-/**
- * Created by aalexeev on 11/12/16.
- */
-
-import com.juick.components.s2s.BasicXmppSession;
-import com.juick.server.configuration.BaseWebConfiguration;
-import com.juick.xmpp.helpers.JidConverter;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.PropertySource;
-import org.springframework.core.convert.ConversionService;
-import org.springframework.format.support.DefaultFormattingConversionService;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import rocks.xmpp.core.session.Extension;
-import rocks.xmpp.core.session.XmppSessionConfiguration;
-import rocks.xmpp.core.session.debug.LogbackDebugger;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-@Configuration
-@ComponentScan(basePackages = {"com.juick.components"})
-@PropertySource("classpath:juick.conf")
-@EnableScheduling
-@EnableWebMvc
-public class XmppAppConfiguration extends BaseWebConfiguration {
- @Value("${hostname}")
- private String hostname;
-
- @Bean
- public ExecutorService service() {
- return Executors.newCachedThreadPool();
- }
- @Bean
- public BasicXmppSession session() {
- XmppSessionConfiguration configuration = XmppSessionConfiguration.builder()
- .extensions(Extension.of(com.juick.Message.class))
- .debugger(LogbackDebugger.class)
- .build();
- return BasicXmppSession.create(hostname, configuration);
- }
- @Bean
- public static ConversionService conversionService() {
- DefaultFormattingConversionService cs = new DefaultFormattingConversionService();
- cs.addConverter(new JidConverter());
- return cs;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/configuration/XmppInitializer.java b/juick-xmpp/src/main/java/com/juick/components/configuration/XmppInitializer.java
deleted file mode 100644
index 38dc05d4..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/configuration/XmppInitializer.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.configuration;
-
-import com.juick.configuration.DataConfiguration;
-import com.juick.server.configuration.StorageConfiguration;
-import org.apache.commons.codec.CharEncoding;
-import org.springframework.web.filter.CharacterEncodingFilter;
-import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
-
-import javax.servlet.Filter;
-
-/**
- * Created by vt on 09/02/16.
- */
-public class XmppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
-
- @Override
- protected Class<?>[] getRootConfigClasses() {
- return new Class<?>[]{ XmppAppConfiguration.class, DataConfiguration.class, StorageConfiguration.class};
- }
-
- @Override
- protected Class<?>[] getServletConfigClasses() {
- return null;
- }
-
- @Override
- protected String[] getServletMappings() {
- return new String[]{"/"};
- }
-
- @Override
- protected Filter[] getServletFilters() {
- CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(CharEncoding.UTF_8);
- return new Filter[]{characterEncodingFilter};
- }
-
- @Override
- protected String getServletName() {
- return "XMPP dispatcher servlet";
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/controllers/StatusController.java b/juick-xmpp/src/main/java/com/juick/components/controllers/StatusController.java
deleted file mode 100644
index f20fc76a..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/controllers/StatusController.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.controllers;
-
-import com.juick.components.XMPPServer;
-import com.juick.components.controllers.helpers.XMPPStatus;
-import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.inject.Inject;
-
-/**
- * Created by vitalyster on 24.10.2016.
- */
-@RestController
-public class StatusController {
- @Inject
- private XMPPServer xmpp;
-
- @RequestMapping(method = RequestMethod.GET, value = "/status", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
- public XMPPStatus status() {
- XMPPStatus status = new XMPPStatus();
- if (xmpp != null) {
- status.setInbound(xmpp.getInConnections());
- status.setOutbound(xmpp.getOutConnections().keySet());
- }
- return status;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/controllers/helpers/XMPPStatus.java b/juick-xmpp/src/main/java/com/juick/components/controllers/helpers/XMPPStatus.java
deleted file mode 100644
index c5a7f6e3..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/controllers/helpers/XMPPStatus.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.controllers.helpers;
-
-import com.juick.components.s2s.ConnectionIn;
-import com.juick.components.s2s.ConnectionOut;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Created by vitalyster on 16.02.2017.
- */
-public class XMPPStatus {
- private List<ConnectionIn> inbound;
- private Set<ConnectionOut> outbound;
-
- public List<ConnectionIn> getInbound() {
- return inbound;
- }
-
- public void setInbound(List<ConnectionIn> inbound) {
- this.inbound = inbound;
- }
-
- public Set<ConnectionOut> getOutbound() {
- return outbound;
- }
-
- public void setOutbound(Set<ConnectionOut> outbound) {
- this.outbound = outbound;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/BasicXmppSession.java b/juick-xmpp/src/main/java/com/juick/components/s2s/BasicXmppSession.java
deleted file mode 100644
index bf352f8c..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/BasicXmppSession.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-import rocks.xmpp.addr.Jid;
-import rocks.xmpp.core.XmppException;
-import rocks.xmpp.core.session.ConnectionConfiguration;
-import rocks.xmpp.core.session.XmppSession;
-import rocks.xmpp.core.session.XmppSessionConfiguration;
-import rocks.xmpp.core.stanza.model.IQ;
-import rocks.xmpp.core.stanza.model.Message;
-import rocks.xmpp.core.stanza.model.Presence;
-import rocks.xmpp.core.stanza.model.server.ServerIQ;
-import rocks.xmpp.core.stanza.model.server.ServerMessage;
-import rocks.xmpp.core.stanza.model.server.ServerPresence;
-import rocks.xmpp.core.stream.model.StreamElement;
-
-/**
- * Created by vitalyster on 06.02.2017.
- */
-public class BasicXmppSession extends XmppSession {
- protected BasicXmppSession(String xmppServiceDomain, XmppSessionConfiguration configuration, ConnectionConfiguration... connectionConfigurations) {
- super(xmppServiceDomain, configuration, connectionConfigurations);
- }
-
- public static BasicXmppSession create(String xmppServiceDomain, XmppSessionConfiguration configuration) {
- BasicXmppSession session = new BasicXmppSession(xmppServiceDomain, configuration);
- notifyCreationListeners(session);
- return session;
- }
-
- @Override
- public void connect(Jid from) throws XmppException {
-
- }
-
- @Override
- public Jid getConnectedResource() {
- return null;
- }
-
- @Override
- protected StreamElement prepareElement(StreamElement element) {
- if (element instanceof Message) {
- element = ServerMessage.from((Message) element);
- } else if (element instanceof Presence) {
- element = ServerPresence.from((Presence) element);
- } else if (element instanceof IQ) {
- element = ServerIQ.from((IQ) element);
- }
-
- return element;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/CacheEntry.java b/juick-xmpp/src/main/java/com/juick/components/s2s/CacheEntry.java
deleted file mode 100644
index c8eeab53..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/CacheEntry.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-import rocks.xmpp.addr.Jid;
-
-import java.time.Instant;
-
-/**
- *
- * @author ugnich
- */
-public class CacheEntry {
-
- public Jid hostname;
- public Instant created;
- public Instant updated;
- public String xml;
-
- public CacheEntry(Jid hostname, String xml) {
- this.hostname = hostname;
- this.created = this.updated =Instant.now();
- this.xml = xml;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/Connection.java b/juick-xmpp/src/main/java/com/juick/components/s2s/Connection.java
deleted file mode 100644
index 8157e046..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/Connection.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.juick.components.XMPPServer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.net.Socket;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.util.UUID;
-
-/**
- *
- * @author ugnich
- */
-public class Connection {
-
- protected static final Logger logger = LoggerFactory.getLogger(Connection.class);
-
- public String streamID;
- public Instant created;
- public Instant updated;
- public long bytesLocal = 0;
- public long packetsLocal = 0;
- XMPPServer xmpp;
- private Socket socket;
- public static final String NS_DB = "jabber:server:dialback";
- public static final String NS_TLS = "urn:ietf:params:xml:ns:xmpp-tls";
- public static final String NS_STREAM = "http://etherx.jabber.org/streams";
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- XmlPullParser parser = factory.newPullParser();
- OutputStreamWriter writer;
- private boolean secured = false;
-
-
-
- public Connection(XMPPServer xmpp) throws XmlPullParserException {
- this.xmpp = xmpp;
- created = updated = Instant.now();
- }
-
- public void logParser() {
- if (streamID == null) {
- return;
- }
- String tag = "IN: <" + parser.getName();
- for (int i = 0; i < parser.getAttributeCount(); i++) {
- tag += " " + parser.getAttributeName(i) + "=\"" + parser.getAttributeValue(i) + "\"";
- }
- tag += ">...</" + parser.getName() + ">\n";
- logger.trace(tag);
- }
-
- public void sendStanza(String xml) {
- if (streamID != null) {
- logger.trace("OUT: {}\n", xml);
- }
- try {
- writer.write(xml);
- writer.flush();
- } catch (IOException e) {
- logger.error("send stanza failed", e);
- }
-
- updated = Instant.now();
- bytesLocal += xml.length();
- packetsLocal++;
- }
-
- public void closeConnection() {
- if (streamID != null) {
- logger.info("closing stream {}", streamID);
- }
-
- try {
- writer.write("</stream:stream>");
- } catch (Exception e) {
- }
-
- try {
- writer.close();
- } catch (Exception e) {
- }
-
- try {
- socket.close();
- } catch (Exception e) {
- }
- }
-
- public boolean isSecured() {
- return secured;
- }
-
- public void setSecured(boolean secured) {
- this.secured = secured;
- }
-
- public void restartParser() throws XmlPullParserException, IOException {
- streamID = UUID.randomUUID().toString();
- parser = factory.newPullParser();
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- parser.setInput(new InputStreamReader(socket.getInputStream()));
- writer = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
- }
-
- @JsonIgnore
- public Socket getSocket() {
- return socket;
- }
-
- public void setSocket(Socket socket) {
- this.socket = socket;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionIn.java b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionIn.java
deleted file mode 100644
index 16f207a7..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionIn.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-import com.juick.components.XMPPServer;
-import com.juick.xmpp.extensions.StreamError;
-import com.juick.xmpp.utils.XmlUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import rocks.xmpp.addr.Jid;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.net.Socket;
-import java.net.SocketException;
-import java.time.Instant;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * @author ugnich
- */
-public class ConnectionIn extends Connection implements Runnable {
-
- final public List<Jid> from = new CopyOnWriteArrayList<>();
- public Instant received;
- public long packetsRemote = 0;
- ConnectionListener listener;
-
- public ConnectionIn(XMPPServer xmpp, Socket socket) throws XmlPullParserException, IOException {
- super(xmpp);
- this.setSocket(socket);
- restartParser();
- }
-
- @Override
- public void run() {
- try {
- parser.next(); // stream:stream
- updateTsRemoteData();
- if (!parser.getName().equals("stream")
- || !parser.getNamespace("stream").equals(NS_STREAM)) {
-// || !parser.getAttributeValue(null, "version").equals("1.0")
-// || !parser.getAttributeValue(null, "to").equals(Main.HOSTNAME)) {
- throw new Exception(String.format("stream from %s invalid", getSocket().getRemoteSocketAddress()));
- }
- streamID = parser.getAttributeValue(null, "id");
- if (streamID == null) {
- streamID = UUID.randomUUID().toString();
- }
- boolean xmppversionnew = parser.getAttributeValue(null, "version") != null;
- String from = parser.getAttributeValue(null, "from");
-
- if (Arrays.asList(xmpp.bannedHosts).contains(from)) {
- closeConnection();
- return;
- }
- sendOpenStream(from, xmppversionnew);
-
- while (parser.next() != XmlPullParser.END_DOCUMENT) {
- updateTsRemoteData();
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
- logParser();
-
- packetsRemote++;
-
- String tag = parser.getName();
- if (tag.equals("result") && parser.getNamespace().equals(NS_DB)) {
- String dfrom = parser.getAttributeValue(null, "from");
- String to = parser.getAttributeValue(null, "to");
- logger.info("stream from {} to {} {} asking for dialback", dfrom, to, streamID);
- if (dfrom.endsWith(xmpp.getJid().toEscapedString()) && (dfrom.equals(xmpp.getJid().toEscapedString())
- || dfrom.endsWith("." + xmpp.getJid()))) {
- logger.warn("stream from {} is invalid", dfrom);
- break;
- }
- if (to != null && to.equals(xmpp.getJid().toEscapedString())) {
- String dbKey = XmlUtils.getTagText(parser);
- updateTsRemoteData();
- xmpp.startDialback(Jid.of(dfrom), streamID, dbKey);
- } else {
- logger.warn("stream from " + dfrom + " " + streamID + " invalid to " + to);
- break;
- }
- } else if (tag.equals("verify") && parser.getNamespace().equals(NS_DB)) {
- String vfrom = parser.getAttributeValue(null, "from");
- String vto = parser.getAttributeValue(null, "to");
- String vid = parser.getAttributeValue(null, "id");
- String vkey = XmlUtils.getTagText(parser);
- updateTsRemoteData();
- final boolean[] valid = {false};
- if (vfrom != null && vto != null && vid != null && vkey != null) {
- xmpp.getConnectionOut(Jid.of(vfrom), false).ifPresent(c -> {
- String dialbackKey = c.dbKey;
- valid[0] = vkey.equals(dialbackKey);
- });
- }
- if (valid[0]) {
- sendStanza("<db:verify from='" + vto + "' to='" + vfrom + "' id='" + vid + "' type='valid'/>");
- logger.info("stream from {} {} dialback verify valid", vfrom, streamID);
- } else {
- sendStanza("<db:verify from='" + vto + "' to='" + vfrom + "' id='" + vid + "' type='invalid'/>");
- logger.warn("stream from {} {} dialback verify invalid", vfrom, streamID);
- }
- } else if (tag.equals("presence") && checkFromTo(parser)) {
- String xml = XmlUtils.parseToString(parser, false);
- logger.info("stream {} presence: {}", streamID, xml);
- xmpp.onStanzaReceived(xml);
- } else if (tag.equals("message") && checkFromTo(parser)) {
- updateTsRemoteData();
- String xml = XmlUtils.parseToString(parser, false);
- logger.info("stream {} message: {}", streamID, xml);
- xmpp.onStanzaReceived(xml);
-
- } else if (tag.equals("iq") && checkFromTo(parser)) {
- updateTsRemoteData();
- String type = parser.getAttributeValue(null, "type");
- String xml = XmlUtils.parseToString(parser, false);
- if (type == null || !type.equals("error")) {
- logger.info("stream {} iq: {}", streamID, xml);
- xmpp.onStanzaReceived(xml);
- }
- } else if (!isSecured() && tag.equals("starttls")) {
- listener.starttls(this);
- } else if (isSecured() && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) {
- sendOpenStream(null, true);
- } else if (tag.equals("error")) {
- StreamError streamError = StreamError.parse(parser);
- logger.warn("Stream error from {}: {}", streamID, streamError.getCondition());
- xmpp.removeConnectionIn(this);
- closeConnection();
- } else {
- String unhandledStanza = XmlUtils.parseToString(parser, true);
- logger.warn("Unhandled stanza from {}: {}", streamID, unhandledStanza);
- }
- }
- logger.warn("stream {} finished", streamID);
- xmpp.removeConnectionIn(this);
- closeConnection();
- } catch (EOFException | SocketException ex) {
- logger.info("stream {} closed (dirty)", streamID);
- xmpp.removeConnectionIn(this);
- closeConnection();
- } catch (Exception e) {
- logger.warn("stream {} error {}", streamID, e);
- xmpp.removeConnectionIn(this);
- closeConnection();
- }
- }
-
- void updateTsRemoteData() {
- received = Instant.now();
- }
-
- void sendOpenStream(String from, boolean xmppversionnew) throws IOException {
- String openStream = "<?xml version='1.0'?><stream:stream xmlns='jabber:server' " +
- "xmlns:stream='http://etherx.jabber.org/streams' xmlns:db='jabber:server:dialback' from='" +
- xmpp.getJid().toEscapedString() + "' id='" + streamID + "' version='1.0'>";
- if (xmppversionnew) {
- openStream += "<stream:features>";
- if (listener != null && !isSecured() && !Arrays.asList(xmpp.brokenSSLhosts).contains(from)) {
- openStream += "<starttls xmlns=\"" + NS_TLS + "\"><optional/></starttls>";
- }
- openStream += "</stream:features>";
- }
- sendStanza(openStream);
- }
-
- public void sendDialbackResult(Jid sfrom, String type) {
- sendStanza("<db:result from='" + xmpp.getJid().toEscapedString() + "' to='" + sfrom + "' type='" + type + "'/>");
- if (type.equals("valid")) {
- from.add(sfrom);
- logger.info("stream from {} {} ready", sfrom, streamID);
- }
- }
-
- boolean checkFromTo(XmlPullParser parser) throws Exception {
- String cfrom = parser.getAttributeValue(null, "from");
- String cto = parser.getAttributeValue(null, "to");
- if (StringUtils.isNotEmpty(cfrom) && StringUtils.isNotEmpty(cto)) {
- Jid jidto = Jid.of(cto);
- if (jidto.getDomain().equals(xmpp.getJid().toEscapedString())) {
- Jid jidfrom = Jid.of(cfrom);
- for (Jid aFrom : from) {
- if (aFrom.equals(Jid.of(jidfrom.getDomain()))) {
- return true;
- }
- }
- }
- }
- return false;
- }
- public void setListener(ConnectionListener listener) {
- this.listener = listener;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionListener.java b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionListener.java
deleted file mode 100644
index 3b191974..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionListener.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.juick.components.s2s;
-
-import com.juick.xmpp.extensions.StreamError;
-
-public interface ConnectionListener {
- void starttls(ConnectionIn connection);
- void proceed(ConnectionOut connection);
- void verify(ConnectionOut connection, String from, String type, String sid);
- void dialbackError(ConnectionOut connection, StreamError error);
- void finished(ConnectionOut connection, boolean dirty);
- void exception(ConnectionOut connection, Exception ex);
- void ready(ConnectionOut connection);
- boolean securing(ConnectionOut connection);
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java b/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java
deleted file mode 100644
index 9578a831..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/ConnectionOut.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-import com.juick.components.s2s.util.DialbackUtils;
-import com.juick.xmpp.Stream;
-import com.juick.xmpp.extensions.StreamError;
-import com.juick.xmpp.extensions.StreamFeatures;
-import com.juick.xmpp.utils.XmlUtils;
-import org.apache.commons.text.RandomStringGenerator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xmlpull.v1.XmlPullParser;
-import rocks.xmpp.addr.Jid;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketException;
-import java.util.UUID;
-
-/**
- * @author ugnich
- */
-public class ConnectionOut extends Stream {
- protected static final Logger logger = LoggerFactory.getLogger(ConnectionOut.class);
- public static final String NS_TLS = "urn:ietf:params:xml:ns:xmpp-tls";
- public static final String NS_DB = "jabber:server:dialback";
- private boolean secured = false;
-
- public boolean streamReady = false;
- String checkSID = null;
- String dbKey = null;
- private String streamID;
- ConnectionListener listener;
- RandomStringGenerator generator = new RandomStringGenerator.Builder().withinRange('a', 'z').build();
-
- public ConnectionOut(Jid from, Jid to, InputStream is, OutputStream os, String checkSID, String dbKey) throws Exception {
- super(from, to, is, os);
- this.to = to;
- this.checkSID = checkSID;
- this.dbKey = dbKey;
- if (dbKey == null) {
- this.dbKey = DialbackUtils.generateDialbackKey(generator.generate(15), to, from, streamID);
- }
- streamID = UUID.randomUUID().toString();
- }
-
- public void sendOpenStream() throws IOException {
- send("<?xml version='1.0'?><stream:stream xmlns='jabber:server' id='" + streamID +
- "' xmlns:stream='http://etherx.jabber.org/streams' xmlns:db='jabber:server:dialback' from='" +
- from.toEscapedString() + "' to='" + to.toEscapedString() + "' version='1.0'>");
- }
-
- void processDialback() throws Exception {
- if (checkSID != null) {
- sendDialbackVerify(checkSID, dbKey);
- }
- send("<db:result from='" + from.toEscapedString() + "' to='" + to.toEscapedString() + "'>" +
- dbKey + "</db:result>");
- }
-
- @Override
- public void handshake() {
- try {
- restartStream();
-
- sendOpenStream();
-
- parser.next(); // stream:stream
- streamID = parser.getAttributeValue(null, "id");
- if (streamID == null || streamID.isEmpty()) {
- throw new Exception("stream to " + to + " invalid first packet");
- }
-
- logger.info("stream to {} {} open", to, streamID);
- boolean xmppversionnew = parser.getAttributeValue(null, "version") != null;
- if (!xmppversionnew) {
- processDialback();
- }
-
- while (parser.next() != XmlPullParser.END_DOCUMENT) {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
-
- String tag = parser.getName();
- if (tag.equals("result") && parser.getNamespace().equals(NS_DB)) {
- String type = parser.getAttributeValue(null, "type");
- if (type != null && type.equals("valid")) {
- streamReady = true;
- listener.ready(this);
- } else {
- logger.info("stream to {} {} dialback fail", to, streamID);
- }
- XmlUtils.skip(parser);
- } else if (tag.equals("verify") && parser.getNamespace().equals(NS_DB)) {
- String from = parser.getAttributeValue(null, "from");
- String type = parser.getAttributeValue(null, "type");
- String sid = parser.getAttributeValue(null, "id");
- listener.verify(this, from, type, sid);
- XmlUtils.skip(parser);
- } else if (tag.equals("features") && parser.getNamespace().equals(NS_STREAM)) {
- StreamFeatures features = StreamFeatures.parse(parser);
- if (listener != null && !secured && features.STARTTLS >= 0
- && listener.securing(this)) {
- logger.info("stream to {} {} securing", to.toEscapedString(), streamID);
- send("<starttls xmlns=\"" + NS_TLS + "\" />");
- } else {
- processDialback();
- }
- } else if (tag.equals("proceed") && parser.getNamespace().equals(NS_TLS)) {
- listener.proceed(this);
- } else if (secured && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) {
- streamID = parser.getAttributeValue(null, "id");
- } else if (tag.equals("error")) {
- StreamError streamError = StreamError.parse(parser);
- listener.dialbackError(this, streamError);
- } else {
- String unhandledStanza = XmlUtils.parseToString(parser, true);
- logger.warn("Unhandled stanza from {} {} : {}", to, streamID, unhandledStanza);
- }
- }
- listener.finished(this, false);
- } catch (EOFException | SocketException eofex) {
- listener.finished(this, true);
- } catch (Exception e) {
- listener.exception(this, e);
- }
- }
-
- public void sendDialbackVerify(String sid, String key) {
- send("<db:verify from='" + from.toEscapedString() + "' to='" + to + "' id='" + sid + "'>" +
- key + "</db:verify>");
- }
- public void setListener(ConnectionListener listener) {
- this.listener = listener;
- }
-
- public String getStreamID() {
- return streamID;
- }
-
- public boolean isSecured() {
- return secured;
- }
-
- public void setSecured(boolean secured) {
- this.secured = secured;
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/DNSQueries.java b/juick-xmpp/src/main/java/com/juick/components/s2s/DNSQueries.java
deleted file mode 100644
index 0cd356b0..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/DNSQueries.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-import org.apache.commons.lang3.math.NumberUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.Hashtable;
-import java.util.Random;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-/**
- *
- * @author ugnich
- */
-public class DNSQueries {
-
- private static final Logger logger = LoggerFactory.getLogger(DNSQueries.class);
-
- private static Random rand = new Random();
-
- public static InetSocketAddress getServerAddress(String hostname) {
-
- String host = hostname;
- int port = 5269;
-
- Hashtable<String, String> env = new Hashtable<>(5);
- env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
- try {
- DirContext ctx = new InitialDirContext(env);
- Attribute att = ctx.getAttributes("_xmpp-server._tcp." + hostname, new String[]{"SRV"}).get("SRV");
-
- if (att != null && att.size() > 0) {
- int i = rand.nextInt(att.size());
- String srv[] = att.get(i).toString().split(" ");
- port = NumberUtils.toInt(srv[2], 5269);
- host = srv[3];
- }
- ctx.close();
- } catch (NamingException e) {
- logger.info("SRV record for {} is not resolved, falling back to A record", hostname);
- }
- return new InetSocketAddress(host, port);
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/StanzaListener.java b/juick-xmpp/src/main/java/com/juick/components/s2s/StanzaListener.java
deleted file mode 100644
index 39253d3f..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/StanzaListener.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s;
-
-
-import rocks.xmpp.core.stanza.model.Stanza;
-
-/**
- * Created by vitalyster on 07.12.2016.
- */
-public interface StanzaListener {
- void stanzaReceived(Stanza xmlValue);
-}
diff --git a/juick-xmpp/src/main/java/com/juick/components/s2s/util/DialbackUtils.java b/juick-xmpp/src/main/java/com/juick/components/s2s/util/DialbackUtils.java
deleted file mode 100644
index fc08c5d6..00000000
--- a/juick-xmpp/src/main/java/com/juick/components/s2s/util/DialbackUtils.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.juick.components.s2s.util;
-
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.codec.digest.HmacUtils;
-import rocks.xmpp.addr.Jid;
-
-/**
- * Created by vitalyster on 05.12.2016.
- */
-public class DialbackUtils {
- private DialbackUtils() {
- throw new IllegalStateException();
- }
-
- public static String generateDialbackKey(String secret, Jid to, Jid from, String id) {
- return HmacUtils.hmacSha256Hex(DigestUtils.sha256(secret),
- (to.toEscapedString() + " " + from.toEscapedString() + " " + id).getBytes());
- }
-}
diff --git a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java
deleted file mode 100644
index c28eee14..00000000
--- a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Juick
- * Copyright (C) 2008-2011, Ugnich Anton
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.juick.xmpp.extensions;
-
-import com.juick.Tag;
-import com.juick.xmpp.StanzaChild;
-import com.juick.xmpp.utils.XmlUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.text.StringEscapeUtils;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-/**
- *
- * @author Ugnich Anton
- */
-public class JuickMessage extends com.juick.Message implements StanzaChild {
- public final static String XMLNS = "http://juick.com/message";
- public final static String TagName = "juick";
- private SimpleDateFormat df;
- public JuickMessage() {
- df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
-
- @Override
- public String getXMLNS() {
- return XMLNS;
- }
- @Override
- public JuickMessage parse(XmlPullParser parser) throws XmlPullParserException, IOException, ParseException {
- JuickMessage jmsg = new JuickMessage();
- final String sMID = parser.getAttributeValue(null, "mid");
- if (sMID != null) {
- jmsg.setMid(Integer.parseInt(sMID));
- }
- final String sRID = parser.getAttributeValue(null, "rid");
- if (sRID != null) {
- jmsg.setRid(Integer.parseInt(sRID));
- }
- final String sReplyTo = parser.getAttributeValue(null, "replyto");
- if (sReplyTo != null) {
- jmsg.setReplyto(Integer.parseInt(sReplyTo));
- }
- final String sPrivacy = parser.getAttributeValue(null, "privacy");
- if (sPrivacy != null) {
- jmsg.setPrivacy(Integer.parseInt(sPrivacy));
- }
- final String sFriendsOnly = parser.getAttributeValue(null, "friendsonly");
- if (sFriendsOnly != null) {
- jmsg.FriendsOnly = true;
- }
- final String sReadOnly = parser.getAttributeValue(null, "readonly");
- if (sReadOnly != null) {
- jmsg.ReadOnly = true;
- }
- jmsg.setTimestamp(df.parse(parser.getAttributeValue(null, "ts")).toInstant());
- jmsg.setAttachmentType(parser.getAttributeValue(null, "attach"));
- while (parser.next() == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- final String xmlns = parser.getNamespace();
- if (tag.equals("body")) {
- jmsg.setText(XmlUtils.getTagText(parser));
- } else if (tag.equals(JuickUser.TagName) && xmlns != null && xmlns.equals(JuickUser.XMLNS)) {
- jmsg.setUser(new JuickUser().parse(parser));
- } else if (tag.equals("tag")) {
- jmsg.getTags().add(new Tag(XmlUtils.getTagText(parser)));
- } else {
- XmlUtils.skip(parser);
- }
- }
- return jmsg;
- }
- @Override
- public String toString() {
- StringBuilder ret = new StringBuilder("<").append(TagName).append(" xmlns=\"").append(XMLNS).append("\"");
- if (getMid() > 0) {
- ret.append(" mid=\"").append(getMid()).append("\"");
- }
- if (getRid() > 0) {
- ret.append(" rid=\"").append(getRid()).append("\"");
- }
- if (getReplyto() > 0) {
- ret.append(" replyto=\"").append(getReplyto()).append("\"");
- }
- ret.append(" privacy=\"").append(getPrivacy()).append("\"");
- if (FriendsOnly) {
- ret.append(" friendsonly=\"1\"");
- }
- if (ReadOnly) {
- ret.append(" readonly=\"1\"");
- }
- if (getTimestamp() != null) {
- ret.append(" ts=\"").append(df.format(Date.from(getTimestamp()))).append("\"");
- }
- if (getAttachmentType() != null) {
- ret.append(" attach=\"").append(getAttachmentType()).append("\"");
- }
- ret.append(">");
- if (getUser() != null) {
- ret.append(JuickUser.toString(getUser()));
- }
- if (getText() != null) {
- ret.append("<body>").append(StringEscapeUtils.escapeXml10(StringUtils.defaultString(getText()))).append("</body>");
- }
- for (Tag Tag : getTags()) {
- ret.append("<tag>").append(StringEscapeUtils.escapeXml10(Tag.getName())).append("</tag>");
- }
- ret.append("</").append(TagName).append(">");
- return ret.toString();
- }
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof JuickMessage)) {
- return false;
- }
- JuickMessage jmsg = (JuickMessage) obj;
- return (this.getMid() == jmsg.getMid() && this.getRid() == jmsg.getRid());
- }
- @Override
- public int compareTo(Object obj) throws ClassCastException {
- if (!(obj instanceof JuickMessage)) {
- throw new ClassCastException();
- }
- JuickMessage jmsg = (JuickMessage) obj;
- if (this.getMid() != jmsg.getMid()) {
- if (this.getMid() > jmsg.getMid()) {
- return -1;
- } else {
- return 1;
- }
- }
- if (this.getRid() != jmsg.getRid()) {
- if (this.getRid() < jmsg.getRid()) {
- return -1;
- } else {
- return 1;
- }
- }
- return 0;
- }
-} \ No newline at end of file
diff --git a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java
deleted file mode 100644
index 10d2b564..00000000
--- a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Juick
- * Copyright (C) 2008-2011, Ugnich Anton
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.juick.xmpp.extensions;
-import com.juick.xmpp.StanzaChild;
-import com.juick.xmpp.utils.XmlUtils;
-import org.apache.commons.text.StringEscapeUtils;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-/**
- *
- * @author Ugnich Anton
- */
-public class JuickUser extends com.juick.User implements StanzaChild {
- public final static String XMLNS = "http://juick.com/user";
- public final static String TagName = "user";
- public JuickUser() {
- }
- @Override
- public String getXMLNS() {
- return XMLNS;
- }
- @Override
- public JuickUser parse(final XmlPullParser parser) throws XmlPullParserException, IOException {
- JuickUser juser = new JuickUser();
- String strUID = parser.getAttributeValue(null, "uid");
- if (strUID != null) {
- juser.setUid(Integer.parseInt(strUID));
- }
- juser.setName(parser.getAttributeValue(null, "uname"));
- XmlUtils.skip(parser);
- return juser;
- }
- public static String toString(com.juick.User user) {
- String str = "<" + TagName + " xmlns='" + XMLNS + "'";
- if (user.getUid() > 0) {
- str += " uid='" + user.getUid() + "'";
- }
- if (user.getName() != null && user.getName().length() > 0) {
- str += " uname='" + StringEscapeUtils.escapeXml10(user.getName()) + "'";
- }
- str += "/>";
- return str;
- }
- @Override
- public String toString() {
- return toString(this);
- }
-} \ No newline at end of file
diff --git a/juick-xmpp/src/main/java/com/juick/xmpp/helpers/JidConverter.java b/juick-xmpp/src/main/java/com/juick/xmpp/helpers/JidConverter.java
deleted file mode 100644
index 253c50f8..00000000
--- a/juick-xmpp/src/main/java/com/juick/xmpp/helpers/JidConverter.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.juick.xmpp.helpers;
-
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.lang.Nullable;
-import rocks.xmpp.addr.Jid;
-
-public class JidConverter implements Converter<String, Jid> {
- @Nullable
- @Override
- public Jid convert(String jidStr) {
- return Jid.of(jidStr);
- }
-}
diff --git a/juick-xmpp/src/main/resources/juick.png b/juick-xmpp/src/main/resources/juick.png
deleted file mode 100644
index c85ef2c4..00000000
--- a/juick-xmpp/src/main/resources/juick.png
+++ /dev/null
Binary files differ
diff --git a/juick-xmpp/src/main/webapp/WEB-INF/web.xml b/juick-xmpp/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index a57cceb9..00000000
--- a/juick-xmpp/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
-
-</web-app> \ No newline at end of file
diff --git a/juick-xmpp/src/test/java/com/juick/xmpp/server/XMPPServerTests.java b/juick-xmpp/src/test/java/com/juick/xmpp/server/XMPPServerTests.java
deleted file mode 100644
index 7c5a1a98..00000000
--- a/juick-xmpp/src/test/java/com/juick/xmpp/server/XMPPServerTests.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package com.juick.xmpp.server;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.juick.Tag;
-import com.juick.User;
-import com.juick.components.JuickBot;
-import com.juick.components.XMPPServer;
-import com.juick.components.configuration.XmppAppConfiguration;
-import com.juick.configuration.RepositoryConfiguration;
-import com.juick.service.MessagesService;
-import com.juick.service.SubscriptionService;
-import com.juick.service.TagService;
-import com.juick.service.UserService;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.TestPropertySource;
-import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import org.springframework.web.context.WebApplicationContext;
-import rocks.xmpp.addr.Jid;
-import rocks.xmpp.core.stanza.model.Stanza;
-import rocks.xmpp.core.stanza.model.server.ServerMessage;
-
-import javax.inject.Inject;
-import java.lang.reflect.InvocationTargetException;
-import java.text.ParseException;
-import java.util.Collections;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@WebAppConfiguration
-@ContextConfiguration(classes = {
- XmppAppConfiguration.class, RepositoryConfiguration.class
-})
-@TestPropertySource(properties = {"broken_ssl_hosts=localhost,serverstorageisfull.tld"})
-public class XMPPServerTests extends AbstractJUnit4SpringContextTests {
- @Inject
- private WebApplicationContext wac;
- @Inject
- private XMPPServer server;
- @Inject
- private JuickBot bot;
- @Inject
- private UserService userService;
- @Inject
- private MessagesService messagesService;
- @Inject
- private TagService tagService;
- @Inject
- private SubscriptionService subscriptionService;
- @Inject
- private JdbcTemplate jdbcTemplate;
- @Value("${hostname}")
- private Jid jid;
-
- private MockMvc mockMvc;
-
- @Before
- public void setup() {
- mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
- }
- @Test
- public void statusPageIsUp() throws Exception {
- mockMvc.perform(get("http://localhost:8080/status")).andExpect(status().isOk());
- assertThat(server.getJid(), equalTo(jid));
- }
- @Test
- public void botIsUpAndProcessingResourceConstraints() {
- int renhaId;
- renhaId = userService.createUser("renha", "umnnbt");
- Jid from = Jid.of("renha@serverstorageisfull.tld");
- jdbcTemplate.update("INSERT INTO jids(user_id,jid,active) VALUES(?,?,?)", renhaId, from.toEscapedString(), 1);
- String xmlMessage = "<message xmlns=\"jabber:server\" from=\"renha@serverstorageisfull.tld\" to=\"juick@juick.com/Juick\" type=\"error\"><body>Reply by @LexX</body><juick xmlns=\"http://juick.com/message\" mid=\"2885759\" privacy=\"1\" replyto=\"0\" rid=\"8\" ts=\"2017-10-10 07:41:10\"><body>Похоже нынче можно публично заявлять о своем веганстве. </body><user xmlns=\"http://juick.com/user\" uname=\"LexX\" uid=\"6340\"></user></juick><error type=\"wait\"><resource-constraint xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"></resource-constraint><text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">Your contact offline message queue is full. The message has been discarded.</text></error></message>";
- Stanza msg = server.parse(xmlMessage);
- assertThat(from, equalTo(msg.getFrom()));
- boolean isActive = jdbcTemplate.queryForObject("SELECT active FROM jids WHERE user_id=?", Integer.class, renhaId) == 1;
- assertThat(isActive, equalTo(true));
- bot.incomingMessage((ServerMessage)msg);
- isActive = jdbcTemplate.queryForObject("SELECT active FROM jids WHERE user_id=?", Integer.class, renhaId) == 1;
- assertThat(isActive, equalTo(false));
- }
- @Test
- public void botCommandsTests() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- assertThat(bot.processCommand(new User(), Jid.of("test@localhost"), "PING").get(), is("PONG"));
- // subscription commands have two lines, others have 1
- assertThat(bot.processCommand(new User(), Jid.of("test@localhost"), "help").get().split("\n").length, is(23));
- }
-
- @Test
- public void protocolTests() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, ParseException, JsonProcessingException {
- int uid = userService.createUser("me", "secret");
- User user = userService.getUserByUID(uid).orElse(new User());
- Tag yo = tagService.getTag("yo", true);
- int mid = messagesService.createMessage(uid, "yoyo", null, Collections.singletonList(yo));
- assertEquals("should be message", true,
- bot.processCommand(user, Jid.of("test@localhost"), String.format("#%d", mid)).get().startsWith("@me"));
- mid = messagesService.getUserBlog(user.getUid(), -1, 0).stream().reduce((first, second) -> second).get();
- assertEquals("text should match", "yoyo",
- messagesService.getMessage(mid).getText());
- assertEquals("tag should match", "yo",
- tagService.getMessageTags(mid).get(0).getTag().getName());
- int readerUid = userService.createUser("dummyReader", "dummySecret");
- User readerUser = userService.getUserByUID(readerUid).orElse(new User());
- assertEquals("should be subscribed", "Subscribed",
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "S #" + mid).get());
- /* TODO: move from juick-legacy
- assertEquals("should be favorited", "Message added to your recommendations",
- juickProtocol.getReply(readerUser, "! #" + mid));
- */
- assertEquals("number of subscribed users should match", 1,
- subscriptionService.getUsersSubscribedToComments(mid, uid).size());
- /*
- assertEquals("should be subscribed", "Subscribed",
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "S @" + user.getName()).get());
- List<User> friends = userService.getUserFriends(readerUid);
- assertEquals("number of friend users should match", 2,
- friends.size());
- assertEquals("number of reader users should match", 1,
- userService.getUserReaders(uid).size());
- String expectedReply = "Reply posted.\n#" + mid + "/1 "
- + "http://juick.com/" + mid + "#1";
- String expectedSecondReply = "Reply posted.\n#" + mid + "/2 "
- + "http://juick.com/" + mid + "#2";
- assertEquals("should be reply", expectedReply,
- bot.processCommand(user, Jid.of("test@localhost"), "#" + mid + " yoyo").get());
- assertEquals("should be second reply", expectedSecondReply,
- bot.processCommand(user, Jid.of("test@localhost"), "#" + mid + "/1 yoyo").get());
- Message reply = messagesService.getReplies(mid).stream().filter(m -> m.getRid() == 2).findFirst()
- .orElse(new Message());
- assertEquals("should be reply to first comment", 1, reply.getReplyto());
- assertNotEquals("tags should NOT be updated", "Tags are updated",
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "#" + mid + " *yo *there").get());
- assertEquals("tags should be updated", "Tags are updated",
- bot.processCommand(user, Jid.of("test@localhost"), "#" + mid + " *there").get());
- assertEquals("number of tags should match", 2,
- tagService.getMessageTags(mid).size());
- assertEquals("should be blacklisted", "Tag added to your blacklist",
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "BL *there").get());
- assertEquals("number of subscribed users should match", 0,
- subscriptionService.getSubscribedUsers(uid, mid).size());
- assertEquals("tags should be updated", "Tags are updated",
- bot.processCommand(user, Jid.of("test@localhost"), "#" + mid + " *there").get());
- assertEquals("number of tags should match", 1,
- tagService.getMessageTags(mid).size());
- int taggerUid = userService.createUser("dummyTagger", "dummySecret");
- User taggerUser = userService.getUserByUID(taggerUid).orElse(new User());
- assertEquals("should be subscribed", "Subscribed",
- bot.processCommand(taggerUser, Jid.of("tagger@localhost"), "S *yo").get());
- assertEquals("number of subscribed users should match", 2,
- subscriptionService.getSubscribedUsers(uid, mid).size());
- assertEquals("should be unsubscribed", "Unsubscribed from yo",
- bot.processCommand(taggerUser, Jid.of("tagger@localhost"), "U *yo").get());
- assertEquals("number of subscribed users should match", 1,
- subscriptionService.getSubscribedUsers(uid, mid).size());
- assertEquals("number of readers should match", 1,
- userService.getUserReaders(uid).size());
- String readerFeed = bot.processCommand(readerUser, Jid.of("dummy@localhost"), "#").get();
- assertEquals("description should match", true, readerFeed.startsWith("Your feed"));
- assertEquals("should be unsubscribed", "Unsubscribed from @" + user.getName(),
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "U @" + user.getName()).get());
- assertEquals("number of readers should match", 0,
- userService.getUserReaders(uid).size());
- assertEquals("number of friends should match", 1,
- userService.getUserFriends(uid).size());
- assertEquals("should be unsubscribed", "Unsubscribed from #" + mid,
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "u #" + mid).get());
- assertEquals("number of subscribed users should match", 0,
- subscriptionService.getUsersSubscribedToComments(mid, uid).size());
- assertNotEquals("should NOT be deleted", String.format("Message %s deleted", mid),
- bot.processCommand(readerUser, Jid.of("dummy@localhost"), "D #" + mid).get());
- assertEquals("should be deleted", String.format("Message %s deleted", mid),
- bot.processCommand(user, Jid.of("test@localhost"), "D #" + mid).get());
- assertEquals("should not have messages", 0, messagesService.getAll(user.getUid(), 0).size());
- */
- }
-}