Seam SVN: r8569 - in branches/Seam_2_0_FP/src/main/org/jboss/seam: navigation and 1 other directory.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:43:22 -0400 (Mon, 04 Aug 2008)
New Revision: 8569
Modified:
branches/Seam_2_0_FP/src/main/org/jboss/seam/core/ConversationPropagation.java
branches/Seam_2_0_FP/src/main/org/jboss/seam/navigation/ELConversationIdParameter.java
Log:
Backport of JBSEAM-3053
Modified: branches/Seam_2_0_FP/src/main/org/jboss/seam/core/ConversationPropagation.java
===================================================================
--- branches/Seam_2_0_FP/src/main/org/jboss/…
[View More]seam/core/ConversationPropagation.java 2008-08-04 14:40:13 UTC (rev 8568)
+++ branches/Seam_2_0_FP/src/main/org/jboss/seam/core/ConversationPropagation.java 2008-08-04 14:43:22 UTC (rev 8569)
@@ -117,11 +117,9 @@
}
// Try to restore the conversation from parameters (the user has specified the exact conversation to restore using f:param)
conversationId = currentConversationIdParameter.getRequestConversationId(parameters);
- if (conversationId == null)
- {
- // Try to restore the conversation from the EL expression on the conversation definition
- conversationId = currentConversationIdParameter.getConversationId();
- }
+
+ // NOTE: If conversationId is still null, don't try to resolve the EL here because we don't yet
+ // have a conversation and therefore things may blow up; resolve EL in getInitialConversationId()
}
else
{
Modified: branches/Seam_2_0_FP/src/main/org/jboss/seam/navigation/ELConversationIdParameter.java
===================================================================
--- branches/Seam_2_0_FP/src/main/org/jboss/seam/navigation/ELConversationIdParameter.java 2008-08-04 14:40:13 UTC (rev 8568)
+++ branches/Seam_2_0_FP/src/main/org/jboss/seam/navigation/ELConversationIdParameter.java 2008-08-04 14:43:22 UTC (rev 8569)
@@ -42,7 +42,7 @@
public String getInitialConversationId(Map parameters)
{
String id = getRequestConversationId(parameters);
- return id==null ? Id.nextId() : id; //TODO: should we try using the expression?
+ return id == null ? getConversationId() : id;
}
public String getRequestConversationId(Map parameters)
[View Less]
16 years, 7 months
Seam SVN: r8568 - branches/Seam_2_0_FP/src/main/org/jboss/seam/security.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:40:13 -0400 (Mon, 04 Aug 2008)
New Revision: 8568
Modified:
branches/Seam_2_0_FP/src/main/org/jboss/seam/security/RuleBasedIdentity.java
Log:
Backport of JBSEAM-3064
Modified: branches/Seam_2_0_FP/src/main/org/jboss/seam/security/RuleBasedIdentity.java
===================================================================
--- branches/Seam_2_0_FP/src/main/org/jboss/seam/security/RuleBasedIdentity.java 2008-08-04 14:32:50 UTC (rev 8567)
+++ branches/…
[View More]Seam_2_0_FP/src/main/org/jboss/seam/security/RuleBasedIdentity.java 2008-08-04 14:40:13 UTC (rev 8568)
@@ -117,15 +117,14 @@
StatefulSession securityContext = getSecurityContext();
if (securityContext == null) return false;
-
- synchronizeContext();
-
+
List<FactHandle> handles = new ArrayList<FactHandle>();
-
PermissionCheck check = new PermissionCheck(name, action);
synchronized( securityContext )
{
+ synchronizeContext();
+
handles.add( securityContext.insert(check) );
for (int i = 0; i < arg.length; i++)
@@ -165,12 +164,15 @@
{
if (securityContext != null)
{
- Iterator<Role> iter = securityContext.iterateObjects(new ClassObjectFilter(Role.class));
-
- while (iter.hasNext())
+ synchronized(securityContext)
{
- Role r = iter.next();
- if (r.getName().equals(role)) return true;
+ Iterator<Role> iter = securityContext.iterateObjects(new ClassObjectFilter(Role.class));
+
+ while (iter.hasNext())
+ {
+ Role r = iter.next();
+ if (r.getName().equals(role)) return true;
+ }
}
}
@@ -222,44 +224,47 @@
{
if (getSecurityContext() != null)
{
- for ( Group sg : getSubject().getPrincipals(Group.class) )
- {
- if ( ROLES_GROUP.equals( sg.getName() ) )
+ synchronized(getSecurityContext())
+ {
+ for ( Group sg : getSubject().getPrincipals(Group.class) )
{
- Enumeration e = sg.members();
- while (e.hasMoreElements())
+ if ( ROLES_GROUP.equals( sg.getName() ) )
{
- Principal role = (Principal) e.nextElement();
-
- boolean found = false;
- Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class));
- while (iter.hasNext())
+ Enumeration e = sg.members();
+ while (e.hasMoreElements())
{
- Role r = iter.next();
- if (r.getName().equals(role.getName()))
+ Principal role = (Principal) e.nextElement();
+
+ boolean found = false;
+ Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class));
+ while (iter.hasNext())
{
- found = true;
- break;
+ Role r = iter.next();
+ if (r.getName().equals(role.getName()))
+ {
+ found = true;
+ break;
+ }
}
+
+ if (!found)
+ {
+ getSecurityContext().insert(new Role(role.getName()));
+ }
+
}
-
- if (!found)
- {
- getSecurityContext().insert(new Role(role.getName()));
- }
-
}
- }
- }
-
- Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class));
- while (iter.hasNext())
- {
- Role r = iter.next();
- if (!super.hasRole(r.getName()))
+ }
+
+ Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class));
+ while (iter.hasNext())
{
- FactHandle fh = getSecurityContext().getFactHandle(r);
- getSecurityContext().retract(fh);
+ Role r = iter.next();
+ if (!super.hasRole(r.getName()))
+ {
+ FactHandle fh = getSecurityContext().getFactHandle(r);
+ getSecurityContext().retract(fh);
+ }
}
}
}
[View Less]
16 years, 7 months
Seam SVN: r8567 - branches/Seam_2_0_FP/src/main/org/jboss/seam/contexts.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:32:50 -0400 (Mon, 04 Aug 2008)
New Revision: 8567
Modified:
branches/Seam_2_0_FP/src/main/org/jboss/seam/contexts/ServerConversationContext.java
Log:
Backport of JBSEAM-3078
Modified: branches/Seam_2_0_FP/src/main/org/jboss/seam/contexts/ServerConversationContext.java
===================================================================
--- branches/Seam_2_0_FP/src/main/org/jboss/seam/contexts/ServerConversationContext.java 2008-08-04 14:28:39 UTC (rev 8566)…
[View More]
+++ branches/Seam_2_0_FP/src/main/org/jboss/seam/contexts/ServerConversationContext.java 2008-08-04 14:32:50 UTC (rev 8567)
@@ -277,8 +277,10 @@
for (String key: getNamesForAllConversationsFromSession()) {
Object attribute = session.get(key);
- if ( attribute!=null && isAttributeDirty(attribute) ) {
- session.put(key, attribute);
+ if (attribute!=null) {
+ if (passivate(attribute) || isAttributeDirty(attribute)) {
+ session.put(key, attribute);
+ }
}
}
//remove removed objects
@@ -288,7 +290,8 @@
removals.clear();
//add new objects
for (Map.Entry<String, Object> entry: additions.entrySet()) {
- session.put( getKey( entry.getKey() ), entry.getValue() );
+ Object attribute = entry.getValue();
+ passivate(attribute);
}
additions.clear();
}
@@ -301,13 +304,24 @@
}
}
}
+
+ private boolean passivate(Object attribute)
+ {
+ if (attribute instanceof Wrapper)
+ {
+ return ((Wrapper) attribute).passivate();
+ }
+ else
+ {
+ return false;
+ }
+ }
private boolean isAttributeDirty(Object attribute)
{
- return Contexts.isAttributeDirty(attribute) ||
- ( attribute instanceof Wrapper && ( (Wrapper) attribute ).passivate() );
+ return Contexts.isAttributeDirty(attribute);
}
-
+
private boolean isCurrent()
{
return id==null || id.equals( Manager.instance().getCurrentConversationId() );
[View Less]
16 years, 7 months
Seam SVN: r8566 - branches/Seam_2_0_FP/src/main/org/jboss/seam.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:28:39 -0400 (Mon, 04 Aug 2008)
New Revision: 8566
Modified:
branches/Seam_2_0_FP/src/main/org/jboss/seam/web-2.0.xsd
Log:
Backport of JBSEAM-3090
Modified: branches/Seam_2_0_FP/src/main/org/jboss/seam/web-2.0.xsd
===================================================================
--- branches/Seam_2_0_FP/src/main/org/jboss/seam/web-2.0.xsd 2008-08-04 14:25:45 UTC (rev 8565)
+++ branches/Seam_2_0_FP/src/main/org/jboss/seam/web-2.0.xsd 2008-08-04 14:28:39 …
[View More]UTC (rev 8566)
@@ -106,13 +106,13 @@
<xs:attribute name="log4j-init-file" type="xs:string"/>
</xs:attributeGroup>
- <xs:element name="servlet-session">
+ <xs:element name="session">
<xs:complexType mixed="true">
<xs:attributeGroup ref="components:attlist.component"/>
- <xs:attributeGroup ref="web:attlist.servlet-session"/>
+ <xs:attributeGroup ref="web:attlist.session"/>
</xs:complexType>
</xs:element>
- <xs:attributeGroup name="attlist.servlet-session">
+ <xs:attributeGroup name="attlist.session">
<xs:attribute name="invalidate-on-scheme-change" type="xs:boolean"/>
</xs:attributeGroup>
[View Less]
16 years, 7 months
Seam SVN: r8565 - branches/Seam_2_0_FP/examples/blog/resources.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:25:45 -0400 (Mon, 04 Aug 2008)
New Revision: 8565
Modified:
branches/Seam_2_0_FP/examples/blog/resources/import.sql
Log:
Backport of JBSEAM-3101
Modified: branches/Seam_2_0_FP/examples/blog/resources/import.sql
===================================================================
--- branches/Seam_2_0_FP/examples/blog/resources/import.sql 2008-08-04 14:18:51 UTC (rev 8564)
+++ branches/Seam_2_0_FP/examples/blog/resources/import.sql 2008-08-04 14:25:45 UTC (…
[View More]rev 8565)
@@ -1,5 +1,5 @@
insert into blog (name, description, locale, timezone, password) values ('JBoss Seam Blog', 'An example of a RESTful Seam application', 'en_AU', 'PST', 'tokyo')
insert into hitcount (blog_name, pageviews) values ('JBoss Seam Blog', 1000)
-insert into blogentry (blog_name, id, title, excerpt, body, date) values ('JBoss Seam Blog', 'seamtext', 'Introducing Seam Text', null, 'Seam Text is a human-friendly language for formatting text in blogs, forums and wikis. It''s easy to enter text in *emphasis*, |monospace|, ~deleted~ or ^superscript^; you can easily enter links, lists, quotes and code blocks.'+char(10)+''+char(10)+'[This is a link.=>http://hibernate.org]'+char(10)+''+char(10)+'You can *not* enter HTML entities, even escaped: \& \< \> \" \ '+char(10)+''+char(10)+'And even emoticons: ;) :-) :-{ ;-)'+char(10)+''+char(10)+'Here is an ordered list:'+char(10)+''+char(10)+'#JBoss'+char(10)+'#Seam'+char(10)+'#Hibernate'+char(10)+''+char(10)+'And this is an unordered list:'+char(10)+''+char(10)+'=jBPM'+char(10)+'=Drools'+char(10)+'=Ajax4JSF'+char(10)+'=Facelets'+char(10)+''+char(10)+'"Here is a quote from someone else"'+char(10)+''+char(10)+'`<p>Here is some code</p>`'+char(10)+''+char(10)+'And!
some plain HTML (restricted subset):'+char(10)+''+char(10)+'<table style="border:1px solid blue;"><tr><td>Foo</td><td>Bar</td></tr></table>', '2007-01-18 4:00')
+insert into blogentry (blog_name, id, title, excerpt, body, date) values ('JBoss Seam Blog', 'seamtext', 'Introducing Seam Text', null, 'Seam Text is a human-friendly language for formatting text in blogs, forums and wikis. It''s easy to enter text in *emphasis*, |monospace|, ~deleted~ or ^superscript^; you can easily enter links, lists, quotes and code blocks.'+char(10)+''+char(10)+'[This is a link.=>http://hibernate.org]'+char(10)+''+char(10)+'You can *not* enter HTML entities, even escaped: \& \< \> \" \ '+char(10)+''+char(10)+'And even emoticons: ;) :-) :-{ ;-)'+char(10)+''+char(10)+'Here is an ordered list:'+char(10)+''+char(10)+'#JBoss'+char(10)+'#Seam'+char(10)+'#Hibernate'+char(10)+''+char(10)+'And this is an unordered list:'+char(10)+''+char(10)+'=jBPM'+char(10)+'=Drools'+char(10)+'=Ajax4JSF'+char(10)+'=Facelets'+char(10)+''+char(10)+'"Here is a quote from someone else"'+char(10)+''+char(10)+'`<p>Here is some code</p>`'+char(10)+''+char(10)+'And!
some plain HTML (restricted subset):'+char(10)+''+char(10)+'<table><tr><td>Foo</td><td>Bar</td></tr></table>', '2007-01-18 4:00')
insert into blogentry (blog_name, id, title, excerpt, body, date) values ('JBoss Seam Blog', 'book', 'Seam book excerpt on InfoQ', null, 'Michael and Thomas are writing [a book=>http://safari.oreilly.com/013241273X] about Seam for [O''Reilly=>http://www.oreillynet.com/], which is apparently the hottest selling item on Rough Cuts. InfoQ are running an [excerpt=>http://www.infoq.com/articles/jboss-seam] from the first chapter.'+char(10)+''+char(10)+'Meanwhile, Norman and I have been tearing our way through JIRA issues, and so 1.1.1 will be ready to go when I get back from vacation :-)', '2006-12-19 19:00')
insert into blogentry (blog_name, id, title, excerpt, body, date) values ('JBoss Seam Blog', 'roadmap11', 'Seam Roadmap', 'The [1.1 release=>http://blog.hibernate.org/cgi-bin/blosxom.cgi/2006/12/13#seam11-goes-ga] involved a lot of hard work in the guts of Seam, refactoring and fixing bugs, and working with \"tricky\" code that handles concerns like clustering and concurrency. Sure, there are many new features, but a lot of the real work is less user-visible. Now that this hard stuff is out of the way, it lets us add some interesting new stuff pretty quickly. Here''s a quick roadmap for the next few months:', 'The [1.1 release=>http://blog.hibernate.org/cgi-bin/blosxom.cgi/2006/12/13#seam11-goes-ga] involved a lot of hard work in the guts of Seam, refactoring and fixing bugs, and working with \"tricky\" code that handles concerns like clustering and concurrency. Sure, there are many new features, but a lot of the real work is less user-visible. Now that this hard stuff is o!
ut of the way, it lets us add some interesting new stuff pretty quickly. Here''s a quick roadmap for the next few months:'+char(10)+''+char(10)+'++++Spring integration package'+char(10)+''+char(10)+'We''re seeing regular requests from people who have existing DAOs and business logic written using the Spring Framework and want a migration path to Seam that lets them re-use this existing code unchanged. The planned Spring integration package will provide:'+char(10)+''+char(10)+'=injection of Spring beans into Seam components, using |@In|'+char(10)+'=access to the Spring beans in the EL'+char(10)+'=injection of Seam components into Spring beans using Spring XML'+char(10)+'=integration of the Spring DAO framework with Seam-managed persistence contexts'+char(10)+''+char(10)+'So, you''ll be able to easily call existing code written in Spring from your Seam component, JSF views, or jBPM process definitions, and have that code be able to take advantage of Seam''s conversation-scope!
persistence contexts. For the first time, you can have Spring code th
at isn''t vulnerable to |LazyInitializationException|!'+char(10)+'We''ll probably even go as far as:'+char(10)+''+char(10)+'=The ability to treat a Spring bean as a Seam |STATELESS JAVA\_BEAN| component, with a full stack of Seam interceptors'+char(10)+''+char(10)+'In which case a class can simultaneously be a Seam component and a Spring bean, the same way a class can simultaneously be a JSF managed beans, an EJB3 session bean, and a Seam component today.'+char(10)+''+char(10)+'++++Seam/Security'+char(10)+''+char(10)+'The most-requested feature in the Seam forums is security. Unfortunately, the security-related specifications did not go through the same process of self-examination and improvement in Java EE 5 that some other specifications (EJB) did, and so there is now a yawning hole, exactly where the platform should strongest. (Today the most inadequate specifications in Java are the portlet spec, the atrocious servlet spec, and any JSR relating to security.) Seam 1.1.5 w!
ill introduce Seam/Security, an extension to Seam that provides:'+char(10)+''+char(10)+'=a usable authentication layer'+char(10)+'=an ACL based permissioning model'+char(10)+'=an optional (customizable) user/role model'+char(10)+'=a totally cool (at least we think so) authorization mechanism based upon EL and Drools'+char(10)+''+char(10)+'The permissioning model lets you do \"row level\" security by writing rules that refer to the actual object instance that we are checking permissions for.'+char(10)+''+char(10)+'A subsequent release will also provide a console for administration of permissions, users/roles and rules. OK, I''m sure that sounds pretty vague now, but stay tuned.'+char(10)+''+char(10)+'++++Seam and iText'+char(10)+'Generating PDF is amazingly unsexy, but also incredibly useful. Seam 1.1.5 will provide a library of JSF controls for iText, letting you quickly create JSF templates that are capable of rendering PDF, Text and RTF. This will be as easy to use as:'+c!
har(10)+''+char(10)+'`<it:document xmlns:f="http://java.sun.com/jsf/co
re"'+char(10)+' xmlns:it="http://jboss.com/products/seam/pdf">'+char(10)+' <it:paragraph>Hello World!</it:paragraph>'+char(10)+'</f:view>`'+char(10)+''+char(10)+'++++Integration of seam-gen with Hibernate Tools'+char(10)+''+char(10)+'Rails has made commandline tools popular for web development, and was the inspiration behind seam-gen. But I''m one of those recalcitrant IDE kinda guys, and I expect tooling to be properly integrated with Eclipse. We''ll be updating the GUI for Hibernate Tools to take advantage of the new templates in Seam 1.1, which will let you do everything you can do today using seam-gen, totally within Eclipse.'+char(10)+''+char(10)+'++++Seam/WS'+char(10)+''+char(10)+'We''ve been promising for months that Seam is the killer component model for SOA. Unfortunately, we got so bogged down in Seam 1.1 that we''re well behind on our original plan to deliver this in 2006.'+char(10)+''+char(10)+'Seam 1.2 will integrate Seam with the Java EE 5 Web Service!
s layer and provide support for service conversations in its context model (I''ve not yet decided whether this calls for a new |SERVICE\_CONVERSATION| context, or whether it is just a different interpretation of the existing |CONVERSATION| context for a WS invocation.) Eventually, Seam/WS will also support service orchestration and conversation recovery via jBPM.'+char(10)+''+char(10)+'Actually, Seam/WS will just be one piece of a larger initiative to bring Seam to ESB and SOA environments, but at present this idea is mostly speculative.'+char(10)+''+char(10)+'Look for a beta release of Seam 1.2 in Q1.', '2006-12-14 15:29')
[View Less]
16 years, 7 months
Seam SVN: r8564 - in branches/Seam_2_0_FP: ui/src/main/java/org/jboss/seam/ui/validator and 1 other directory.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:18:51 -0400 (Mon, 04 Aug 2008)
New Revision: 8564
Added:
branches/Seam_2_0_FP/seam-text.g
Removed:
branches/Seam_2_0_FP/seam-text.g
Modified:
branches/Seam_2_0_FP/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java
Log:
Backport of JBSEAM-3058
Deleted: branches/Seam_2_0_FP/seam-text.g
===================================================================
--- branches/Seam_2_0_FP/seam-text.g 2008-08-04 14:15:41 UTC (rev 8563)
+++ …
[View More]branches/Seam_2_0_FP/seam-text.g 2008-08-04 14:18:51 UTC (rev 8564)
@@ -1,462 +0,0 @@
-header
-{
-package org.jboss.seam.text;
-}
-
-class SeamTextParser extends Parser;
-options
-{
- k=4;
- defaultErrorHandler=false;
-}
-{
- private java.util.Set htmlElements = new java.util.HashSet( java.util.Arrays.asList( new String[] { "a", "p", "q", "blockquote", "code", "pre", "table", "tr", "td", "th", "ul", "ol", "li", "b", "i", "u", "tt", "del", "em", "hr", "br", "div", "span", "h1", "h2", "h3", "h4", "img"} ) );
- private java.util.Set htmlAttributes = new java.util.HashSet( java.util.Arrays.asList( new String[] { "src", "href", "lang", "class", "id", "style", "width", "height", "name", "value", "type", "cellpadding", "cellspacing", "border" } ) );
-
- public class Macro {
- public String name;
- public java.util.SortedMap<String,String> params = new java.util.TreeMap<String,String>();
-
- public Macro(String name) {
- this.name = name;
- }
- }
-
- private Macro currentMacro;
-
- private StringBuilder mainBuilder = new StringBuilder();
- private StringBuilder builder = mainBuilder;
-
- public String toString() {
- return builder.toString();
- }
-
- private void append(String... strings) {
- for (String string: strings) builder.append(string);
- }
-
- private static boolean hasMultiple(String string, char c) {
- return string.indexOf(c)!=string.lastIndexOf(c);
- }
-
- private void validateElement(Token t) throws NoViableAltException {
- if ( !htmlElements.contains( t.getText().toLowerCase() ) ) {
- throw new NoViableAltException(t, null);
- }
- }
-
- private void validateAttribute(Token t) throws NoViableAltException {
- if ( !htmlAttributes.contains( t.getText().toLowerCase() ) ) {
- throw new NoViableAltException(t, null);
- }
- }
-
- private void beginCapture() {
- builder = new StringBuilder();
- }
-
- private String endCapture() {
- String result = builder.toString();
- builder = mainBuilder;
- return result;
- }
-
- protected String linkTag(String description, String url) {
- return "<a href=\"" + url + "\" class=\"seamTextLink\">" + description + "</a>";
- }
-
- protected String macroInclude(String macroName) {
- return "";
- }
-
- protected String macroInclude(Macro m) {
- return macroInclude(m.name);
- }
-
- protected String paragraphOpenTag() {
- return "<p class=\"seamTextPara\">\n";
- }
-
- protected String preformattedOpenTag() {
- return "<pre class=\"seamTextPreformatted\">\n";
- }
-
- protected String blockquoteOpenTag() {
- return "<blockquote class=\"seamTextBlockquote\">\n";
- }
-
- protected String headline1(String line) {
- return "<h1 class=\"seamTextHeadline1\">" + line + "</h1>";
- }
-
- protected String headline2(String line) {
- return "<h2 class=\"seamTextHeadline2\">" + line + "</h2>";
- }
-
- protected String headline3(String line) {
- return "<h3 class=\"seamTextHeadline3\">" + line + "</h3>";
- }
-
- protected String headline4(String line) {
- return "<h4 class=\"seamTextHeadline4\">" + line + "</h4>";
- }
-
- protected String orderedListOpenTag() {
- return "<ol class=\"seamTextOrderedList\">\n";
- }
-
- protected String orderedListItemOpenTag() {
- return "<li class=\"seamTextOrderedListItem\">";
- }
-
- protected String unorderedListOpenTag() {
- return "<ul class=\"seamTextUnorderedList\">\n";
- }
-
- protected String unorderedListItemOpenTag() {
- return "<li class=\"seamTextUnorderedListItem\">";
- }
-
- protected String emphasisOpenTag() {
- return "<i class=\"seamTextEmphasis\">";
- }
-
- protected String emphasisCloseTag() {
- return "</i>";
- }
-}
-
-startRule: (newline)* ( (heading (newline)* )? text (heading (newline)* text)* )?
- ;
-
-text: ( (paragraph|preformatted|blockquote|list|html) (newline)* )+
- ;
-
-paragraph: { append( paragraphOpenTag() ); } (line newlineOrEof)+ { append("</p>\n"); } newlineOrEof
- ;
-
-line: (plain|formatted) (plain|formatted|preformatted|quoted|html)*
- ;
-
-blockquote: DOUBLEQUOTE { append( blockquoteOpenTag() ); }
- (plain|formatted|preformatted|newline|html|list)*
- DOUBLEQUOTE newlineOrEof { append("</blockquote>\n"); }
- ;
-
-preformatted: BACKTICK { append( preformattedOpenTag() ); }
- (word|punctuation|specialChars|moreSpecialChars|htmlSpecialChars|space|newline)*
- BACKTICK { append("</pre>"); }
- ;
-
-plain: word|punctuation|escape|space|link|macro
- ;
-
-formatted: underline|emphasis|monospace|superscript|deleted
- ;
-
-word: an:ALPHANUMERICWORD { append( an.getText() ); } | uc:UNICODEWORD { append( uc.getText() ); }
- ;
-
-punctuation: p:PUNCTUATION { append( p.getText() ); }
- | sq:SINGLEQUOTE { append( sq.getText() ); }
- | s:SLASH { append( s.getText() ); }
- ;
-
-escape: ESCAPE ( specialChars | moreSpecialChars | evenMoreSpecialChars | htmlSpecialChars | b:BACKTICK {append( b.getText() );} )
- ;
-
-specialChars:
- st:STAR { append( st.getText() ); }
- | b:BAR { append( b.getText() ); }
- | h:HAT { append( h.getText() ); }
- | p:PLUS { append( p.getText() ); }
- | eq:EQ { append( eq.getText() ); }
- | hh:HASH { append( hh.getText() ); }
- | e:ESCAPE { append( e.getText() ); }
- | t:TWIDDLE { append( t.getText() ); }
- | u:UNDERSCORE { append( u.getText() ); }
- ;
-
-moreSpecialChars:
- o:OPEN { append( o.getText() ); }
- | c:CLOSE { append( c.getText() ); }
- ;
-
-evenMoreSpecialChars:
- q:QUOTE { append( q.getText() ); }
- ;
-
-htmlSpecialChars:
- GT { append(">"); }
- | LT { append("<"); }
- | DOUBLEQUOTE { append("""); }
- | AMPERSAND { append("&"); }
- ;
-
-link: OPEN
- { beginCapture(); }
- (word|punctuation|escape|space)*
- { String text=endCapture(); }
- EQ GT
- { beginCapture(); }
- attributeValue
- { String link = endCapture(); append(linkTag(text, link)); }
- CLOSE
- ;
-
-/*
-
-[<=macro[param1=value "1"][param2=value '2']]
-
-*/
-macro: OPEN
- LT EQ
- mn:ALPHANUMERICWORD { currentMacro = new Macro(mn.getText()); }
- (macroParam)*
- CLOSE
- { append( macroInclude(currentMacro) ); currentMacro = null; }
- ;
-
-macroParam:
- OPEN
- pn:ALPHANUMERICWORD
- EQ
- { beginCapture(); }
- macroParamValue
- { String pv = endCapture(); currentMacro.params.put(pn.getText(),pv); }
- CLOSE
- ;
-
-macroParamValue:
- ( amp:AMPERSAND { append(amp.getText()); } |
- dq:DOUBLEQUOTE { append(dq.getText()); } |
- sq:SINGLEQUOTE { append(sq.getText()); } |
- an:ALPHANUMERICWORD { append(an.getText()); } |
- p:PUNCTUATION { append(p.getText()); } |
- s:SLASH { append(s.getText()); } |
- lt:LT { append(lt.getText()); } |
- gt:GT { append(gt.getText()); } |
- space | specialChars )*
- ;
-
-emphasis: STAR { append( emphasisOpenTag() ); }
- (plain|underline|monospace|superscript|deleted|newline)+
- STAR { append( emphasisCloseTag() ); }
- ;
-
-underline: UNDERSCORE { append("<u>"); }
- (plain|emphasis|monospace|superscript|deleted|newline)+
- UNDERSCORE { append("</u>"); }
- ;
-
-
-monospace: BAR { append("<tt>"); }
- (word | punctuation | space
- | st:STAR { append( st.getText() ); }
- | h:HAT { append( h.getText() ); }
- | p:PLUS { append( p.getText() ); }
- | eq:EQ { append( eq.getText() ); }
- | hh:HASH { append( hh.getText() ); }
- | e:ESCAPE { append( e.getText() ); }
- | t:TWIDDLE { append( t.getText() ); }
- | u:UNDERSCORE { append( u.getText() ); }
- | moreSpecialChars
- | htmlSpecialChars
- | newline)+
- BAR { append("</tt>"); }
- ;
-
-superscript: HAT { append("<sup>"); }
- (plain|emphasis|underline|monospace|deleted|newline)+
- HAT { append("</sup>"); }
- ;
-
-deleted: TWIDDLE { append("<del>"); }
- (plain|emphasis|underline|monospace|superscript|newline)+
- TWIDDLE { append("</del>"); }
- ;
-
-quoted: DOUBLEQUOTE { append("<q>"); }
- (plain|emphasis|underline|monospace|superscript|deleted|newline)+
- DOUBLEQUOTE { append("</q>"); }
- ;
-
-heading: ( h1 | h2 | h3 | h4 ) newlineOrEof
- ;
-
-h1: PLUS
- { beginCapture(); }
- line
- { String headline=endCapture(); }
- { append(headline1(headline.trim())); }
- ;
-
-h2: PLUS PLUS
- { beginCapture(); }
- line
- { String headline=endCapture(); }
- { append(headline2(headline.trim())); }
- ;
-
-h3: PLUS PLUS PLUS
- { beginCapture(); }
- line
- { String headline=endCapture(); }
- { append(headline3(headline.trim())); }
- ;
-
-h4: PLUS PLUS PLUS PLUS
- { beginCapture(); }
- line
- { String headline=endCapture(); }
- { append(headline4(headline.trim())); }
- ;
-
-list: ( olist | ulist ) newlineOrEof
- ;
-
-olist: { append( orderedListOpenTag() ); } (olistLine newlineOrEof)+ { append("</ol>\n"); }
- ;
-
-olistLine: HASH { append( orderedListItemOpenTag() ); } line { append("</li>"); }
- ;
-
-ulist: { append( unorderedListOpenTag() ); } (ulistLine newlineOrEof)+ { append("</ul>\n"); }
- ;
-
-ulistLine: EQ { append( unorderedListItemOpenTag() ); } line { append("</li>"); }
- ;
-
-space: s:SPACE { append( s.getText() ); }
- ;
-
-newline: n:NEWLINE { append( n.getText() ); }
- ;
-
-newlineOrEof: newline | EOF
- ;
-
-html: openTag ( space | space attribute )* ( ( beforeBody body closeTagWithBody ) | closeTagWithNoBody )
- ;
-
-body: (plain|formatted|preformatted|quoted|html|list|newline)*
- ;
-
-openTag: LT name:ALPHANUMERICWORD { validateElement(name); append("<"); append(name.getText()); }
- ;
-
-beforeBody: GT { append(">"); }
- ;
-
-closeTagWithBody: LT SLASH name:ALPHANUMERICWORD GT { append("</"); append(name.getText()); append(">"); }
- ;
-
-closeTagWithNoBody: SLASH GT { append("/>"); }
- ;
-
-attribute: att:ALPHANUMERICWORD (space)* EQ (space)*
- DOUBLEQUOTE { validateAttribute(att); append(att.getText()); append("=\""); }
- attributeValue
- DOUBLEQUOTE { append("\""); }
- ;
-
-attributeValue: ( AMPERSAND { append("&"); } |
- an:ALPHANUMERICWORD { append( an.getText() ); } |
- p:PUNCTUATION { append( p.getText() ); } |
- s:SLASH { append( s.getText() ); } |
- space | specialChars )*
- ;
-
-class SeamTextLexer extends Lexer;
-options
-{
- k=2;
-
- // Allow any char but \uFFFF (16 bit -1)
- charVocabulary='\u0000'..'\uFFFE';
-}
-
-// Unicode sets allowed:
-// '\u00a0'..'\u00ff' Latin 1 supplement (no control characters) http://www.unicode.org/charts/PDF/U0080.pdf
-// '\u0100'..'\u017f' Latin Extended A http://www.unicode.org/charts/PDF/U0100.pdf
-// '\u0180'..'\u024f' Latin Extended B http://www.unicode.org/charts/PDF/U0180.pdf
-// '\u0250'..'\ufaff' Various other languages, punctuation etc. (excluding "presentation forms")
-// '\uff00'..'\uffef' Halfwidth and Fullwidth forms (including CJK punctuation)
-
-ALPHANUMERICWORD: ('a'..'z'|'A'..'Z'|'0'..'9')+
- ;
-
-UNICODEWORD: (
- '\u00a0'..'\u00ff' |
- '\u0100'..'\u017f' |
- '\u0180'..'\u024f' |
- '\u0250'..'\ufaff' |
- '\uff00'..'\uffef'
- )+
- ;
-
-PUNCTUATION: '-' | ';' | ':' | '(' | ')' | '{' | '}' | '?' | '!' | '@' | '%' | '.' | ',' | '$'
- ;
-
-EQ: '='
- ;
-
-PLUS: '+'
- ;
-
-UNDERSCORE: '_'
- ;
-
-STAR: '*'
- ;
-
-SLASH: '/'
- ;
-
-ESCAPE: '\\'
- ;
-
-BAR: '|'
- ;
-
-BACKTICK: '`'
- ;
-
-TWIDDLE: '~'
- ;
-
-DOUBLEQUOTE: '"'
- ;
-
-SINGLEQUOTE: '\''
- ;
-
-OPEN: '['
- ;
-
-CLOSE: ']'
- ;
-
-HASH: '#'
- ;
-
-HAT: '^'
- ;
-
-GT: '>'
- ;
-
-LT: '<'
- ;
-
-AMPERSAND: '&'
- ;
-
-SPACE: (' '|'\t')+
- ;
-
-NEWLINE: "\r\n" | '\r' | '\n'
- ;
-
-EOF : '\uFFFF'
- ;
Added: branches/Seam_2_0_FP/seam-text.g
===================================================================
--- branches/Seam_2_0_FP/seam-text.g (rev 0)
+++ branches/Seam_2_0_FP/seam-text.g 2008-08-04 14:18:51 UTC (rev 8564)
@@ -0,0 +1,821 @@
+header
+{
+package org.jboss.seam.text;
+}
+
+class SeamTextParser extends Parser;
+options
+{
+ k=4;
+ defaultErrorHandler=false;
+}
+{
+ public class Macro {
+ public String name;
+ public java.util.SortedMap<String,String> params = new java.util.TreeMap<String,String>();
+
+ public Macro(String name) {
+ this.name = name;
+ }
+ }
+
+ /**
+ * Sanitization of user input, used to clean links and plain HTML.
+ */
+ public interface Sanitizer {
+
+ /**
+ * Called by the SeamTextParser when a link tag is parsed, i.e. [=>some URI].
+ *
+ * @param uri the user-entered link text
+ * @throws SemanticException thrown if the URI is not syntactically or semantically valid
+ */
+ public void validateLinkTagURI(String uri) throws SemanticException;
+
+ /**
+ * Called by the SeamTextParser when a plain HTML element is parsed.
+ *
+ * @param element the token of the parse tree, call <tt>getText()</tt> to access the HTML tag name
+ * @throws SemanticException thrown when the HTML tag is not valid
+ */
+ public void validateHtmlElement(Token element) throws SemanticException;
+
+ /**
+ * Called by the SeamTextParser when a plain HTML attribute is parsed.
+ *
+ * @param element the token of the parse tree that represents the HTML tag
+ * @param attribute the token of the parse tree that represents the HTML attribute
+ * @throws SemanticException thrown if the attribute is not valid for the given HTML tag
+ */
+ public void validateHtmlAttribute(Token element, Token attribute) throws SemanticException;
+
+ /**
+ * Called by the SeamTextParser when a plain HTML attribute value is parsed.
+ *
+ * @param element the token of the parse tree that represents the HTML tag
+ * @param attribute the token of the parse tree that represents the HTML attribute
+ * @param attributeValue the plain string value of the HTML attribute
+ * @throws SemanticException thrown if the attribute value is not valid for the given HTML attribute and element
+ */
+ public void validateHtmlAttributeValue(Token element, Token attribute, String attributeValue) throws SemanticException;
+
+ public String getInvalidURIMessage(String uri);
+ public String getInvalidElementMessage(String elementName);
+ public String getInvalidAttributeMessage(String elementName, String attributeName);
+ public String getInvalidAttributeValueMessage(String elementName, String attributeName, String value);
+ }
+
+ /**
+ * Implementation of the rules in http://wiki.whatwg.org/wiki/Sanitization_rules
+ *
+ * Changes and additions:
+ *
+ * 1. Expanded all -* wildcard values to their full CSS property name (e.g. border-*).
+ *
+ * 2. Added dash as allowed characater to REGEX_VALID_CSS_STRING1.
+ *
+ * 3. Improved REGEX_VALID_CSS_VALUE with range {n,m} checks for color values and negative units.
+ *
+ * 4. Added more options (mostly of vertical-align property, e.g. "middle", "text-top") as allowed CSS values.
+ *
+ * 5. Added "max-height", "max-width", "min-height", "min-width" to CSS properties.
+ *
+ * 6. Removed 'data' URI scheme.
+ *
+ * 7. Not implemented filtering of CSS url() - it's an invalid value always.
+ *
+ */
+ public static class DefaultSanitizer implements SeamTextParser.Sanitizer {
+
+ public final java.util.regex.Pattern REGEX_VALID_CSS_STRING1 = java.util.regex.Pattern.compile(
+ "^([-:,;#%.\\sa-zA-Z0-9!]|\\w-\\w|'[\\s\\w]+'|\"[\\s\\w]+\"|\\([\\d,\\s]+\\))*$"
+ );
+
+ public final java.util.regex.Pattern REGEX_VALID_CSS_STRING2 = java.util.regex.Pattern.compile(
+ "^(\\s*[-\\w]+\\s*:\\s*[^:;]*(;|$))*$"
+ );
+
+ public final java.util.regex.Pattern REGEX_VALID_CSS_VALUE = java.util.regex.Pattern.compile(
+ "^(#[0-9a-f]{3,6}|rgb\\(\\d{1,3}%?,\\d{1,3}%?,?\\d{1,3}%?\\)?|-?\\d{0,2}\\.?\\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\\))?)$"
+ );
+
+ public final java.util.regex.Pattern REGEX_INVALID_CSS_URL = java.util.regex.Pattern.compile(
+ "url\\s*\\(\\s*[^\\s)]+?\\s*\\)\\s*"
+ );
+
+ protected java.util.Set<String> acceptableElements = new java.util.HashSet(java.util.Arrays.asList(
+ "a", "abbr", "acronym", "address", "area", "b", "bdo", "big", "blockquote",
+ "br", "button", "caption", "center", "cite", "code", "col", "colgroup", "dd",
+ "del", "dfn", "dir", "div", "dl", "dt", "em", "fieldset", "font", "form",
+ "h1", "h2", "h3", "h4", "h5", "h6", "hr", "i", "img", "input", "ins", "kbd",
+ "label", "legend", "li", "map", "menu", "ol", "optgroup", "option", "p",
+ "pre", "q", "s", "samp", "select", "small", "span", "strike", "strong",
+ "sub", "sup", "table", "tbody", "td", "textarea", "tfoot", "th", "thead",
+ "tr", "tt", "u", "ul", "var", "wbr"
+ ));
+
+ protected java.util.Set<String> mathmlElements = new java.util.HashSet(java.util.Arrays.asList(
+ "maction", "math", "merror", "mfrac", "mi", "mmultiscripts", "mn", "mo",
+ "mover", "mpadded", "mphantom", "mprescripts", "mroot", "mrow", "mspace",
+ "msqrt", "mstyle", "msub", "msubsup", "msup", "mtable", "mtd", "mtext",
+ "mtr", "munder", "munderover", "none"
+ ));
+
+ protected java.util.Set<String> svgElements = new java.util.HashSet(java.util.Arrays.asList(
+ "a", "animate", "animateColor", "animateMotion", "animateTransform",
+ "circle", "defs", "desc", "ellipse", "font-face", "font-face-name",
+ "font-face-src", "g", "glyph", "hkern", "image", "line", "linearGradient",
+ "marker", "metadata", "missing-glyph", "mpath", "path", "polygon",
+ "polyline", "radialGradient", "rect", "set", "stop", "svg", "switch", "text",
+ "title", "tspan", "use"
+ ));
+
+ protected java.util.Set<String> acceptableAttributes = new java.util.HashSet(java.util.Arrays.asList(
+ "abbr", "accept", "accept-charset", "accesskey", "action", "align", "alt",
+ "axis", "border", "cellpadding", "cellspacing", "char", "charoff", "charset",
+ "checked", "cite", "class", "clear", "color", "cols", "colspan", "compact",
+ "coords", "datetime", "dir", "disabled", "enctype", "for", "frame",
+ "headers", "height", "href", "hreflang", "hspace", "id", "ismap", "label",
+ "lang", "longdesc", "maxlength", "media", "method", "multiple", "name",
+ "nohref", "noshade", "nowrap", "prompt", "readonly", "rel", "rev", "rows",
+ "rowspan", "rules", "scope", "selected", "shape", "size", "span", "src",
+ "start", "style", "summary", "tabindex", "target", "title", "type", "usemap",
+ "valign", "value", "vspace", "width", "xml:lang"
+ ));
+
+ protected java.util.Set<String> mathmlAttributes = new java.util.HashSet(java.util.Arrays.asList(
+ "actiontype", "align", "columnalign", "columnalign", "columnalign",
+ "columnlines", "columnspacing", "columnspan", "depth", "display",
+ "displaystyle", "equalcolumns", "equalrows", "fence", "fontstyle",
+ "fontweight", "frame", "height", "linethickness", "lspace", "mathbackground",
+ "mathcolor", "mathvariant", "mathvariant", "maxsize", "minsize", "other",
+ "rowalign", "rowalign", "rowalign", "rowlines", "rowspacing", "rowspan",
+ "rspace", "scriptlevel", "selection", "separator", "stretchy", "width",
+ "width", "xlink:href", "xlink:show", "xlink:type", "xmlns", "xmlns:xlink"
+ ));
+
+ protected java.util.Set<String> svgAttributes = new java.util.HashSet(java.util.Arrays.asList(
+ "accent-height", "accumulate", "additive", "alphabetic", "arabic-form",
+ "ascent", "attributeName", "attributeType", "baseProfile", "bbox", "begin",
+ "by", "calcMode", "cap-height", "class", "color", "color-rendering",
+ "content", "cx", "cy", "d", "descent", "display", "dur", "dx", "dy", "end",
+ "fill", "fill-rule", "font-family", "font-size", "font-stretch",
+ "font-style", "font-variant", "font-weight", "from", "fx", "fy", "g1", "g2",
+ "glyph-name", "gradientUnits", "hanging", "height", "horiz-adv-x",
+ "horiz-origin-x", "id", "ideographic", "k", "keyPoints", "keySplines",
+ "keyTimes", "lang", "marker-end", "marker-mid", "marker-start",
+ "markerHeight", "markerUnits", "markerWidth", "mathematical", "max", "min",
+ "name", "offset", "opacity", "orient", "origin", "overline-position",
+ "overline-thickness", "panose-1", "path", "pathLength", "points",
+ "preserveAspectRatio", "r", "refX", "refY", "repeatCount", "repeatDur",
+ "requiredExtensions", "requiredFeatures", "restart", "rotate", "rx", "ry",
+ "slope", "stemh", "stemv", "stop-color", "stop-opacity",
+ "strikethrough-position", "strikethrough-thickness", "stroke",
+ "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
+ "stroke-miterlimit", "stroke-opacity", "stroke-width", "systemLanguage",
+ "target", "text-anchor", "to", "transform", "type", "u1", "u2",
+ "underline-position", "underline-thickness", "unicode", "unicode-range",
+ "units-per-em", "values", "version", "viewBox", "visibility", "width",
+ "widths", "x", "x-height", "x1", "x2", "xlink:actuate", "xlink:arcrole",
+ "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type",
+ "xml:base", "xml:lang", "xml:space", "xmlns", "xmlns:xlink", "y", "y1", "y2",
+ "zoomAndPan"
+ ));
+
+ protected java.util.Set<String> styleProperties = new java.util.HashSet(java.util.Arrays.asList(
+ "azimuth",
+ "background", "background-attachment", "background-color", "background-image",
+ "background-position", "background-repeat",
+ "border", "border-bottom", "border-bottom-color", "border-bottom-style",
+ "border-bottom-width", "border-collapse", "border-color", "border-left",
+ "border-left-color", "border-left-style", "border-left-width", "border-right",
+ "border-right-color", "border-right-style", "border-right-width", "border-spacing",
+ "border-style", "border-top", "border-top-color", "border-top-style",
+ "border-top-width", "border-width",
+ "clear", "color",
+ "cursor", "direction", "display", "elevation", "float", "font",
+ "font-family", "font-size", "font-style", "font-variant", "font-weight",
+ "height", "letter-spacing", "line-height",
+ "margin", "margin-bottom", "margin-left", "margin-right", "margin-top",
+ "max-height", "max-width", "min-height", "min-width",
+ "overflow",
+ "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
+ "pause", "pause-after", "pause-before", "pitch",
+ "pitch-range", "richness", "speak", "speak-header", "speak-numeral",
+ "speak-punctuation", "speech-rate", "stress", "text-align",
+ "text-decoration", "text-indent", "unicode-bidi", "vertical-align",
+ "voice-family", "volume", "white-space", "width"
+ ));
+
+ protected java.util.Set<String> stylePropertiesValues = new java.util.HashSet(java.util.Arrays.asList(
+ "aqua", "auto", "baseline", "black", "block", "blue", "bold", "both", "bottom", "brown",
+ "center", "collapse", "dashed", "dotted", "fuchsia", "gray", "green",
+ "inherit", "italic", "left", "length", "lime", "maroon", "medium", "middle", "navy", "none", "normal",
+ "nowrap", "olive", "percentage", "pointer", "purple", "red", "right", "silver", "solid", "sub", "super",
+ "teal", "text-bottom", "text-top", "top", "transparent", "underline", "white", "yellow"
+ ));
+
+ protected java.util.Set<String> svgStyleProperties = new java.util.HashSet(java.util.Arrays.asList(
+ "fill", "fill-opacity", "fill-rule", "stroke", "stroke-linecap",
+ "stroke-linejoin", "stroke-opacity", "stroke-width"
+ ));
+
+ protected java.util.Set<String> attributesWhoseValueIsAURI = new java.util.HashSet(java.util.Arrays.asList(
+ "action", "cite", "href", "longdesc", "src", "xlink:href", "xml:base"
+ ));
+
+ protected java.util.Set<String> uriSchemes = new java.util.HashSet(java.util.Arrays.asList(
+ "afs", "aim", "callto", "ed2k", "feed", "ftp", "gopher", "http", "https",
+ "irc", "mailto", "news", "nntp", "rsync", "rtsp", "sftp", "ssh", "tag",
+ "tel", "telnet", "urn", "webcal", "wtai", "xmpp"
+ ));
+
+ public void validateLinkTagURI(String uri) throws SemanticException {
+ if (!validateURI(uri)) {
+ throw new SemanticException("Invalid URI");
+ }
+ }
+
+ public void validateHtmlElement(Token element) throws SemanticException {
+ String elementName = element.getText().toLowerCase();
+
+ if (!acceptableElements.contains(elementName) &&
+ !svgElements.contains(elementName) &&
+ !mathmlElements.contains(elementName)) {
+ throw new SemanticException(getInvalidElementMessage(elementName));
+ }
+ }
+
+ public void validateHtmlAttribute(Token element, Token attribute) throws SemanticException {
+ String elementName = element.getText().toLowerCase();
+ String attributeName = attribute.getText().toLowerCase();
+ if (!acceptableAttributes.contains(attributeName) &&
+ !svgAttributes.contains(attributeName) &&
+ !mathmlAttributes.contains(attributeName)) {
+ throw new SemanticException(getInvalidAttributeMessage(elementName, attributeName));
+ }
+ }
+
+ public void validateHtmlAttributeValue(Token element,
+ Token attribute,
+ String attributeValue) throws SemanticException {
+
+ String elementName = element.getText().toLowerCase();
+ String attributeName = attribute.getText().toLowerCase();
+
+ // Check element with attribute that has URI value (href, src, etc.)
+ if (attributesWhoseValueIsAURI.contains(attributeName) && !validateURI(attributeValue)) {
+ throw new SemanticException(getInvalidURIMessage(attributeValue));
+ }
+
+ // Check attribute value of style (CSS filtering)
+ if (attributeName.equals("style")) {
+ if (!REGEX_VALID_CSS_STRING1.matcher(attributeValue).matches() ||
+ !REGEX_VALID_CSS_STRING2.matcher(attributeValue).matches()) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+
+ String[] cssProperties = attributeValue.split(";");
+ for (String cssProperty : cssProperties) {
+ if (!cssProperty.contains(":")) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+ String[] property = cssProperty.split(":");
+ String propertyName = property[0].trim();
+ String propertyValue = property.length == 2 ? property[1].trim() : null;
+
+ // CSS property name
+ if (!styleProperties.contains(propertyName) &&
+ !svgStyleProperties.contains(propertyName)) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+
+ // CSS property value
+ if (!stylePropertiesValues.contains(propertyValue)) {
+ // Not in list, now check the regex
+ if (!REGEX_VALID_CSS_VALUE.matcher(propertyValue).matches()) {
+ throw new SemanticException(getInvalidAttributeValueMessage(elementName, attributeName, attributeValue));
+ }
+ }
+ }
+ }
+
+ // TODO: Implement SVG style checking?! Who cares...
+ }
+
+ /**
+ * Validate a URI string.
+ * <p>
+ * The default implementation accepts any URI string that starts with a slash,
+ * this is considered a relative URL. Any absolute URI is parsed by the JDK with
+ * the <tt>java.net.URI</tt> constructor. Finally, the scheme of the parsed
+ * absolute URI is checked with a list of valid schemes.
+ * </p>
+ *
+ * @param uri the URI string
+ * @return return true if the String represents a safe and valid URI
+ */
+ protected boolean validateURI(String uri) {
+
+ // Relative URI starts with a slash
+ if (uri.startsWith("/")) return true;
+
+ java.net.URI parsedURI;
+ try {
+ parsedURI = new java.net.URI(uri);
+ } catch (java.net.URISyntaxException ex) {
+ return false;
+ }
+
+ if (!uriSchemes.contains(parsedURI.getScheme())) {
+ return false;
+ }
+ return true;
+ }
+
+ public String getInvalidURIMessage(String uri) {
+ return "invalid URI";
+ }
+
+ public String getInvalidElementMessage(String elementName) {
+ return "invalid element '" + elementName + "'";
+ }
+
+ public String getInvalidAttributeMessage(String elementName, String attributeName) {
+ return "invalid attribute '" + attributeName + "' for element '" + elementName + "'";
+ }
+
+ public String getInvalidAttributeValueMessage(String elementName, String attributeName, String value) {
+ return "invalid value of attribute '" + attributeName + "' for element '" + elementName + "'";
+ };
+
+ }
+
+ private Sanitizer sanitizer = new DefaultSanitizer();
+ public void setSanitizer(Sanitizer sanitizer) {
+ this.sanitizer = sanitizer;
+ }
+
+ private Macro currentMacro;
+ private java.util.Stack<Token> htmlElementStack = new java.util.Stack<Token>();
+
+ private StringBuilder mainBuilder = new StringBuilder();
+ private StringBuilder builder = mainBuilder;
+
+ public String toString() {
+ return builder.toString();
+ }
+
+ private void append(String... strings) {
+ for (String string: strings) builder.append(string);
+ }
+
+ private static boolean hasMultiple(String string, char c) {
+ return string.indexOf(c)!=string.lastIndexOf(c);
+ }
+
+ private void beginCapture() {
+ builder = new StringBuilder();
+ }
+
+ private String endCapture() {
+ String result = builder.toString();
+ builder = mainBuilder;
+ return result;
+ }
+
+ protected String linkTag(String description, String url) {
+ return "<a href=\"" + url + "\" class=\"seamTextLink\">" + description + "</a>";
+ }
+
+ protected String macroInclude(String macroName) {
+ return "";
+ }
+
+ protected String macroInclude(Macro m) {
+ return macroInclude(m.name);
+ }
+
+ protected String paragraphOpenTag() {
+ return "<p class=\"seamTextPara\">\n";
+ }
+
+ protected String preformattedOpenTag() {
+ return "<pre class=\"seamTextPreformatted\">\n";
+ }
+
+ protected String blockquoteOpenTag() {
+ return "<blockquote class=\"seamTextBlockquote\">\n";
+ }
+
+ protected String headline1(String line) {
+ return "<h1 class=\"seamTextHeadline1\">" + line + "</h1>";
+ }
+
+ protected String headline2(String line) {
+ return "<h2 class=\"seamTextHeadline2\">" + line + "</h2>";
+ }
+
+ protected String headline3(String line) {
+ return "<h3 class=\"seamTextHeadline3\">" + line + "</h3>";
+ }
+
+ protected String headline4(String line) {
+ return "<h4 class=\"seamTextHeadline4\">" + line + "</h4>";
+ }
+
+ protected String orderedListOpenTag() {
+ return "<ol class=\"seamTextOrderedList\">\n";
+ }
+
+ protected String orderedListItemOpenTag() {
+ return "<li class=\"seamTextOrderedListItem\">";
+ }
+
+ protected String unorderedListOpenTag() {
+ return "<ul class=\"seamTextUnorderedList\">\n";
+ }
+
+ protected String unorderedListItemOpenTag() {
+ return "<li class=\"seamTextUnorderedListItem\">";
+ }
+
+ protected String emphasisOpenTag() {
+ return "<i class=\"seamTextEmphasis\">";
+ }
+
+ protected String emphasisCloseTag() {
+ return "</i>";
+ }
+}
+
+startRule: (newline)* ( (heading (newline)* )? text (heading (newline)* text)* )?
+ ;
+
+text: ( (paragraph|preformatted|blockquote|list|html) (newline)* )+
+ ;
+
+paragraph: { append( paragraphOpenTag() ); } (line newlineOrEof)+ { append("</p>\n"); } newlineOrEof
+ ;
+
+line: (plain|formatted) (plain|formatted|preformatted|quoted|html)*
+ ;
+
+blockquote: DOUBLEQUOTE { append( blockquoteOpenTag() ); }
+ (plain|formatted|preformatted|newline|html|list)*
+ DOUBLEQUOTE newlineOrEof { append("</blockquote>\n"); }
+ ;
+
+preformatted: BACKTICK { append( preformattedOpenTag() ); }
+ (word|punctuation|specialChars|moreSpecialChars|htmlSpecialChars|space|newline)*
+ BACKTICK { append("</pre>"); }
+ ;
+
+plain: word|punctuation|escape|space|link|macro
+ ;
+
+formatted: underline|emphasis|monospace|superscript|deleted
+ ;
+
+word: an:ALPHANUMERICWORD { append( an.getText() ); } | uc:UNICODEWORD { append( uc.getText() ); }
+ ;
+
+punctuation: p:PUNCTUATION { append( p.getText() ); }
+ | sq:SINGLEQUOTE { append( sq.getText() ); }
+ | s:SLASH { append( s.getText() ); }
+ ;
+
+escape: ESCAPE ( specialChars | moreSpecialChars | evenMoreSpecialChars | htmlSpecialChars | b:BACKTICK {append( b.getText() );} )
+ ;
+
+specialChars:
+ st:STAR { append( st.getText() ); }
+ | b:BAR { append( b.getText() ); }
+ | h:HAT { append( h.getText() ); }
+ | p:PLUS { append( p.getText() ); }
+ | eq:EQ { append( eq.getText() ); }
+ | hh:HASH { append( hh.getText() ); }
+ | e:ESCAPE { append( e.getText() ); }
+ | t:TWIDDLE { append( t.getText() ); }
+ | u:UNDERSCORE { append( u.getText() ); }
+ ;
+
+moreSpecialChars:
+ o:OPEN { append( o.getText() ); }
+ | c:CLOSE { append( c.getText() ); }
+ ;
+
+evenMoreSpecialChars:
+ q:QUOTE { append( q.getText() ); }
+ ;
+
+htmlSpecialChars:
+ GT { append(">"); }
+ | LT { append("<"); }
+ | DOUBLEQUOTE { append("""); }
+ | AMPERSAND { append("&"); }
+ ;
+
+link: OPEN
+ { beginCapture(); }
+ (word|punctuation|escape|space)*
+ { String text=endCapture(); }
+ EQ GT
+ { beginCapture(); }
+ attributeValue
+ {
+ String link = endCapture();
+ sanitizer.validateLinkTagURI(link);
+ append(linkTag(text, link));
+ }
+ CLOSE
+ ;
+
+/*
+
+[<=macro[param1=value "1"][param2=value '2']]
+
+*/
+macro: OPEN
+ LT EQ
+ mn:ALPHANUMERICWORD { currentMacro = new Macro(mn.getText()); }
+ (macroParam)*
+ CLOSE
+ { append( macroInclude(currentMacro) ); currentMacro = null; }
+ ;
+
+macroParam:
+ OPEN
+ pn:ALPHANUMERICWORD
+ EQ
+ { beginCapture(); }
+ macroParamValue
+ { String pv = endCapture(); currentMacro.params.put(pn.getText(),pv); }
+ CLOSE
+ ;
+
+macroParamValue:
+ ( amp:AMPERSAND { append(amp.getText()); } |
+ dq:DOUBLEQUOTE { append(dq.getText()); } |
+ sq:SINGLEQUOTE { append(sq.getText()); } |
+ an:ALPHANUMERICWORD { append(an.getText()); } |
+ p:PUNCTUATION { append(p.getText()); } |
+ s:SLASH { append(s.getText()); } |
+ lt:LT { append(lt.getText()); } |
+ gt:GT { append(gt.getText()); } |
+ space | specialChars )*
+ ;
+
+emphasis: STAR { append( emphasisOpenTag() ); }
+ (plain|underline|monospace|superscript|deleted|newline)+
+ STAR { append( emphasisCloseTag() ); }
+ ;
+
+underline: UNDERSCORE { append("<u>"); }
+ (plain|emphasis|monospace|superscript|deleted|newline)+
+ UNDERSCORE { append("</u>"); }
+ ;
+
+
+monospace: BAR { append("<tt>"); }
+ (word | punctuation | space
+ | st:STAR { append( st.getText() ); }
+ | h:HAT { append( h.getText() ); }
+ | p:PLUS { append( p.getText() ); }
+ | eq:EQ { append( eq.getText() ); }
+ | hh:HASH { append( hh.getText() ); }
+ | e:ESCAPE { append( e.getText() ); }
+ | t:TWIDDLE { append( t.getText() ); }
+ | u:UNDERSCORE { append( u.getText() ); }
+ | moreSpecialChars
+ | htmlSpecialChars
+ | newline)+
+ BAR { append("</tt>"); }
+ ;
+
+superscript: HAT { append("<sup>"); }
+ (plain|emphasis|underline|monospace|deleted|newline)+
+ HAT { append("</sup>"); }
+ ;
+
+deleted: TWIDDLE { append("<del>"); }
+ (plain|emphasis|underline|monospace|superscript|newline)+
+ TWIDDLE { append("</del>"); }
+ ;
+
+quoted: DOUBLEQUOTE { append("<q>"); }
+ (plain|emphasis|underline|monospace|superscript|deleted|newline)+
+ DOUBLEQUOTE { append("</q>"); }
+ ;
+
+heading: ( h1 | h2 | h3 | h4 ) newlineOrEof
+ ;
+
+h1: PLUS
+ { beginCapture(); }
+ line
+ { String headline=endCapture(); }
+ { append(headline1(headline.trim())); }
+ ;
+
+h2: PLUS PLUS
+ { beginCapture(); }
+ line
+ { String headline=endCapture(); }
+ { append(headline2(headline.trim())); }
+ ;
+
+h3: PLUS PLUS PLUS
+ { beginCapture(); }
+ line
+ { String headline=endCapture(); }
+ { append(headline3(headline.trim())); }
+ ;
+
+h4: PLUS PLUS PLUS PLUS
+ { beginCapture(); }
+ line
+ { String headline=endCapture(); }
+ { append(headline4(headline.trim())); }
+ ;
+
+list: ( olist | ulist ) newlineOrEof
+ ;
+
+olist: { append( orderedListOpenTag() ); } (olistLine newlineOrEof)+ { append("</ol>\n"); }
+ ;
+
+olistLine: HASH { append( orderedListItemOpenTag() ); } line { append("</li>"); }
+ ;
+
+ulist: { append( unorderedListOpenTag() ); } (ulistLine newlineOrEof)+ { append("</ul>\n"); }
+ ;
+
+ulistLine: EQ { append( unorderedListItemOpenTag() ); } line { append("</li>"); }
+ ;
+
+space: s:SPACE { append( s.getText() ); }
+ ;
+
+newline: n:NEWLINE { append( n.getText() ); }
+ ;
+
+newlineOrEof: newline | EOF
+ ;
+
+html: openTag ( space | space attribute )* ( ( beforeBody body closeTagWithBody ) | closeTagWithNoBody )
+ ;
+
+body: (plain|formatted|preformatted|quoted|html|list|newline)*
+ ;
+
+openTag:
+ LT name:ALPHANUMERICWORD
+ {
+ htmlElementStack.push(name);
+ sanitizer.validateHtmlElement(name);
+ append("<");
+ append(name.getText());
+ }
+ ;
+
+beforeBody: GT { append(">"); }
+ ;
+
+closeTagWithBody:
+ LT SLASH name:ALPHANUMERICWORD GT
+ {
+ append("</");
+ append(name.getText());
+ append(">");
+ htmlElementStack.pop();
+ }
+ ;
+
+closeTagWithNoBody:
+ SLASH GT
+ {
+ append("/>");
+ htmlElementStack.pop();
+ }
+ ;
+
+attribute: att:ALPHANUMERICWORD (space)* EQ (space)*
+ DOUBLEQUOTE
+ {
+ sanitizer.validateHtmlAttribute(htmlElementStack.peek(), att);
+ append(att.getText());
+ append("=\"");
+ }
+ {
+ beginCapture();
+ }
+ attributeValue
+ {
+ String attValue = endCapture();
+ sanitizer.validateHtmlAttributeValue(htmlElementStack.peek(), att, attValue);
+ append(attValue);
+ }
+ DOUBLEQUOTE { append("\""); }
+ ;
+
+attributeValue: ( AMPERSAND { append("&"); } |
+ an:ALPHANUMERICWORD { append( an.getText() ); } |
+ p:PUNCTUATION { append( p.getText() ); } |
+ s:SLASH { append( s.getText() ); } |
+ space | specialChars )*
+ ;
+
+class SeamTextLexer extends Lexer;
+options
+{
+ k=2;
+
+ // Allow any char but \uFFFF (16 bit -1)
+ charVocabulary='\u0000'..'\uFFFE';
+}
+
+// Unicode sets allowed:
+// '\u00a0'..'\u00ff' Latin 1 supplement (no control characters) http://www.unicode.org/charts/PDF/U0080.pdf
+// '\u0100'..'\u017f' Latin Extended A http://www.unicode.org/charts/PDF/U0100.pdf
+// '\u0180'..'\u024f' Latin Extended B http://www.unicode.org/charts/PDF/U0180.pdf
+// '\u0250'..'\ufaff' Various other languages, punctuation etc. (excluding "presentation forms")
+// '\uff00'..'\uffef' Halfwidth and Fullwidth forms (including CJK punctuation)
+
+ALPHANUMERICWORD: ('a'..'z'|'A'..'Z'|'0'..'9')+
+ ;
+
+UNICODEWORD: (
+ '\u00a0'..'\u00ff' |
+ '\u0100'..'\u017f' |
+ '\u0180'..'\u024f' |
+ '\u0250'..'\ufaff' |
+ '\uff00'..'\uffef'
+ )+
+ ;
+
+PUNCTUATION: '-' | ';' | ':' | '(' | ')' | '{' | '}' | '?' | '!' | '@' | '%' | '.' | ',' | '$'
+ ;
+
+EQ: '='
+ ;
+
+PLUS: '+'
+ ;
+
+UNDERSCORE: '_'
+ ;
+
+STAR: '*'
+ ;
+
+SLASH: '/'
+ ;
+
+ESCAPE: '\\'
+ ;
+
+BAR: '|'
+ ;
+
+BACKTICK: '`'
+ ;
+
+TWIDDLE: '~'
+ ;
+
+DOUBLEQUOTE: '"'
+ ;
+
+SINGLEQUOTE: '\''
+ ;
+
+OPEN: '['
+ ;
+
+CLOSE: ']'
+ ;
+
+HASH: '#'
+ ;
+
+HAT: '^'
+ ;
+
+GT: '>'
+ ;
+
+LT: '<'
+ ;
+
+AMPERSAND: '&'
+ ;
+
+SPACE: (' '|'\t')+
+ ;
+
+NEWLINE: "\r\n" | '\r' | '\n'
+ ;
+
+EOF : '\uFFFF'
+ ;
Modified: branches/Seam_2_0_FP/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java
===================================================================
--- branches/Seam_2_0_FP/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java 2008-08-04 14:15:41 UTC (rev 8563)
+++ branches/Seam_2_0_FP/ui/src/main/java/org/jboss/seam/ui/validator/FormattedTextValidator.java 2008-08-04 14:18:51 UTC (rev 8564)
@@ -56,9 +56,7 @@
+ value);
}
String text = (String) value;
- Reader r = new StringReader(text);
- SeamTextLexer lexer = new SeamTextLexer(r);
- SeamTextParser parser = new SeamTextParser(lexer);
+ SeamTextParser parser = getSeamTextParser(text);
try {
parser.startRule();
}
@@ -79,6 +77,18 @@
+ firstError));
}
}
+
+ /**
+ * Override to instantiate a custom <tt>SeamTextLexer</tt> and <tt>SeamTextParser</tt>.
+ *
+ * @param text the raw markup text
+ * @return an instance of <tt>SeamTextParser</tt>
+ */
+ public SeamTextParser getSeamTextParser(String text) {
+ Reader r = new StringReader(text);
+ SeamTextLexer lexer = new SeamTextLexer(r);
+ return new SeamTextParser(lexer);
+ }
/**
* Extracts the error from the <tt>RecognitionException</tt> and generates
[View Less]
16 years, 7 months
Seam SVN: r8563 - in branches/Seam_2_0_FP: examples/mail/src/org/jboss/seam/example/mail/test and 10 other directories.
by seam-commits@lists.jboss.org
Author: manaRH
Date: 2008-08-04 10:15:41 -0400 (Mon, 04 Aug 2008)
New Revision: 8563
Added:
branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/sanitization.xhtml
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/Header.java
branches/Seam_2_0_FP/src/test/mail/
branches/Seam_2_0_FP/src/test/mail/unit/
branches/Seam_2_0_FP/src/test/mail/unit/org/
branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/
branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/
…
[View More] branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/
branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/
branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/
branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/HeaderTest.java
branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/testng.xml
Modified:
branches/Seam_2_0_FP/build/mail.pom.xml
branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/MailTest.java
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/AddressComponent.java
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIAttachment.java
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIBody.java
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIHeader.java
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIMessage.java
branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UISubject.java
Log:
Backport of JBSEAM-3071
Modified: branches/Seam_2_0_FP/build/mail.pom.xml
===================================================================
--- branches/Seam_2_0_FP/build/mail.pom.xml 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/build/mail.pom.xml 2008-08-04 14:15:41 UTC (rev 8563)
@@ -59,6 +59,19 @@
<artifactId>el-api</artifactId>
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>5.6</version>
+ <optional>true</optional>
+ <exclusions>
+ <exclusion>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
</dependencies>
Modified: branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/MailTest.java
===================================================================
--- branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/MailTest.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/MailTest.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -528,6 +528,39 @@
}
@Test
+ public void testSanitization() throws Exception
+ {
+
+ new FacesRequest()
+ {
+ @Override
+ protected void updateModelValues() throws Exception
+ {
+
+ }
+
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ Contexts.getEventContext().set("name", "Pete\nMuir");
+ MimeMessage renderedMessage = getRenderedMailMessage("/org/jboss/seam/example/mail/test/sanitization.xhtml");
+ assert "Try out".equals(renderedMessage.getSubject());
+ InternetAddress to = (InternetAddress) renderedMessage.getAllRecipients()[0];
+ assert to.getAddress().equals("peter(a)email.tld");
+ assert to.getPersonal().equals("Pete");
+ assert renderedMessage.getFrom().length == 1;
+ assert renderedMessage.getFrom()[0] instanceof InternetAddress;
+ InternetAddress from = (InternetAddress) renderedMessage.getFrom()[0];
+ assert from.getAddress().equals("peter(a)example.com");
+ assert from.getPersonal().equals("Pete");
+ assert renderedMessage.getHeader("Pete") != null;
+ assert renderedMessage.getHeader("Pete").length == 1;
+ assert "roll".equals(renderedMessage.getHeader("Pete")[0]);
+ }
+ }.run();
+ }
+
+ @Test
public void testTemplating() throws Exception
{
Added: branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/sanitization.xhtml
===================================================================
--- branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/sanitization.xhtml (rev 0)
+++ branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/sanitization.xhtml 2008-08-04 14:15:41 UTC (rev 8563)
@@ -0,0 +1,14 @@
+<m:message xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:m="http://jboss.com/products/seam/mail"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <m:from name="#{name}">peter(a)example.com
+foo</m:from>
+ <m:to name="#{name}">peter(a)email.tld
+bar</m:to>
+ <m:subject>Try out
+Seam!</m:subject>
+ <m:header name="#{name}">roll
+over</m:header>
+ <m:body>A mail message to test sanitization</m:body>
+</m:message>
\ No newline at end of file
Property changes on: branches/Seam_2_0_FP/examples/mail/src/org/jboss/seam/example/mail/test/sanitization.xhtml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/AddressComponent.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/AddressComponent.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/AddressComponent.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -25,15 +25,16 @@
protected InternetAddress getInternetAddress(FacesContext facesContext) throws IOException, AddressException
{
InternetAddress address = new InternetAddress();
- address.setAddress(getAddress() != null ? getAddress() : encode(facesContext));
+ address.setAddress(new Header(getAddress() != null ? getAddress() : encode(facesContext)).getSanitizedValue());
String charset = findMessage().getCharset();
+ String personal = new Header(getName()).getSanitizedValue();
if (charset == null)
{
- address.setPersonal(getName());
+ address.setPersonal(personal);
}
else
{
- address.setPersonal(getName(), charset);
+ address.setPersonal(personal, charset);
}
address.validate();
return address;
@@ -70,7 +71,7 @@
*/
public String getName()
{
- if (address == null)
+ if (name == null)
{
return getString("name");
}
Added: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/Header.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/Header.java (rev 0)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/Header.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -0,0 +1,82 @@
+package org.jboss.seam.mail.ui;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.mail.internet.MimeUtility;
+
+public class Header
+{
+
+ private final String name;
+ private final String value;
+
+ private String sanitizedName;
+ private String sanitizedValue;
+
+ public Header(String name, String value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+
+ public Header(String value)
+ {
+ this.value = value;
+ this.name = null;
+ }
+
+ public String getSanitizedName()
+ {
+ if (sanitizedName == null && name != null)
+ {
+ try
+ {
+ sanitizedName = sanitize(name);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Error santizing Header name " + name, e);
+ }
+ }
+ return sanitizedName;
+ }
+
+ public String getSanitizedValue()
+ {
+ if (sanitizedValue == null && value != null)
+ {
+ try
+ {
+ sanitizedValue = sanitizeValue(value);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Error santizing Header " + name + " value " + value, e);
+ }
+ }
+ return sanitizedValue;
+ }
+
+ /**
+ * Remove any line feed/new line characters
+ * @throws IOException
+ */
+ public static String sanitize(String value) throws IOException
+ {
+ BufferedReader reader = new BufferedReader(new StringReader(value));
+ return reader.readLine();
+ }
+
+ /**
+ * Remove any line feed/new line characters from a (possibly) folded header
+ * @throws IOException
+ */
+ public static String sanitizeValue(String value) throws IOException
+ {
+ // The user might have folded the header (stupid SMTP idiocy)
+ return sanitize(MimeUtility.unfold(value));
+ }
+
+}
Property changes on: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/Header.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIAttachment.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIAttachment.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIAttachment.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -163,10 +163,10 @@
MimeBodyPart attachment = new MimeBodyPart();
// Need to manually set the contentid
String contentId = RandomStringUtils.randomAlphabetic(20).toLowerCase();
- attachment.setContentID("<" + contentId + ">");
+ attachment.setContentID(new Header("<" + contentId + ">").getSanitizedValue());
attachment.setDataHandler(new DataHandler(ds));
- attachment.setFileName(getName(ds.getName()));
- attachment.setDisposition(getDisposition());
+ attachment.setFileName(new Header(getName(ds.getName())).getSanitizedValue());
+ attachment.setDisposition(new Header(getDisposition()).getSanitizedValue());
super.getRootMultipart().addBodyPart(attachment);
if (getStatus() != null)
{
Modified: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIBody.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIBody.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIBody.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -88,13 +88,13 @@
throws MessagingException
{
MimeBodyPart bodyPart = new MimeBodyPart();
- bodyPart.setDisposition("inline");
+ bodyPart.setDisposition(new Header("inline").getSanitizedValue());
String charset = findMessage().getCharset();
if ( charset != null)
{
//bodyPart.setContent(body, "text/plain; charset="
// + charset + "; format=flowed");
- bodyPart.setText(body, charset);
+ bodyPart.setText(body, new Header(charset).getSanitizedValue());
}
else
{
@@ -107,16 +107,16 @@
throws MessagingException
{
MimeBodyPart bodyPart = new MimeBodyPart();
- bodyPart.setDisposition("inline");
+ bodyPart.setDisposition(new Header("inline").getSanitizedValue());
String charset = findMessage().getCharset();
if ( charset != null)
{
- bodyPart.setContent(body, "text/html; charset="
- + charset);
+ bodyPart.setContent(body, new Header("text/html; charset="
+ + charset).getSanitizedValue());
}
else
{
- bodyPart.setContent(body, "text/html");
+ bodyPart.setContent(body, new Header("text/html").getSanitizedValue());
}
return bodyPart;
Modified: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIHeader.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIHeader.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIHeader.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -17,11 +17,16 @@
{
try
{
- if (getValue() != null) {
- findMimeMessage().addHeader(getName(), getValue());
- } else {
- findMimeMessage().addHeader(getName(), encode(facesContext));
+ if (getValue() != null)
+ {
+ Header header = new Header(getName(), getValue());
+ findMimeMessage().addHeader(header.getSanitizedName(), header.getSanitizedValue());
}
+ else
+ {
+ Header header = new Header(getName(), encode(facesContext));
+ findMimeMessage().addHeader(header.getSanitizedName(), header.getSanitizedValue());
+ }
}
catch (MessagingException e)
{
Modified: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIMessage.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIMessage.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UIMessage.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -108,7 +108,8 @@
}
if (getPrecedence() != null)
{
- getMimeMessage().addHeader("Precedence", getPrecedence());
+ Header header = new Header("Precedence", getPrecedence());
+ getMimeMessage().addHeader(header.getSanitizedName(), header.getSanitizedValue());
}
}
catch (MessagingException e)
@@ -131,8 +132,9 @@
if (isRequestReadReceipt() && getMimeMessage().getFrom() != null
&& getMimeMessage().getFrom().length == 1)
{
- getMimeMessage().addHeader("Disposition-Notification-To",
- getMimeMessage().getFrom()[0].toString());
+ Header header = new Header("Disposition-Notification-To",
+ getMimeMessage().getFrom()[0].toString());
+ getMimeMessage().addHeader(header.getSanitizedName(), header.getSanitizedValue());
}
// Do the send manually, Transport.send gets the wrong transport
getMimeMessage().saveChanges();
Modified: branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UISubject.java
===================================================================
--- branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UISubject.java 2008-08-04 01:22:44 UTC (rev 8562)
+++ branches/Seam_2_0_FP/src/mail/org/jboss/seam/mail/ui/UISubject.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -22,11 +22,11 @@
String charset = findMessage().getCharset();
if (charset == null)
{
- findMimeMessage().setSubject(subject);
+ findMimeMessage().setSubject(new Header(subject).getSanitizedValue());
}
else
{
- findMimeMessage().setSubject(subject, charset);
+ findMimeMessage().setSubject(new Header(subject).getSanitizedValue(), charset);
}
}
catch (MessagingException e)
Added: branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/HeaderTest.java
===================================================================
--- branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/HeaderTest.java (rev 0)
+++ branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/HeaderTest.java 2008-08-04 14:15:41 UTC (rev 8563)
@@ -0,0 +1,105 @@
+package org.jboss.seam.test.mail.unit;
+
+import org.jboss.seam.mail.ui.Header;
+import org.testng.annotations.Test;
+
+public class HeaderTest
+{
+ @Test
+ public void testHeader()
+ {
+ String name = "foo";
+ String value = "bar";
+
+ Header header = new Header(name, value);
+
+ assert header.getSanitizedName().equals(name);
+ assert header.getSanitizedValue().equals(value);
+ }
+
+ @Test
+ public void testHeaderWithLineFeed()
+ {
+ String name = "foo\nnewline";
+ String value = "bar\nnewline";
+
+ Header header = new Header(name, value);
+
+ assert !header.getSanitizedName().equals(name);
+ assert !header.getSanitizedValue().equals(value);
+
+ assert "foo".equals(header.getSanitizedName());
+ assert "bar".equals(header.getSanitizedValue());
+ }
+
+ @Test
+ public void testHeaderWithCarrigeReturnLineBreak()
+ {
+ String name = "foo\r\nnewline";
+ String value = "bar\r\nnewline";
+
+ Header header = new Header(name, value);
+
+ assert !header.getSanitizedName().equals(name);
+ assert !header.getSanitizedValue().equals(value);
+
+ assert "foo".equals(header.getSanitizedName());
+ assert "bar".equals(header.getSanitizedValue());
+ }
+
+ @Test
+ public void testHeaderWithCarriageReturn()
+ {
+ String name = "foo\rnewline";
+ String value = "bar\rnewline";
+
+ Header header = new Header(name, value);
+
+ assert !header.getSanitizedName().equals(name);
+ assert !header.getSanitizedValue().equals(value);
+
+ assert "foo".equals(header.getSanitizedName());
+ assert "bar".equals(header.getSanitizedValue());
+ }
+
+ @Test
+ public void testHeaderWithFolding1()
+ {
+ String name = "header";
+ String value = "\"Joe & J. Harvey\" <ddd @ Org>,\n JJV @ BBN";
+ String sanitizedValue = "\"Joe & J. Harvey\" <ddd @ Org>, JJV @ BBN";
+
+ Header header = new Header(name, value);
+
+ assert header.getSanitizedName().equals(name);
+ assert header.getSanitizedValue().equals(sanitizedValue);
+
+ }
+
+ @Test
+ public void testHeaderWithFolding2()
+ {
+ String name = "header";
+ String value = "\"Joe & J. Harvey\"\n <ddd @ Org>, JJV\n @ BBN";
+ String sanitizedValue = "\"Joe & J. Harvey\" <ddd @ Org>, JJV @ BBN";
+
+ Header header = new Header(name, value);
+
+ assert header.getSanitizedName().equals(name);
+ assert header.getSanitizedValue().equals(sanitizedValue);
+
+ }
+
+ @Test
+ public void testHeaderWithFolding3()
+ {
+ String name = "header";
+ String value = "\"Joe &\n J. Harvey\" <ddd @ Org>, JJV @ BBN";
+ String sanitizedValue = "\"Joe & J. Harvey\" <ddd @ Org>, JJV @ BBN";
+ Header header = new Header(name, value);
+
+ assert header.getSanitizedName().equals(name);
+ assert header.getSanitizedValue().equals(sanitizedValue);
+
+ }
+}
Added: branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/testng.xml
===================================================================
--- branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/testng.xml (rev 0)
+++ branches/Seam_2_0_FP/src/test/mail/unit/org/jboss/seam/test/mail/unit/testng.xml 2008-08-04 14:15:41 UTC (rev 8563)
@@ -0,0 +1,9 @@
+<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
+
+<suite name="Seam Mail Unit Testsuite" verbose="2" parallel="false">
+ <test name="Seam Unit Tests: Mail">
+ <classes>
+ <class name="org.jboss.seam.test.mail.unit.HeaderTest"/>
+ </classes>
+ </test>
+</suite>
[View Less]
16 years, 7 months
Seam SVN: r8562 - trunk/doc/Seam_Reference_Guide/en-US.
by seam-commits@lists.jboss.org
Author: shane.bryzak(a)jboss.com
Date: 2008-08-03 21:22:44 -0400 (Sun, 03 Aug 2008)
New Revision: 8562
Modified:
trunk/doc/Seam_Reference_Guide/en-US/Security.xml
Log:
documented typesafe role checks
Modified: trunk/doc/Seam_Reference_Guide/en-US/Security.xml
===================================================================
--- trunk/doc/Seam_Reference_Guide/en-US/Security.xml 2008-08-04 01:12:40 UTC (rev 8561)
+++ trunk/doc/Seam_Reference_Guide/en-US/Security.xml 2008-08-04 01:22:44 UTC …
[View More](rev 8562)
@@ -2966,7 +2966,7 @@
</sect2>
<sect2>
- <title>Typesafe Security Annotations</title>
+ <title>Typesafe Permission Annotations</title>
<para>
Seam provides a number of annotations that may be used as an alternative to <literal>@Restrict</literal>, which have
@@ -3041,7 +3041,34 @@
<programlisting><![CDATA[@PermissionCheck("upgrade")]]></programlisting>
+ </sect2>
+
+ <sect2>
+ <title>Typesafe Role Annotations</title>
+ <para>
+ In addition to supporting typesafe permission annotation, Seam Security also provides typesafe role annotations that
+ allow you to restrict access to component methods based on the role memberships of the currently authenticated user.
+ Seam provides one such annotation out of the box, <literal>org.jboss.seam.annotations.security.Admin</literal>, used
+ to restrict access to a method to users that are a member of the <literal>admin</literal> role (so long as your
+ own application supports such a role). To create your own role annotations, simply meta-annotate them with
+ <literal>org.jboss.seam.annotations.security.RoleCheck</literal>, like in the following example:
+ </para>
+
+ <programlisting><![CDATA[@Target({METHOD})
+@Documented
+@Retention(RUNTIME)
+@Inherited
+@RoleCheck
+public @interface User {
+}]]></programlisting>
+
+ <para>
+ Any methods subsequently annotated with the <literal>@User</literal> annotation as shown in the above example
+ will be automatically intercepted and the user checked for the membership of the corresponding role name
+ (which is the lower case version of the annotation name, in this case <literal>user</literal>).
+ </para>
+
</sect2>
<sect2>
@@ -4379,8 +4406,9 @@
<title>Permission checks for PermissionManager operations</title>
<para>
- Invoking the methods of <literal>PermissionManager</literal> requires that currently authenticated user
- has the appropriate authorization to perform the operation.
+ Invoking the methods of <literal>PermissionManager</literal> requires that the currently-authenticated user
+ has the appropriate authorization to perform that management operation. The following table lists the required
+ permissions that the current user must have.
</para>
<table>
@@ -4665,7 +4693,8 @@
<title>Security Events</title>
<para>
- The following table describes a number of events (see <xref linkend="events"/>) raised by Seam Security.
+ The following table describes a number of events (see <xref linkend="events"/>) raised by Seam Security
+ in response to certain security-related events.
</para>
<table>
[View Less]
16 years, 7 months
Seam SVN: r8561 - in trunk/src/main/org/jboss/seam: security and 1 other directory.
by seam-commits@lists.jboss.org
Author: shane.bryzak(a)jboss.com
Date: 2008-08-03 21:12:40 -0400 (Sun, 03 Aug 2008)
New Revision: 8561
Added:
trunk/src/main/org/jboss/seam/annotations/security/Admin.java
trunk/src/main/org/jboss/seam/annotations/security/RoleCheck.java
Modified:
trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java
Log:
typesafe role checks
Added: trunk/src/main/org/jboss/seam/annotations/security/Admin.java
===================================================================
--- trunk/src/…
[View More]main/org/jboss/seam/annotations/security/Admin.java (rev 0)
+++ trunk/src/main/org/jboss/seam/annotations/security/Admin.java 2008-08-04 01:12:40 UTC (rev 8561)
@@ -0,0 +1,25 @@
+package org.jboss.seam.annotations.security;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the action method requires the user to be a member of the 'admin' role to invoke.
+ *
+ * @author Shane Bryzak
+ */
+@Target({TYPE, METHOD})
+@Documented
+@Retention(RUNTIME)
+@Inherited
+@RoleCheck
+public @interface Admin
+{
+
+}
Added: trunk/src/main/org/jboss/seam/annotations/security/RoleCheck.java
===================================================================
--- trunk/src/main/org/jboss/seam/annotations/security/RoleCheck.java (rev 0)
+++ trunk/src/main/org/jboss/seam/annotations/security/RoleCheck.java 2008-08-04 01:12:40 UTC (rev 8561)
@@ -0,0 +1,24 @@
+package org.jboss.seam.annotations.security;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Meta-annotation that designates an annotation as being a role,
+ * requiring a security check prior to invoking the annotated method or class
+ *
+ * @author Shane Bryzak
+ */
+@Target({ANNOTATION_TYPE})
+@Documented
+@Retention(RUNTIME)
+@Inherited
+public @interface RoleCheck
+{
+
+}
Modified: trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java 2008-08-03 22:08:34 UTC (rev 8560)
+++ trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java 2008-08-04 01:12:40 UTC (rev 8561)
@@ -12,6 +12,7 @@
import org.jboss.seam.annotations.intercept.InterceptorType;
import org.jboss.seam.annotations.security.PermissionCheck;
import org.jboss.seam.annotations.security.Restrict;
+import org.jboss.seam.annotations.security.RoleCheck;
import org.jboss.seam.async.AsynchronousInterceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
@@ -36,6 +37,7 @@
private Map<String, Object> methodRestrictions;
private Map<Integer,Set<String>> paramRestrictions;
+ private Set<String> roleRestrictions;
public void setExpression(String expression)
{
@@ -52,6 +54,16 @@
methodRestrictions.put(action, target);
}
+ public void addRoleRestriction(String role)
+ {
+ if (roleRestrictions == null)
+ {
+ roleRestrictions = new HashSet<String>();
+ }
+
+ roleRestrictions.add(role);
+ }
+
public void addParameterRestriction(int index, String action)
{
Set<String> actions = null;
@@ -102,6 +114,14 @@
}
}
}
+
+ if (roleRestrictions != null)
+ {
+ for (String role : roleRestrictions)
+ {
+ Identity.instance().checkRole(role);
+ }
+ }
}
}
}
@@ -178,6 +198,11 @@
}
}
}
+ if (annotation.annotationType().isAnnotationPresent(RoleCheck.class))
+ {
+ if (restriction == null) restriction = new Restriction();
+ restriction.addRoleRestriction(annotation.annotationType().getSimpleName().toLowerCase());
+ }
}
for (int i = 0; i < method.getParameterAnnotations().length; i++)
[View Less]
16 years, 7 months
Seam SVN: r8560 - in trunk/examples/excel/view: css and 1 other directory.
by seam-commits@lists.jboss.org
Author: danielc.roth
Date: 2008-08-03 18:08:34 -0400 (Sun, 03 Aug 2008)
New Revision: 8560
Added:
trunk/examples/excel/view/css/
trunk/examples/excel/view/css/screen.css
trunk/examples/excel/view/home.xhtml
Modified:
trunk/examples/excel/view/index.html
Log:
Added Excel Export "export by command button"-example.
Added: trunk/examples/excel/view/css/screen.css
===================================================================
--- trunk/examples/excel/view/css/screen.css …
[View More] (rev 0)
+++ trunk/examples/excel/view/css/screen.css 2008-08-03 22:08:34 UTC (rev 8560)
@@ -0,0 +1,22 @@
+body,div,dd,dt,dl,img,ul,ol,li,p,h1,h2,h3,h4,h5,form,hr,fieldset,span {
+ margin: 0;
+ padding: 0;
+ font-face: Verdana, Arial;
+}
+
+html {
+ height: 100%;
+ background-color: #FFFFFF;
+}
+
+span.header {
+ font-size: 22px;
+}
+
+td.left {
+ text-align: left;
+}
+
+td.right {
+ text-align: right;
+}
\ No newline at end of file
Copied: trunk/examples/excel/view/home.xhtml (from rev 8555, trunk/examples/excel/view/index.html)
===================================================================
--- trunk/examples/excel/view/home.xhtml (rev 0)
+++ trunk/examples/excel/view/home.xhtml 2008-08-03 22:08:34 UTC (rev 8560)
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:e="http://jboss.com/products/seam/excel"
+ xmlns:s="http://jboss.com/products/seam/taglib">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Microsoft® Excel® Export examples</title>
+<link href="css/screen.css" rel="stylesheet" type="text/css" />
+</head>
+<body id="excelHome">
+<f:view>
+
+ <h:outputText value="Microsoft® Excel® Export examples"
+ style="header"></h:outputText>
+ <br />
+ <br />
+
+ <h:outputLink value="jxl.seam">
+ <h:outputText>Export as Excel® spreadsheet</h:outputText>
+ </h:outputLink>
+ <br />
+
+ <h:outputLink value="jxl.seam">
+ <h:outputText>Export as comma separated file</h:outputText>
+ </h:outputLink>
+ <br />
+ <br />
+
+ <h:form id="excelExport">
+ <h:dataTable value="#{excelTest.people}" var="person" id="excelTable"
+ columnClasses="left, right">
+ <h:column>
+ <f:facet name="header">Name</f:facet>
+ <h:outputText value="#{person.name} #{person.lastName}"></h:outputText>
+ </h:column>
+ <h:column>
+ <f:facet name="header">Age</f:facet>
+ <h:outputText value="#{person.age}"></h:outputText>
+ </h:column>
+ </h:dataTable>
+ <h:commandLink value="Export table"
+ action="#{org.jboss.seam.excel.excelExporter.export('excelExport:excelTable')}" />
+ </h:form>
+
+</f:view>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/examples/excel/view/index.html
===================================================================
--- trunk/examples/excel/view/index.html 2008-08-03 21:22:02 UTC (rev 8559)
+++ trunk/examples/excel/view/index.html 2008-08-03 22:08:34 UTC (rev 8560)
@@ -1,16 +1,5 @@
-<html>
-<head>
-<title>Excel example</title>
-</head>
-<body>
-<a href="jxl.seam">Export to excel</a>
-<br />
-
-<a href="csv.seam">Export to csv</a>
-<br />
-
-Here wil be some more examples. Soon.
-<br />
-
-</body>
+<html>
+<head>
+ <meta http-equiv="Refresh" content="0; URL=home.seam">
+</head>
</html>
\ No newline at end of file
[View Less]
16 years, 7 months