Author: sletellier Date: 2011-05-25 15:54:55 +0200 (Wed, 25 May 2011) New Revision: 50 Url: http://chorem.org/repositories/revision/vradi/50 Log: - Add table css - Add image for render sort - Fix pagination - Add escape scipt balise decorator -> add unit test - Fix i18n Added: trunk/vradi-web/src/main/java/org/chorem/vradi/VradiWebHelper.java trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/ trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/DateFormatColumnDecorator.java trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/EscapeScriptColomnDecorator.java trunk/vradi-web/src/main/resources/displaytag.properties trunk/vradi-web/src/main/webapp/css/ trunk/vradi-web/src/main/webapp/css/search.css trunk/vradi-web/src/main/webapp/img/ trunk/vradi-web/src/main/webapp/img/arrow_down.png trunk/vradi-web/src/main/webapp/img/arrow_off.png trunk/vradi-web/src/main/webapp/img/arrow_up.png trunk/vradi-web/src/test/java/org/ trunk/vradi-web/src/test/java/org/chorem/ trunk/vradi-web/src/test/java/org/chorem/vradi/ trunk/vradi-web/src/test/java/org/chorem/vradi/VradiWebHelperTest.java Modified: trunk/vradi-web/src/main/i18n/jsp.rules trunk/vradi-web/src/main/java/org/chorem/vradi/FormPaginatedList.java trunk/vradi-web/src/main/java/org/chorem/vradi/actions/FormNoteAction.java trunk/vradi-web/src/main/java/org/chorem/vradi/actions/SearchAction.java trunk/vradi-web/src/main/resources/i18n/vradi-web_en_GB.properties trunk/vradi-web/src/main/resources/i18n/vradi-web_fr_FR.properties trunk/vradi-web/src/main/webapp/WEB-INF/jsp/search.jsp Modified: trunk/vradi-web/src/main/i18n/jsp.rules =================================================================== --- trunk/vradi-web/src/main/i18n/jsp.rules 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/i18n/jsp.rules 2011-05-25 13:54:55 UTC (rev 50) @@ -11,3 +11,6 @@ //s:select/@key //sx:datetimepicker/@key + +//displaytag:column/@title +//displaytag:column/@titleKey Modified: trunk/vradi-web/src/main/java/org/chorem/vradi/FormPaginatedList.java =================================================================== --- trunk/vradi-web/src/main/java/org/chorem/vradi/FormPaginatedList.java 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/java/org/chorem/vradi/FormPaginatedList.java 2011-05-25 13:54:55 UTC (rev 50) @@ -1,11 +1,15 @@ package org.chorem.vradi; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.chorem.vradi.beans.FormPagedResult; import org.chorem.vradi.entities.Form; +import org.chorem.vradi.entities.Infogene; import org.displaytag.pagination.PaginatedList; import org.displaytag.properties.SortOrderEnum; import org.nuiton.wikitty.WikittyProxy; +import javax.servlet.http.HttpServletRequest; import java.util.List; /** @@ -13,14 +17,35 @@ */ public class FormPaginatedList implements PaginatedList { + protected static final Log log = LogFactory.getLog(FormPaginatedList.class); + + public static final int NB_FORMS_TO_SHOW = 100; + public static final String DISPLAY_URL_PAGE = "page"; + public static final String DISPLAY_URL_SORT = "sort"; + public static final String DISPLAY_URL_DIR = "dir"; + protected FormPagedResult result; protected WikittyProxy proxy; - public FormPaginatedList(WikittyProxy proxy, FormPagedResult result) { - this.result = result; + public FormPaginatedList(WikittyProxy proxy) { this.proxy = proxy; + result = new FormPagedResult(); + result.setNbFormsToShow(NB_FORMS_TO_SHOW); + result.setPageToShow(1); + + // Sort by default by fate descending + result.setAscending(false); + result.setFieldToSort(Infogene.FIELD_INFOGENE_CREATIONDATE); } + public FormPagedResult getResult() { + return result; + } + + public void setResult(FormPagedResult result) { + this.result = result; + } + @Override public List<Form> getList() { List<String> formsIdsToShow = result.getFormsIdsToShow(); @@ -45,16 +70,64 @@ @Override public String getSortCriterion() { - return null; + return result.getFieldToSort(); } @Override public SortOrderEnum getSortDirection() { - return null; + if (result.isAscending()) { + return SortOrderEnum.ASCENDING; + } else { + return SortOrderEnum.DESCENDING; + } } @Override public String getSearchId() { + + // Not used return null; } + + /** + * Recupere les parametres depuis une requete de servlet. + * + * @param request la requete utilisee pour recuperee les valeur du POJO + * @return l'instance + */ + public FormPaginatedList fromRequest(HttpServletRequest request) { + + // Number of forms by pages + String page = request.getParameter(DISPLAY_URL_PAGE); + if (page != null && !page.trim().isEmpty()) { + Integer pageNumber = Integer.valueOf(page); + if (log.isDebugEnabled()) { + log.debug("change pageNumber : " + pageNumber); + } + result.setPageToShow(pageNumber); + } + + // Search field criteria + String criterion = request.getParameter(DISPLAY_URL_SORT); + if (criterion != null && !criterion.trim().isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("change sortCriterion : " + criterion); + } + result.setFieldToSort(criterion); + } + + // attention, on supose ici qu'on a defini les variables suivantes dans displaytag.properties : + // pagination.sort.asc.value=ascending + // pagination.sort.desc.value=descending + String direction = request.getParameter(DISPLAY_URL_DIR); + if (direction != null && !direction.trim().isEmpty()) { + SortOrderEnum orderEnum = SortOrderEnum.fromName(direction); + if (log.isDebugEnabled()) { + log.debug("change sortDirection : " + orderEnum); + } + boolean ascending = orderEnum.equals(SortOrderEnum.ASCENDING); + result.setAscending(ascending); + } + return this; + } } Added: trunk/vradi-web/src/main/java/org/chorem/vradi/VradiWebHelper.java =================================================================== --- trunk/vradi-web/src/main/java/org/chorem/vradi/VradiWebHelper.java (rev 0) +++ trunk/vradi-web/src/main/java/org/chorem/vradi/VradiWebHelper.java 2011-05-25 13:54:55 UTC (rev 50) @@ -0,0 +1,15 @@ +package org.chorem.vradi; + +/** + * Utilities class + * + * @author sletellier + */ +public class VradiWebHelper { + + public static String escapeSciptBalises(String txt) { + + // (?s) activ dotall (http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#DO...) + return txt.replaceAll("(?s)<script>.*</script>", ""); + } +} Modified: trunk/vradi-web/src/main/java/org/chorem/vradi/actions/FormNoteAction.java =================================================================== --- trunk/vradi-web/src/main/java/org/chorem/vradi/actions/FormNoteAction.java 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/java/org/chorem/vradi/actions/FormNoteAction.java 2011-05-25 13:54:55 UTC (rev 50) @@ -111,8 +111,8 @@ } partners = proxy.restore(VradiUser.class, formNote.getPartners()); - - // TODO evolution JRST: permettre l'entre String/StringBuffer/Reader, et la sortie String/StringBuffer/Writer pour generate + + // Render JRST in HTML try { summary = JRST.generate(JRST.TYPE_HTML, formNote.getSummary()); } catch(Exception eee) { Modified: trunk/vradi-web/src/main/java/org/chorem/vradi/actions/SearchAction.java =================================================================== --- trunk/vradi-web/src/main/java/org/chorem/vradi/actions/SearchAction.java 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/java/org/chorem/vradi/actions/SearchAction.java 2011-05-25 13:54:55 UTC (rev 50) @@ -17,11 +17,9 @@ public class SearchAction extends VradiBaseAction implements ServletRequestAware { private static final long serialVersionUID = -3735250067223062719L; + public static final String REQUEST_ATTRIBUTE_FORMS = "forms"; - public static final int NB_FORMS_TO_SHOW = 100; - protected String query; - protected FormPagedResult result; protected HttpServletRequest request; public String getQuery() { @@ -42,23 +40,23 @@ */ public String execute() { - if (result == null) { - result = new FormPagedResult(); - result.setNbFormsToShow(NB_FORMS_TO_SHOW); - } + FormPaginatedList paginatedList = new FormPaginatedList(getProxy()); + paginatedList.fromRequest(request); + QueryParameters queryParameters = new QueryParameters(query); try { - result = getDataService().findForms(queryParameters, result); - log.info(result.getTotalFoundFormNb() + " forms found"); + FormPagedResult result = paginatedList.getResult(); + FormPagedResult forms = getDataService().findForms(queryParameters, result); + paginatedList.setResult(forms); } catch (VradiException eee) { log.error("Failed to execute query", eee); } catch (UnsupportedQueryException eee) { log.error("Unsuported query", eee); } - request.setAttribute("forms", new FormPaginatedList(getProxy(), result)); + request.setAttribute(REQUEST_ATTRIBUTE_FORMS, paginatedList); return SUCCESS; } Added: trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/DateFormatColumnDecorator.java =================================================================== --- trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/DateFormatColumnDecorator.java (rev 0) +++ trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/DateFormatColumnDecorator.java 2011-05-25 13:54:55 UTC (rev 50) @@ -0,0 +1,27 @@ +package org.chorem.vradi.decorators; + +import org.displaytag.decorator.DisplaytagColumnDecorator; +import org.displaytag.exception.DecoratorException; +import org.displaytag.properties.MediaTypeEnum; +import org.nuiton.util.DateUtil; + +import javax.servlet.jsp.PageContext; +import java.util.Date; + +/** + * Decorator used to display tooltip on form lines + * + * @author sletellier + */ +public class DateFormatColumnDecorator implements DisplaytagColumnDecorator { + + @Override + public Object decorate(Object columnValue, PageContext pageContext, MediaTypeEnum media) throws DecoratorException { + + if (columnValue == null) { + return null; + } + String txt = DateUtil.formatDate((Date)columnValue, "dd-MM-yyyy"); + return txt; + } +} Added: trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/EscapeScriptColomnDecorator.java =================================================================== --- trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/EscapeScriptColomnDecorator.java (rev 0) +++ trunk/vradi-web/src/main/java/org/chorem/vradi/decorators/EscapeScriptColomnDecorator.java 2011-05-25 13:54:55 UTC (rev 50) @@ -0,0 +1,28 @@ +package org.chorem.vradi.decorators; + +import org.chorem.vradi.VradiWebHelper; +import org.displaytag.decorator.DisplaytagColumnDecorator; +import org.displaytag.exception.DecoratorException; +import org.displaytag.properties.MediaTypeEnum; + +import javax.servlet.jsp.PageContext; + +/** + * This decorator is used to remove all scipts balises found in content of columns (to prevent attacks) + * + * @author sletellier + */ +public class EscapeScriptColomnDecorator implements DisplaytagColumnDecorator { + + @Override + public Object decorate(Object columnValue, PageContext pageContext, MediaTypeEnum media) throws DecoratorException { + + if (columnValue == null) { + return null; + } + String txt = columnValue.toString(); + txt = VradiWebHelper.escapeSciptBalises(txt); + + return txt; + } +} Added: trunk/vradi-web/src/main/resources/displaytag.properties =================================================================== --- trunk/vradi-web/src/main/resources/displaytag.properties (rev 0) +++ trunk/vradi-web/src/main/resources/displaytag.properties 2011-05-25 13:54:55 UTC (rev 50) @@ -0,0 +1,20 @@ +basic.empty.showtable=true +basic.msg.empty_list=Vide +basic.msg.empty_list_row=<tr class="empty"><td colspan="{0}">Vide</td></tr></tr> + +sort.amount=list + +paging.banner.placement=bottom +paging.banner.item_name=\u00e9l\u00e9ment +paging.banner.items_name=\u00e9l\u00e9ments +paging.banner.no_items_found=<span class="pagebanner">Aucun {0} trouv\u00e9.</span> +paging.banner.one_item_found=<span class="pagebanner">Un seul {0} trouv\u00e9.</span> +paging.banner.all_items_found=<span class="pagebanner">{0} {1} trouv\u00e9s, tout afficher {2}.</span> +paging.banner.some_items_found=<span class="pagebanner">{0} {1} trouv\u00e9s, affich\u00e9 de {2} \u00e0 {3}.</span> +paging.banner.full=<span class="pagelinks">[<a href="{1}">Premier</a>/<a href="{2}">Pr\u00e9c\u00e9dent</a>]{0} [<a href="{3}">Suivant</a>/<a href="{4}">Dernier</a>]</span> +paging.banner.first=<span class="pagelinks">[Permier/Pr\u00e9c\u00e9dent] {0} [<a href="{3}">Suivant</a>/<a href="{4}">Dernier</a>]</span> +paging.banner.last=<span class="pagelinks">[<a href="{1}">Premier</a>/<a href="{2}">Pr\u00e9c\u00e9dent</a>]{0} [Suivant/Dernier]</span> +paging.banner.page.link=<a href="{1}" title="Aller \u00e0 {0}">{0}</a> + +pagination.sort.asc.value=ascending +pagination.sort.desc.value=descending Modified: trunk/vradi-web/src/main/resources/i18n/vradi-web_en_GB.properties =================================================================== --- trunk/vradi-web/src/main/resources/i18n/vradi-web_en_GB.properties 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/resources/i18n/vradi-web_en_GB.properties 2011-05-25 13:54:55 UTC (rev 50) @@ -24,3 +24,5 @@ vradi.register.title=Login vradi.search.submit=Search vradi.search.title=Search +vradi.form.object=Object +vradi.form.creationDate=Creation date Modified: trunk/vradi-web/src/main/resources/i18n/vradi-web_fr_FR.properties =================================================================== --- trunk/vradi-web/src/main/resources/i18n/vradi-web_fr_FR.properties 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/resources/i18n/vradi-web_fr_FR.properties 2011-05-25 13:54:55 UTC (rev 50) @@ -1,4 +1,4 @@ -vradi.authentification.error= +vradi.authentification.error=Erreur lors de l'authentification vradi.config.configFileName.description=Fichier de configuration de Vradi web vradi.config.database.version.description=Version de la base de donnée vradi.config.last.version.description=Dernière version de Vradi web lancée @@ -9,6 +9,8 @@ vradi.forgotPassword.emailDoesntExist=Cette adresse email n'existe pas vradi.forgotpwd.submit=Envoyer vradi.forgotpwd.title=Vous avez oublié votre mot de passe ? +vradi.form.creationDate=Date de création +vradi.form.object=Objet vradi.login.email=Email vradi.login.password=Mot de passe vradi.login.repeatPassword=Confiramtion Modified: trunk/vradi-web/src/main/webapp/WEB-INF/jsp/search.jsp =================================================================== --- trunk/vradi-web/src/main/webapp/WEB-INF/jsp/search.jsp 2011-05-25 13:51:42 UTC (rev 49) +++ trunk/vradi-web/src/main/webapp/WEB-INF/jsp/search.jsp 2011-05-25 13:54:55 UTC (rev 50) @@ -1,21 +1,38 @@ -<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> +<%@page import="org.chorem.vradi.entities.Infogene"%> +<%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags"%> <%@taglib prefix="displaytag" uri="http://displaytag.sf.net"%> +<script type="text/javascript" src="/js/jquery-1.6.1.min.js"></script> + <html xmlns:s="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" xmlns:jsp="http://java.sun.com/JSP/Page"> <head> + <s:url var="css" value="/css/search.css" /> + <link href="${css}" rel="stylesheet" type="text/css" /> <title><s:text name="vradi.search.title" /></title> <s:head /> </head> <body> <s:form id="searchForm" action="search" method="post"> <s:textarea id="searchArea" name="query"/> - <s:submit key="vradi.search.submit" name="submit" /> + <s:submit key="vradi.search.submit" name="submit"/> </s:form> - <displaytag:table name="forms" id="f" requestURI="search.action"> - <displaytag:column titleKey="vradi.form.title" property="creationDate"/> - <displaytag:column titleKey="vradi.form.title" property="objet"/> - <displaytag:column titleKey="vradi.form.title" property="sourceURL"/> + <displaytag:table name="forms" + sort="list" + id="f" + requestURI="search.action"> + + <displaytag:column titleKey="vradi.form.creationDate" + property="<%=Infogene.FIELD_INFOGENE_CREATIONDATE%>" + sortable="true" + sortProperty="<%=Infogene.FQ_FIELD_INFOGENE_CREATIONDATE%>" + decorator="org.chorem.vradi.decorators.DateFormatColumnDecorator"/> + + <displaytag:column titleKey="vradi.form.object" + property="<%=Infogene.FIELD_INFOGENE_OBJET%>" + sortable="true" + sortProperty="<%=Infogene.FQ_FIELD_INFOGENE_OBJET%>" + decorator="org.chorem.vradi.decorators.EscapeScriptColomnDecorator"/> </displaytag:table> </body> </html> \ No newline at end of file Added: trunk/vradi-web/src/main/webapp/css/search.css =================================================================== --- trunk/vradi-web/src/main/webapp/css/search.css (rev 0) +++ trunk/vradi-web/src/main/webapp/css/search.css 2011-05-25 13:54:55 UTC (rev 50) @@ -0,0 +1,42 @@ + +/* Tableau */ +table {border-collapse:collapse; width: 100%;} +.subTable th {font-weight: normal;} + +td { + border: 1px solid black; + padding:5px;} +td.action {text-align: right; white-space:nowrap;} +th { + background-color: #eee; + border: 1px solid black; + padding: 4px; +} + +th a:hover {color: black;} +th a,th a:visited { + text-decoration: none; + font-weight:bold; + color: black; + background-repeat: no-repeat; +} + +/* Tri sur une table */ +th.sorted a,th.sortable a {background-position: right; display: block;} +th.sortable a {background-image: url(../img/arrow_off.png);} +th.order1 a {background-image: url(../img/arrow_down.png);} +th.order2 a {background-image: url(../img/arrow_up.png);} +tr.odd:hover, tr.even:hover { background-color:#deecf1; cursor: pointer;} + +/* Pagination sur une table */ +span.pagebanner, span.pagelinks { + background-color: #eee; + border: 1px solid black; + padding: 2px; + display: block; + text-align: center; +} + +span.pagebanner{margin-top: 10px; border-bottom: none;} +span.pagelinks {border-top: none; margin-bottom: 10px;} +span.pagelinks a, span.pagelinks a:visited{color:black;} Added: trunk/vradi-web/src/main/webapp/img/arrow_down.png =================================================================== (Binary files differ) Property changes on: trunk/vradi-web/src/main/webapp/img/arrow_down.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/vradi-web/src/main/webapp/img/arrow_off.png =================================================================== (Binary files differ) Property changes on: trunk/vradi-web/src/main/webapp/img/arrow_off.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/vradi-web/src/main/webapp/img/arrow_up.png =================================================================== (Binary files differ) Property changes on: trunk/vradi-web/src/main/webapp/img/arrow_up.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/vradi-web/src/test/java/org/chorem/vradi/VradiWebHelperTest.java =================================================================== --- trunk/vradi-web/src/test/java/org/chorem/vradi/VradiWebHelperTest.java (rev 0) +++ trunk/vradi-web/src/test/java/org/chorem/vradi/VradiWebHelperTest.java 2011-05-25 13:54:55 UTC (rev 50) @@ -0,0 +1,72 @@ +package org.chorem.vradi; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author sletellier + */ +public class VradiWebHelperTest { + + @Test + public void testEscapeSciptBalises() { + String content = "aaa <p> ppp <br> <script>toRemove</script> </p>"; + + String result = VradiWebHelper.escapeSciptBalises(content); + Assert.assertNotSame(content, result); + Assert.assertFalse(result.contains("toRemove")); + } + + @Test + public void testEscapeSciptBalisesMultiLine() { + String content = "\n" + + "<script>\n" + + " function openPublicAliasForm(bookmarkId) {\n" + + " $(\"#publicAliasFormBookmarkId\")[0].value = bookmarkId;\n" + + " $(\"#setPublicAliasPopup\").dialog(\"open\");\n" + + " return false;\n" + + " }\n" + + " \n" + + " $(function() {\n" + + " $( \"#setPublicAliasPopup\" ).dialog({\n" + + " autoOpen: false,\n" + + " width: 300,\n" + + " modal: true,\n" + + "// buttons: {\n" + + "// \"Validate\": function() {\n" + + "// $(\"#setPublicAliasForm\").submit();\n" + + "// $( this ).dialog( \"close\" );\n" + + "// },\n" + + "// Cancel: function() {\n" + + "// $( this ).dialog( \"close\" );\n" + + "// }\n" + + "// },\n" + + " close: function() {\n" + + " //allFields.val( \"\" ).removeClass( \"ui-state-error\" );\n" + + " }\n" + + " });\n" + + " });\n" + + " function submitPublicAlias() {\n" + + " $(\"#setPublicAliasForm\").submit();\n" + + " closePopupAddUrl();\n" + + " }\n" + + "\n" + + " function closePopupPublicAlias() {\n" + + " $( \"#setPublicAliasPopup\" ).dialog( \"close\" )\n" + + " }\n" + + "</script>\n" + + "\n" + + "<div xmlns:s=\"http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd\"\n" + + " id=\"setPublicAliasPopup\" title=\"Entrer un alias public\">\n" + + " <form id=\"setPublicAliasForm\" name=\"setPublicAliasForm\" action=\"createAlias\" method=\"post\">\n" + + "<table class=\"wwFormTable\"><tr>\n" + + " <td class=\"tdLabel\"><label for=\"setPublicAliasForm_alias\" class=\"label\">ALIAS:</label></td>\n" + + " <td\n" + + "><input type=\"text\" name=\"alias\" value=\"\" id=\"setPublicAliasForm_alias\" class=\"class java.util.HashMap\"/></td>\n" + + "</tr>\n" + + "<input type=\"hidden\" name=\"bookmarkId\" value=\"\" id=\"publicAliasFormBookmarkId\"/></table></form>"; + String result = VradiWebHelper.escapeSciptBalises(content); + Assert.assertNotSame(content, result); + Assert.assertFalse(result.contains("<script>")); + } +}