/*
* Copyright (C) 2011 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.portal.url;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.exoplatform.commons.utils.I18N;
import org.exoplatform.portal.application.PortalRequestHandler;
import org.exoplatform.portal.mop.SiteKey;
import org.exoplatform.web.ControllerContext;
import org.exoplatform.web.WebAppController;
import org.exoplatform.web.controller.QualifiedName;
import org.exoplatform.web.controller.router.URIWriter;
import org.exoplatform.web.url.PortalURL;
import org.exoplatform.web.url.URLContext;
import org.exoplatform.webui.CSRFTokenUtil;
import org.gatein.common.io.UndeclaredIOException;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
*/
public class PortalURLContext implements URLContext {
private static final char REPLACEMENT_CHAR = '\ufffd';
/** . */
private final ControllerContext controllerContext;
/** . */
private final SiteKey siteKey;
/** . */
private URIWriter writer;
/** . */
private StringBuilder buffer;
public PortalURLContext(ControllerContext controllerContext, SiteKey siteKey) {
if (controllerContext == null) {
throw new NullPointerException("No null controller context");
}
//
this.controllerContext = controllerContext;
this.siteKey = siteKey;
this.writer = null;
this.buffer = null;
}
public <R, U extends PortalURL<R, U>> String render(U url) {
try {
return _render(url);
} catch (IOException e) {
throw new UndeclaredIOException(e);
}
}
private <R, U extends PortalURL<R, U>> String _render(U url) throws IOException {
if (url.getResource() == null) {
throw new IllegalStateException("No resource set on portal URL");
}
//
if (writer == null) {
writer = new URIWriter(buffer = new StringBuilder());
} else {
buffer.setLength(0);
writer.reset(buffer);
}
//
HttpServletRequest req = controllerContext.getRequest();
if (url.getSchemeUse()) {
buffer.append(req.getScheme());
buffer.append("://");
}
if (url.getAuthorityUse()) {
buffer.append(req.getServerName());
int port = req.getServerPort();
if (port != 80) {
buffer.append(':').append(port);
}
}
//
writer.setMimeType(url.getMimeType());
//
String confirm = url.getConfirm();
boolean hasConfirm = confirm != null && confirm.length() > 0;
//
boolean ajax = url.getAjax() != null && url.getAjax();
if (ajax) {
writer.append("javascript:");
if (hasConfirm) {
writer.append("if(confirm('");
writer.append(confirm.replaceAll("'", "\\\\'"));
writer.append("'))");
}
writer.append("ajaxGet('");
} else {
if (hasConfirm) {
writer.append("javascript:");
writer.append("if(confirm('");
writer.append(confirm.replaceAll("'", "\\\\'"));
writer.append("'))");
writer.append("window.location=\'");
}
}
//
Map<QualifiedName, String> parameters = new HashMap<QualifiedName, String>();
parameters.put(WebAppController.HANDLER_PARAM, "portal");
parameters.put(PortalRequestHandler.REQUEST_SITE_TYPE, siteKey.getTypeName());
parameters.put(PortalRequestHandler.REQUEST_SITE_NAME, siteKey.getName());
//
String lang = "";
Locale locale = url.getLocale();
if (locale != null && locale.getLanguage().length() > 0) {
lang = I18N.toTagIdentifier(locale);
}
parameters.put(PortalRequestHandler.LANG, lang);
//
for (QualifiedName parameterName : url.getParameterNames()) {
String parameterValue = url.getParameterValue(parameterName);
if (parameterValue != null) {
parameters.put(parameterName, parameterValue);
}
}
int untrustedStart = buffer.length();
// Render url via controller
controllerContext.renderURL(parameters, writer);
checkUntrustedData(untrustedStart);
// Now append generic query parameters
Map<String, String[]> queryParameters = url.getQueryParameters();
if (queryParameters != null) {
for (Map.Entry<String, String[]> entry : queryParameters.entrySet()) {
for (String value : entry.getValue()) {
writer.appendQueryParameter(entry.getKey(), value);
}
}
}
// CSRF token
if (url.isCSRFCheck()) {
String token;
try {
token = CSRFTokenUtil.getToken();
writer.appendQueryParameter(CSRFTokenUtil.CSRF_TOKEN, token);
} catch (Exception e) {
throw new IllegalStateException("Can't add csrf token to url", e);
}
}
//
if (ajax) {
writer.appendQueryParameter("ajaxRequest", "true");
writer.append("')");
} else {
if (hasConfirm) {
writer.append("\'");
}
}
//
return buffer.toString();
}
private void checkUntrustedData(int start) {
int len = buffer.length();
for (int i = start; i < len; i++) {
if (buffer.charAt(i) == '\'') {
buffer.setCharAt(i, REPLACEMENT_CHAR);
}
}
}
}