Commit 227b28b5 authored by Liang Ding's avatar Liang Ding

Fix #12060

parent 51bf1e63
...@@ -16,8 +16,10 @@ ...@@ -16,8 +16,10 @@
package org.b3log.solo; package org.b3log.solo;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.Set;
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextEvent;
import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestEvent;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionEvent;
...@@ -35,6 +37,7 @@ import org.b3log.latke.servlet.AbstractServletListener; ...@@ -35,6 +37,7 @@ import org.b3log.latke.servlet.AbstractServletListener;
import org.b3log.latke.util.Requests; import org.b3log.latke.util.Requests;
import org.b3log.latke.util.Stopwatchs; import org.b3log.latke.util.Stopwatchs;
import org.b3log.latke.util.Strings; import org.b3log.latke.util.Strings;
import org.b3log.latke.util.freemarker.Templates;
import org.b3log.solo.event.comment.ArticleCommentReplyNotifier; import org.b3log.solo.event.comment.ArticleCommentReplyNotifier;
import org.b3log.solo.event.comment.PageCommentReplyNotifier; import org.b3log.solo.event.comment.PageCommentReplyNotifier;
import org.b3log.solo.event.plugin.PluginRefresher; import org.b3log.solo.event.plugin.PluginRefresher;
...@@ -56,7 +59,7 @@ import org.json.JSONObject; ...@@ -56,7 +59,7 @@ import org.json.JSONObject;
* Solo Servlet listener. * Solo Servlet listener.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.7.0.13, Dec 23, 2015 * @version 1.8.0.13, Dec 27, 2015
* @since 0.3.1 * @since 0.3.1
*/ */
public final class SoloServletListener extends AbstractServletListener { public final class SoloServletListener extends AbstractServletListener {
...@@ -277,6 +280,25 @@ public final class SoloServletListener extends AbstractServletListener { ...@@ -277,6 +280,25 @@ public final class SoloServletListener extends AbstractServletListener {
* @param httpServletRequest the specified HTTP servlet request * @param httpServletRequest the specified HTTP servlet request
*/ */
private void resolveSkinDir(final HttpServletRequest httpServletRequest) { private void resolveSkinDir(final HttpServletRequest httpServletRequest) {
// https://github.com/b3log/solo/issues/12060
final Cookie[] cookies = httpServletRequest.getCookies();
if (null != cookies) {
for (final Cookie cookie : cookies) {
if (Skin.SKIN.equals(cookie.getName())) {
final String skin = cookie.getValue();
final Set<String> skinDirNames = Skins.getSkinDirNames();
if (skinDirNames.contains(skin)) {
Templates.MAIN_CFG.setServletContextForTemplateLoading(SoloServletListener.getServletContext(),
"/skins/" + skin);
httpServletRequest.setAttribute(Keys.TEMAPLTE_DIR_NAME, skin);
return;
}
}
}
}
try { try {
final PreferenceQueryService preferenceQueryService = beanManager.getReference(PreferenceQueryService.class); final PreferenceQueryService preferenceQueryService = beanManager.getReference(PreferenceQueryService.class);
final JSONObject preference = preferenceQueryService.getPreference(); final JSONObject preference = preferenceQueryService.getPreference();
...@@ -296,6 +318,8 @@ public final class SoloServletListener extends AbstractServletListener { ...@@ -296,6 +318,8 @@ public final class SoloServletListener extends AbstractServletListener {
LOGGER.log(Level.DEBUG, "The request [URI={0}] comes frome mobile device", requestURI); LOGGER.log(Level.DEBUG, "The request [URI={0}] comes frome mobile device", requestURI);
} }
Templates.MAIN_CFG.setServletContextForTemplateLoading(SoloServletListener.getServletContext(),
"/skins/" + desiredView);
httpServletRequest.setAttribute(Keys.TEMAPLTE_DIR_NAME, desiredView); httpServletRequest.setAttribute(Keys.TEMAPLTE_DIR_NAME, desiredView);
} catch (final Exception e) { } catch (final Exception e) {
LOGGER.log(Level.ERROR, "Resolves skin failed", e); LOGGER.log(Level.ERROR, "Resolves skin failed", e);
......
...@@ -21,6 +21,7 @@ import java.io.PrintWriter; ...@@ -21,6 +21,7 @@ import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -39,8 +40,12 @@ import org.b3log.latke.servlet.renderer.freemarker.AbstractFreeMarkerRenderer; ...@@ -39,8 +40,12 @@ import org.b3log.latke.servlet.renderer.freemarker.AbstractFreeMarkerRenderer;
import org.b3log.latke.servlet.renderer.freemarker.FreeMarkerRenderer; import org.b3log.latke.servlet.renderer.freemarker.FreeMarkerRenderer;
import org.b3log.latke.util.Locales; import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Requests; import org.b3log.latke.util.Requests;
import org.b3log.latke.util.Strings;
import org.b3log.latke.util.freemarker.Templates;
import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Common; import org.b3log.solo.model.Common;
import org.b3log.solo.model.Option; import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import org.b3log.solo.processor.renderer.ConsoleRenderer; import org.b3log.solo.processor.renderer.ConsoleRenderer;
import org.b3log.solo.processor.util.Filler; import org.b3log.solo.processor.util.Filler;
import org.b3log.solo.service.PreferenceQueryService; import org.b3log.solo.service.PreferenceQueryService;
...@@ -53,7 +58,7 @@ import org.json.JSONObject; ...@@ -53,7 +58,7 @@ import org.json.JSONObject;
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="mailto:385321165@qq.com">DASHU</a> * @author <a href="mailto:385321165@qq.com">DASHU</a>
* @version 1.1.2.6, Nov 20, 2015 * @version 1.2.2.6, Dec 27, 2015
* @since 0.3.1 * @since 0.3.1
*/ */
@RequestProcessor @RequestProcessor
...@@ -98,18 +103,28 @@ public class IndexProcessor { ...@@ -98,18 +103,28 @@ public class IndexProcessor {
@RequestProcessing(value = {"/\\d*", ""}, uriPatternsMode = URIPatternMode.REGEX, method = HTTPRequestMethod.GET) @RequestProcessing(value = {"/\\d*", ""}, uriPatternsMode = URIPatternMode.REGEX, method = HTTPRequestMethod.GET)
public void showIndex(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response) { public void showIndex(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response) {
final AbstractFreeMarkerRenderer renderer = new FreeMarkerRenderer(); final AbstractFreeMarkerRenderer renderer = new FreeMarkerRenderer();
context.setRenderer(renderer); context.setRenderer(renderer);
renderer.setTemplateName("index.ftl"); renderer.setTemplateName("index.ftl");
final Map<String, Object> dataModel = renderer.getDataModel(); final Map<String, Object> dataModel = renderer.getDataModel();
final String requestURI = request.getRequestURI(); final String requestURI = request.getRequestURI();
try { try {
final int currentPageNum = getCurrentPageNum(requestURI); final int currentPageNum = getCurrentPageNum(requestURI);
final JSONObject preference = preferenceQueryService.getPreference(); final JSONObject preference = preferenceQueryService.getPreference();
// https://github.com/b3log/solo/issues/12060
String specifiedSkin = Skins.getSkinDirName(request);
if (null != specifiedSkin) {
if ("default".equals(specifiedSkin)) {
specifiedSkin = preference.optString(Option.ID_C_SKIN_DIR_NAME);
}
} else {
specifiedSkin = preference.optString(Option.ID_C_SKIN_DIR_NAME);
}
Templates.MAIN_CFG.setServletContextForTemplateLoading(SoloServletListener.getServletContext(),
"/skins/" + specifiedSkin);
request.setAttribute(Keys.TEMAPLTE_DIR_NAME, specifiedSkin);
Skins.fillLangs(preference.optString(Option.ID_C_LOCALE_STRING), (String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME), dataModel); Skins.fillLangs(preference.optString(Option.ID_C_LOCALE_STRING), (String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME), dataModel);
filler.fillIndexArticles(request, dataModel, currentPageNum, preference); filler.fillIndexArticles(request, dataModel, currentPageNum, preference);
...@@ -121,14 +136,19 @@ public class IndexProcessor { ...@@ -121,14 +136,19 @@ public class IndexProcessor {
dataModel.put(Pagination.PAGINATION_CURRENT_PAGE_NUM, currentPageNum); dataModel.put(Pagination.PAGINATION_CURRENT_PAGE_NUM, currentPageNum);
final int previousPageNum = currentPageNum > 1 ? currentPageNum - 1 : 0; final int previousPageNum = currentPageNum > 1 ? currentPageNum - 1 : 0;
dataModel.put(Pagination.PAGINATION_PREVIOUS_PAGE_NUM, previousPageNum); dataModel.put(Pagination.PAGINATION_PREVIOUS_PAGE_NUM, previousPageNum);
final Integer pageCount = (Integer) dataModel.get(Pagination.PAGINATION_PAGE_COUNT); final Integer pageCount = (Integer) dataModel.get(Pagination.PAGINATION_PAGE_COUNT);
final int nextPageNum = currentPageNum+1 > pageCount ? pageCount : currentPageNum + 1; final int nextPageNum = currentPageNum + 1 > pageCount ? pageCount : currentPageNum + 1;
dataModel.put(Pagination.PAGINATION_NEXT_PAGE_NUM, nextPageNum); dataModel.put(Pagination.PAGINATION_NEXT_PAGE_NUM, nextPageNum);
dataModel.put(Common.PATH, ""); dataModel.put(Common.PATH, "");
statisticMgmtService.incBlogViewCount(request, response); statisticMgmtService.incBlogViewCount(request, response);
// https://github.com/b3log/solo/issues/12060
final Cookie cookie = new Cookie(Skin.SKIN, specifiedSkin);
cookie.setPath("/");
response.addCookie(cookie);
} catch (final ServiceException e) { } catch (final ServiceException e) {
LOGGER.log(Level.ERROR, e.getMessage(), e); LOGGER.log(Level.ERROR, e.getMessage(), e);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package org.b3log.solo.processor.console; package org.b3log.solo.processor.console;
import javax.inject.Inject; import javax.inject.Inject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -32,6 +33,7 @@ import org.b3log.latke.servlet.renderer.JSONRenderer; ...@@ -32,6 +33,7 @@ import org.b3log.latke.servlet.renderer.JSONRenderer;
import org.b3log.latke.util.Requests; import org.b3log.latke.util.Requests;
import org.b3log.solo.model.Option; import org.b3log.solo.model.Option;
import org.b3log.solo.model.Sign; import org.b3log.solo.model.Sign;
import org.b3log.solo.model.Skin;
import org.b3log.solo.service.OptionMgmtService; import org.b3log.solo.service.OptionMgmtService;
import org.b3log.solo.service.OptionQueryService; import org.b3log.solo.service.OptionQueryService;
import org.b3log.solo.service.PreferenceMgmtService; import org.b3log.solo.service.PreferenceMgmtService;
...@@ -435,6 +437,10 @@ public class PreferenceConsole { ...@@ -435,6 +437,10 @@ public class PreferenceConsole {
} }
preferenceMgmtService.updatePreference(preference); preferenceMgmtService.updatePreference(preference);
final Cookie cookie = new Cookie(Skin.SKIN, preference.getString(Skin.SKIN_DIR_NAME));
cookie.setPath("/");
response.addCookie(cookie);
ret.put(Keys.STATUS_CODE, true); ret.put(Keys.STATUS_CODE, true);
ret.put(Keys.MSG, langPropsService.get("updateSuccLabel")); ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
*/ */
package org.b3log.solo.util; package org.b3log.solo.util;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
...@@ -24,6 +23,8 @@ import java.util.Map; ...@@ -24,6 +23,8 @@ import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.b3log.latke.Latkes; import org.b3log.latke.Latkes;
import org.b3log.latke.ioc.LatkeBeanManager; import org.b3log.latke.ioc.LatkeBeanManager;
import org.b3log.latke.ioc.Lifecycle; import org.b3log.latke.ioc.Lifecycle;
...@@ -34,15 +35,16 @@ import org.b3log.latke.service.LangPropsServiceImpl; ...@@ -34,15 +35,16 @@ import org.b3log.latke.service.LangPropsServiceImpl;
import org.b3log.latke.service.ServiceException; import org.b3log.latke.service.ServiceException;
import org.b3log.latke.util.Locales; import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Stopwatchs; import org.b3log.latke.util.Stopwatchs;
import org.b3log.latke.util.Strings;
import org.b3log.latke.util.freemarker.Templates; import org.b3log.latke.util.freemarker.Templates;
import org.b3log.solo.SoloServletListener; import org.b3log.solo.SoloServletListener;
import org.b3log.solo.model.Skin;
/** /**
* Skin utilities. * Skin utilities.
* *
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.4.7, Nov 1, 2015 * @version 1.1.4.7, Dec 27, 2015
* @since 0.3.1 * @since 0.3.1
*/ */
public final class Skins { public final class Skins {
...@@ -60,11 +62,12 @@ public final class Skins { ...@@ -60,11 +62,12 @@ public final class Skins {
/** /**
* Private default constructor. * Private default constructor.
*/ */
private Skins() {} private Skins() {
}
/** /**
* Fills the specified data model with the current skink's (WebRoot/skins/${skinName}/lang/lang_xx_XX.properties) and * Fills the specified data model with the current skink's (WebRoot/skins/${skinName}/lang/lang_xx_XX.properties)
* core language (WebRoot/WEB-INF/classes/lang_xx_XX.properties) configurations. * and core language (WebRoot/WEB-INF/classes/lang_xx_XX.properties) configurations.
* *
* @param localeString the specified locale string * @param localeString the specified locale string
* @param currentSkinDirName the specified current skin directory name * @param currentSkinDirName the specified current skin directory name
...@@ -72,7 +75,7 @@ public final class Skins { ...@@ -72,7 +75,7 @@ public final class Skins {
* @throws ServiceException service exception * @throws ServiceException service exception
*/ */
public static void fillLangs(final String localeString, final String currentSkinDirName, final Map<String, Object> dataModel) public static void fillLangs(final String localeString, final String currentSkinDirName, final Map<String, Object> dataModel)
throws ServiceException { throws ServiceException {
Stopwatchs.start("Fill Skin Langs"); Stopwatchs.start("Fill Skin Langs");
try { try {
...@@ -82,7 +85,7 @@ public final class Skins { ...@@ -82,7 +85,7 @@ public final class Skins {
if (null == langs) { if (null == langs) {
LANG_MAP.clear(); // Collect unused skin languages LANG_MAP.clear(); // Collect unused skin languages
LOGGER.log(Level.DEBUG, "Loading skin [dirName={0}, locale={1}]", new Object[] {currentSkinDirName, localeString}); LOGGER.log(Level.DEBUG, "Loading skin [dirName={0}, locale={1}]", new Object[]{currentSkinDirName, localeString});
langs = new HashMap<String, String>(); langs = new HashMap<String, String>();
final String language = Locales.getLanguage(localeString); final String language = Locales.getLanguage(localeString);
...@@ -90,7 +93,7 @@ public final class Skins { ...@@ -90,7 +93,7 @@ public final class Skins {
final ServletContext servletContext = SoloServletListener.getServletContext(); final ServletContext servletContext = SoloServletListener.getServletContext();
final InputStream inputStream = servletContext.getResourceAsStream( final InputStream inputStream = servletContext.getResourceAsStream(
"/skins/" + currentSkinDirName + "/lang/lang_" + language + '_' + country + ".properties"); "/skins/" + currentSkinDirName + "/lang/lang_" + language + '_' + country + ".properties");
final Properties props = new Properties(); final Properties props = new Properties();
...@@ -103,7 +106,7 @@ public final class Skins { ...@@ -103,7 +106,7 @@ public final class Skins {
LANG_MAP.put(langName, langs); LANG_MAP.put(langName, langs);
LOGGER.log(Level.DEBUG, "Loaded skin[dirName={0}, locale={1}, keyCount={2}]", LOGGER.log(Level.DEBUG, "Loaded skin[dirName={0}, locale={1}, keyCount={2}]",
new Object[] {currentSkinDirName, localeString, langs.size()}); new Object[]{currentSkinDirName, localeString, langs.size()});
} }
dataModel.putAll(langs); // Fills the current skin's language configurations dataModel.putAll(langs); // Fills the current skin's language configurations
...@@ -122,8 +125,8 @@ public final class Skins { ...@@ -122,8 +125,8 @@ public final class Skins {
} }
/** /**
* Sets the directory for template loading with the specified skin directory * Sets the directory for template loading with the specified skin directory name, and sets the directory for mobile
* name, and sets the directory for mobile request template loading. * request template loading.
* *
* @param skinDirName the specified skin directory name * @param skinDirName the specified skin directory name
*/ */
...@@ -135,8 +138,8 @@ public final class Skins { ...@@ -135,8 +138,8 @@ public final class Skins {
} }
/** /**
* Gets all skin directory names. Scans the /skins/ directory, * Gets all skin directory names. Scans the /skins/ directory, using the subdirectory of it as the skin directory
* using the subdirectory of it as the skin directory name, for example, * name, for example,
* <pre> * <pre>
* ${Web root}/skins/ * ${Web root}/skins/
* <b>default</b>/ * <b>default</b>/
...@@ -156,7 +159,7 @@ public final class Skins { ...@@ -156,7 +159,7 @@ public final class Skins {
for (final String path : resourcePaths) { for (final String path : resourcePaths) {
final String dirName = path.substring("/skins".length() + 1, path.length() - 1); final String dirName = path.substring("/skins".length() + 1, path.length() - 1);
if (dirName.startsWith(".")) { if (dirName.startsWith(".")) {
continue; continue;
} }
...@@ -167,4 +170,47 @@ public final class Skins { ...@@ -167,4 +170,47 @@ public final class Skins {
return ret; return ret;
} }
/**
* Gets skin directory name from the specified request.
*
* @param request the specified request
* @return directory name, or {@code "default"} if not found
*/
public static String getSkinDirName(final HttpServletRequest request) {
// https://github.com/b3log/solo/issues/12060
// 1. Get skin from query
final String specifiedSkin = request.getParameter(Skin.SKIN);
if ("default".equals(specifiedSkin)) {
return "default";
}
if (!Strings.isEmptyOrNull(specifiedSkin)) {
final Set<String> skinDirNames = Skins.getSkinDirNames();
if (skinDirNames.contains(specifiedSkin)) {
return specifiedSkin;
} else {
return null;
}
}
// 2. Get skin from cookie
final Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (final Cookie cookie : cookies) {
if (Skin.SKIN.equals(cookie.getName())) {
final String skin = cookie.getValue();
final Set<String> skinDirNames = Skins.getSkinDirNames();
if (skinDirNames.contains(skin)) {
return skin;
}
}
}
}
return "default";
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment