/* * 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; } } }