/*
* 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 .
*/
package com.juick.www;
import com.juick.Message;
import com.juick.server.UserQueries;
import com.mitchellbosecke.pebble.error.PebbleException;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import rocks.xmpp.addr.Jid;
import rocks.xmpp.core.XmppException;
import rocks.xmpp.core.session.Extension;
import rocks.xmpp.core.session.XmppSessionConfiguration;
import rocks.xmpp.core.session.debug.LogbackDebugger;
import rocks.xmpp.extensions.component.accept.ExternalComponent;
import ru.sape.Sape;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Objects;
import java.util.Properties;
/**
*
* @author Ugnich Anton
*/
@WebServlet(name = "Main", urlPatterns = {"/"})
@MultipartConfig(fileSizeThreshold = 1024 * 1024, maxRequestSize = 1024 * 1024 * 10)
public class Main extends HttpServlet {
JdbcTemplate sql;
JdbcTemplate sqlSearch;
String sqlSearchConnStr = "jdbc:mysql://127.0.0.1:9306?autoReconnect=true&useUnicode=yes&characterEncoding=utf8&maxAllowedPacket=512000";
ExternalComponent xmpp;
Home home = new Home();
Discover discover = new Discover();
PM pm = new PM();
Login login = new Login();
Help help = new Help();
User pagesUser = new User();
UserThread pagesUserThread = new UserThread();
NewMessage pagesNewMessage;
FacebookLogin loginFacebook;
VKontakteLogin loginVK = new VKontakteLogin();
TwitterAuth twitterAuth;
SignUp signup = new SignUp();
Settings settings;
RSS rss = new RSS();
@Override
public void init() throws ServletException {
super.init();
try {
Properties conf = new Properties();
conf.load(getServletContext().getResourceAsStream("/WEB-INF/juick.conf"));
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(conf.getProperty("datasource_driver", "com.mysql.jdbc.Driver"));
dataSource.setUrl(conf.getProperty("datasource_url"));
BasicDataSource dataSourceSearch = new BasicDataSource();
dataSourceSearch.setDriverClassName(conf.getProperty("datasource_driver", "com.mysql.jdbc.Driver"));
dataSourceSearch.setUrl(sqlSearchConnStr);
sql = new JdbcTemplate(dataSource);
sqlSearch = new JdbcTemplate(dataSourceSearch);
boolean isXmppDisabled = BooleanUtils.toBoolean(conf.getProperty("xmpp_disabled"));
if (!isXmppDisabled) {
setupXmppComponent(Jid.of(conf.getProperty("www_xmpp_jid", "www.juick.local")),
conf.getProperty("xmpp_password"), NumberUtils.toInt(conf.getProperty("xmpp_port", ""), 5347));
}
twitterAuth = new TwitterAuth(conf.getProperty("twitter_consumer_key"),
conf.getProperty("twitter_consumer_secret"));
loginFacebook = new FacebookLogin(conf.getProperty("facebook_appid"), conf.getProperty("facebook_secret"));
String tmpDir = conf.getProperty("upload_tmp_dir", "/var/www/juick.com/i/tmp/");
Utils.setTmpDir(tmpDir);
String imgPath = conf.getProperty("img_path", "/var/www/juick.com/i/");
pagesNewMessage = new NewMessage(tmpDir, imgPath);
settings = new Settings(imgPath);
String sapeUser = conf.getProperty("sape_user", "");
if (!Objects.equals(sapeUser, "")) {
PageTemplates.sape = new Sape(sapeUser, "juick.com", 2000, 3600);
} else {
log("Sape is not initialized");
}
} catch (Exception e) {
log(null, e);
}
}
@Override
public void destroy() {
try {
if (xmpp != null)
xmpp.close();
log("ExternalComponent on WWW destroyed");
} catch (Exception e) {
log("exception on destroy", e);
}
}
public void setupXmppComponent(final Jid componentJid, final String password, final int port) {
XmppSessionConfiguration configuration = XmppSessionConfiguration.builder()
.extensions(Extension.of(Message.class))
.debugger(LogbackDebugger.class)
.build();
xmpp = ExternalComponent.create(componentJid.toString(), password, configuration, "localhost", port);
xmpp.addConnectionListener(e -> log(e.toString(), e.getCause()));
try {
xmpp.connect();
} catch (XmppException e) {
log("xmpp extension", e);
}
}
/**
* Handles the HTTP GET
method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getCharacterEncoding() == null) {
request.setCharacterEncoding("UTF-8");
}
String uri = request.getRequestURI();
if (uri.equals("/")) {
String tag = request.getParameter("tag");
if (tag != null) {
Utils.sendPermanentRedirect(response, "/tag/" + URLEncoder.encode(tag, "UTF-8"));
} else {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
home.doGet(sql, sqlSearch, request, response, visitor);
}
} else if (uri.equals("/post")) {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
if (visitor.getUid() > 0) {
pagesNewMessage.doGetNewMessage(sql, request, response, visitor);
} else {
Utils.sendTemporaryRedirect(response, "/login");
}
} else if (uri.equals("/login")) {
if (request.getQueryString() == null) {
login.doGetLoginForm(sql, request, response);
} else {
login.doGetLogin(sql, request, response);
}
} else if (uri.startsWith("/pm/")) {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
if (visitor.getUid() == 0) {
Utils.sendTemporaryRedirect(response, "/login");
} else {
switch (uri) {
case "/pm/inbox":
try {
pm.doGetInbox(sql, request, response, visitor);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
break;
case "/pm/sent":
try {
pm.doGetSent(sql, request, response, visitor);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
break;
default:
Errors.doGet404(sql, request, response);
break;
}
}
} else if (uri.startsWith("/rss/")) {
String uname = uri.substring(5);
int uid = UserQueries.getUIDbyName(sql, uname);
if (uid > 0) {
try {
rss.doGet(sql, response, uid);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} else if (uri.equals("/logout")) {
login.doGetLogout(sql, request, response);
} else if (uri.equals("/settings")) {
try {
settings.doGet(sql, request, response);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} else if (uri.equals("/_fblogin")) {
loginFacebook.doGet(sql, request, response);
} else if (uri.equals("/_vklogin")) {
loginVK.doGet(sql, request, response);
} else if (uri.startsWith("/_twitter")) {
twitterAuth.doGet(sql, request, response);
} else if (uri.equals("/signup")) {
try {
signup.doGet(sql, request, response);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} else if (uri.equals("/help") || uri.equals("/help/")) {
help.doRedirectToHelpIndex(response);
} else if (uri.startsWith("/help/")) {
try {
help.doGetHelp(sql, request, response);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (URISyntaxException e) {
log("help exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} else if (uri.startsWith("/tag/")) {
discover.doGet(sql, sqlSearch, request, response);
} else if (uri.matches("^/\\d+$")) {
String strID = request.getRequestURI().substring(1);
int mid = 0;
try {
mid = Integer.parseInt(strID);
} catch (NumberFormatException e) {
}
if (mid > 0) {
com.juick.User author = com.juick.server.MessagesQueries.getMessageAuthor(sql, mid);
if (author != null) {
Utils.sendPermanentRedirect(response, "/" + author.getName() + "/" + mid);
return;
}
}
Errors.doGet404(sql, request, response);
} else if (uri.matches("^/[^/]+$")) {
com.juick.User user = com.juick.server.UserQueries.getUserByName(sql, request.getRequestURI().substring(1));
if (user != null) {
Utils.sendPermanentRedirect(response, "/" + user.getName() + "/");
} else {
Errors.doGet404(sql, request, response);
}
} else if (uri.matches("^/.+/.*")) {
String uriparts[] = uri.split("/");
com.juick.User user = com.juick.server.UserQueries.getUserByName(sql, uriparts[1]);
if (user != null && user.getName().equals(uriparts[1]) && !user.isBanned()) {
if (uriparts.length == 2) { // http://juick.com/username/
pagesUser.doGetBlog(sql, sqlSearch, request, response, user);
} else if (uriparts[2].equals("tags")) {
pagesUser.doGetTags(sql, request, response, user);
} else if (uriparts[2].equals("friends")) {
pagesUser.doGetFriends(sql, request, response, user);
} else if (uriparts[2].equals("readers")) {
pagesUser.doGetReaders(sql, request, response, user);
} else {
int mid = 0;
try {
mid = Integer.parseInt(uriparts[2]);
} catch (NumberFormatException e) {
}
if (mid > 0) {
com.juick.User author = com.juick.server.MessagesQueries.getMessageAuthor(sql, mid);
if (author != null) {
if (!author.getName().equals(user.getName())) {
Utils.sendPermanentRedirect(response, "/" + author.getName() + "/" + mid);
} else {
pagesUserThread.doGetThread(sql, request, response, mid);
}
} else {
Errors.doGet404(sql, request, response);
}
} else {
Errors.doGet404(sql, request, response);
}
}
} else if (user != null && !user.isBanned()) {
Utils.sendPermanentRedirect(response, "/" + user.getName() + "/" + (uriparts.length > 2 ? uriparts[2] : ""));
} else {
Errors.doGet404(sql, request, response);
}
} else {
Errors.doGet404(sql, request, response);
}
}
/**
* Handles the HTTP POST
method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getCharacterEncoding() == null) {
request.setCharacterEncoding("UTF-8");
}
String uri = request.getRequestURI();
switch (uri) {
case "/post": {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
if (visitor.getUid() > 0 && !visitor.isBanned()) {
pagesNewMessage.doPostMessage(sql, request, response, xmpp, visitor);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
break;
}
case "/comment": {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
if (visitor.getUid() > 0 && !visitor.isBanned()) {
pagesNewMessage.doPostComment(sql, request, response, xmpp, visitor);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
break;
}
case "/like": {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
if (visitor.getUid() > 0 && !visitor.isBanned()) {
pagesNewMessage.doPostRecomm(sql, request, response, xmpp, visitor);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
break;
}
case "/pm/send": {
com.juick.User visitor = Utils.getVisitorUser(sql, request, response);
if (visitor.getUid() > 0 && !visitor.isBanned()) {
pm.doPostPM(sql, request, response, xmpp, visitor);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
break;
}
case "/login":
login.doPostLogin(sql, request, response);
break;
case "/signup":
signup.doPost(sql, request, response);
break;
case "/settings":
try {
settings.doPost(sql, request, response);
} catch (PebbleException e) {
log("pebble exception", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
break;
default:
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
break;
}
}
}