sitemesh-2.4.1+dfsg.orig/0000755000175000017500000000000011340277634015162 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/LICENSE.txt0000644000175000017500000000465210125024250016774 0ustar twernertwerner==================================================================== The OpenSymphony Software License, Version 1.1 (this license is derived and fully compatible with the Apache Software License - see http://www.apache.org/LICENSE.txt) Copyright (c) 2001 The OpenSymphony Group. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "OpenSymphony" and "The OpenSymphony Group" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact license@opensymphony.com . 5. Products derived from this software may not be called "OpenSymphony" or "SiteMesh", nor may "OpenSymphony" or "SiteMesh" appear in their name, without prior written permission of the OpenSymphony Group. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================== sitemesh-2.4.1+dfsg.orig/CHANGES.txt0000644000175000017500000002373411157162354017002 0ustar twernertwerner-------------------------- -- Changes in 2.4.1 -- -------------------------- Fixed error in Page.getRequest() implementation. Now deprecated and removed from examples. -------------------------- -- Changes in 2.4 -- -------------------------- Mostly minor fixes. Bug fixes * [SIM-156] - Style Tags are stripped from * [SIM-172] - Unclosed quotes cause parsing problems * [SIM-180] - Header content after a tag gets treated as part of the body * [SIM-186] - SM should honor (at least) 304 (SC_NOT_MODIFIED) * [SIM-197] - when bodyContent is null,page:applyDecorator will throw NullPointerException * [SIM-198] - Deleted '<' in included content * [SIM-206] - XML Declaration in XHTML * [SIM-216] - NoSuchElementException in com.opensymphony.module.sitemesh.html.HTMLProcessor$1.currentBuffer(HTMLProcessor.java:44) * [SIM-241] - ArrayIndexOutofBounds exception in HTMLPageParser * [SIM-247] - OSDecoratorMapper == FAIL * [SIM-249] - tlds are broken - shortname does not conform to NMTOKEN Improvements * [SIM-151] - Allow the forced session creation to be optional * [SIM-174] - Simple (but measurable) Performance improvements for DefaultFactory and ConfigLoader * [SIM-192] - Need more user-friendly log error message when decorators.xml is missing Tasks * [SIM-229] - Update Sitemesh testsuite to use Cargo * [SIM-230] - Remove PageFilter, in favour of new SiteMeshFilter -------------------------- -- Changes in 2.3 -- -------------------------- Default parser has been moved from FastPageParser to HTMLPageParser. Misc bug fixes. Added components to enable decorators to be built with Tapestry (contributed by Erik Hatcher). -------------------------- -- Changes in 2.2.1 -- -------------------------- SiteMesh 2.2 introduced a few critical bugs, which have stopped it from being a seamless upgrade to many users. -- Fixed critical bugs -- * ClassNotFound: DefaultPageParser This is a class that no longer exists but may still lurk in sitemesh.xml if based on a 1.0 version. The config loader now just silently ignores this. * Head of content page chopped off This was caused by setContentType() always resetting the buffer, however sometimes setContentType() was called half way through a page (for instance by the Servlet engine whilst doing an include). -------------------------- -- Changes in 2.2 -- -------------------------- This release fixes a number of minor bugs, and no code changes are required from 2.1. The following improvements have been made: - The tag in decorators.xml now takes into account ServletPath, PathInfo and QueryString. - Overhaul of the main Servlet Filter to remove unnecessary complexity and more gracefully handle situations where the order of calls on the HttpServletResponse, PrintWriter and ServletOutputStream occur in an awkward order. JIRA issues fixed: - SIM-125 Internal Tomcat CGI throws NullPointerException. - SIM-128 HTML parser cannot handle attributes that span multiple lines. - SIM-86 Requests that use setHeader("Content-type") instead of setContentType() do not get decorated. - SIM-134 Not calling setContentType() caused NullPointerException. -------------------------- -- Changes in 2.1 -- -------------------------- This release fixes a number of major bugs, and no code changes are required from 2.0.1. We recommend all users upgrade. This release mainly contains application server compatibilty changes. Sitemesh is now compatible with more servers than ever before, and this release fixes the number one bug which was decoration of static pages under Tomcat. - The URI's for the SiteMesh tag libraries have changed: sitemesh-decorator becomes http://www.opensymphony.com/sitemesh/decorator sitemesh-page becomes http://www.opensymphony.com/sitemesh/page There have been no other changes to the tag library descriptors (.tld) files from the previous version, so you don't need to replace you existing ones. - Added VelocityDecoratorServlet (SIM-62; see 'Velocity Decorators' in the documentation and the example webapp). - The example webapp and blank webapp use Packaged Tag Libraries (specifying the URI of the taglib). - Hardened ConfigLoader to ignore whitespace inserted by XMLBuddy. - A new method, isPathExcluded(), has been added to the Factory interface (SIM-98) - There is no longer the concept of a default parser for unknown content types. JIRA issues fixed: - SIM-82 IllegalStateException when decorating static pages in Tomcat 4 & 5 - SIM-114 Sitemesh truncates content on non-decorated pages. - SIM-73 PageFilter is not final and you can now subclass the newly protected applyDecorator and parsePage methods - SIM-83 RequestDispatcher.forward() support - SIM-91 Remove singleton configuration - SIM-55 applyDecorator tag doesn't work on resin - SIM-73 Make PageFilter subclassable - SIM-89 mapping on deployment descriptor - SIM-97 Sitemesh captures the response even for non-parseable content - SIM-98 Add the ability to exclude content from being decorated -------------------------- -- Changes from 2.0 -- -------------------------- Chris Miller has been working like a demon on FastPageParser, and it's now as fast and efficient as it can get. To give you a rough idea, 2.0 is about 3 times faster than 1.5. 2.0.1 is about 5 times faster than 1.5. With regards to memory usage, it's basically been knocked down to be negligible. Previously (1.5), a 50k page parsed 250 times (separate instances strongly referenced, with an explicit gc call to remove temporary objects) used up 37mb. Currently, it uses 25mb (and it's no coincidence that 50k * 250 * 2 bytes per char == 25mb). - Minor DTD fix. - Updates to documentation and build process. - Added ParserGrinder to load test FastPageParser. -------------------------- -- Changes from 1.5 -- -------------------------- - SiteMesh now hosted at http://sitemesh.dev.java.net. - FastPageParser performance improvements. - DTD location has changed; now http://www.opensymphony.com/sitemesh/dtd/sitemesh_1_5_decorators.dtd - API change in Decorator (check your custom written Decorator classes): Added new method getRole() to enable role based decorators. - Updated documentation to align with new Opensymphony website. JIRA issues fixed: SIM-16 Tomcat IllegalStateException SIM-41 NoSuchMethodException with Orion SIM-2 Response bug on WebLogic 6.1 SIM-13 Tomcat4 throws IOException after response.sendRedirect() SIM-29 WebLogic 7 doesn't work SIM-40 Let properties be retrieved programatically SIM-27 Example apps don't work in Pramati SIM-17 Can't set headers from decorator page. SIM-8 body tag not correctly parsed SIM-56 Decorator taglibs allowed to contain body SIM-37 role based decorators SIM-46 Place TLDs in Jar file. -------------------------- -- Changes from 1.4.1 -- -------------------------- - API change in DecoratorMapper (check your custom written DecoratorMappers): before Decorator getNamedDecorator(String name); after Decorator getNamedDecorator(HttpServletRequest request, String name); - API change in Decorator (check your custom written Decorator classes): Added new method getURIPath() to enable cross web-app support for decorators. - New (shorter!) decorator xml format (backward compability is maintained), check above or the decorators.xml file in the /example/WEB-INF directory for an example. DTD: http://www.opensymphony.com/sitemesh/dtd/sitemesh_1_5_decorators.dtd - Default SiteMesh configuration if sitemesh.xml is not present. - When the request contains a Page object (under the key RequestConstants.PAGE) use this one (supports SiteMesh aware applications) so we don't need to parse. - EnvEntryDecoratorMapper: allows the reference to a web-app environment entry for the decorator name, and falls back to ConfigDecoratorMapper's behavior if no matching environment entry is found. - Cross web-app support for decorators by specifying . This will first try to get the decorator from anotherwebapp and fall back if not found. - Small performance improvements in RobotDecoratorMapper. - Some improvements to get SiteMesh working on different web containers. If you need to detect on which container your application is running, have a look at the com.opensymphony.module.sitemesh.util.Container class. - BUGFIX: DefaultDecorator returned bad init param - BUGFIX: small fixes to make SiteMesh work better on Tomcat - BUGFIX: javadoc fixes JIRA issues fixed: SIM-1 Finalize RE support in PathMapper SIM-3 Page filter strips tags SIM-4 PathMapper order is incorrect SIM-5 Add a mapper that uses environment entries SIM-6 When using the EnvEntryDecoratorMapper, decorations fail for html SIM-7 Parsing of body should strip doctype SIM-8 body tag not correctly parsed SIM-11 Parsing the text "<>" causes problems SIM-16 Define how charsets should work SIM-20 Cross web-app support for decorators SIM-21 FactoryException thrown when starting testsuite on WebLogic SIM-22 Create template web-app SIM-23 Distribution bundle SIM-32 A smaller than sign (<) in javascript fails -------------------------- -- Changes from 1.4 -- -------------------------- - complete support for WebLogic 6.1 / 7 - complete support for Jetty 4 - internal optimizations to filter - BUGFIX: StringIndexOutOfBoundsException in RobotDecoratorMapper -------------------------- -- Changes from 1.3 -- -------------------------- - changed package structure from com.sitemesh to com.opensymphony.module.sitemesh - many performance optimizations in FastPageParser - various bug fixes and small performance improvements - BUGFIX: memory leak in PageFilter - BUGFIX: meta http-equiv tags are now added as properties with prefix meta.http-equiv.x where x is the value of the http-equiv attribute (eg refresh) - BUGFIX: the configuration files are not case-sensitive anymore ������������������������������������sitemesh-2.4.1+dfsg.orig/README.txt�����������������������������������������������������������������0000644�0001750�0001750�00000013122�11157162236�016654� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������************************************* ** OpenSymphony SiteMesh 2.4.1 ** ************************************* SiteMesh is a web-page layout system that can be used to abstract common look and feel from the functionality of a web-application and to assemble large webpages from smaller components. Pages and components can have meta-data extracted from them (such as body, title and meta-tags) which can be used by decorators (skins) that are applied. SiteMesh won't tread on your toes or force you to work in a certain way (except for cleaner) - you install and carry on working as before. It seamlessly fits in with existing frameworks. Forget the hype - just try it! You'll be impressed with how it can simplify things. -------------------------- -- Obtaining -- -------------------------- The latest version of SiteMesh can be obtained from: http://www.opensymphony.com/sitemesh/ -------------------------- -- Requirements -- -------------------------- SiteMesh requires a Java Servlet container conforming to the Servlet 2.3 specification. Versions prior to 2.3 are not enough. Currently known containers that support this and SiteMesh was tested with: * Orion 1.5.4 and up - http://www.orionserver.com * Tomcat 4.0, 4.1 and 5.0.19 - http://jakarta.apache.org/tomcat * Resin 2.1.11, 2.1.12, 2.1.13 and 3.0.7 - http://www.caucho.com * Oracle OC4J 2 - http://www.oracle.com * WebLogic 7.0 SP2, 8.1 and 8.1 SP2 - http://www.bea.com * WebSphere 5.0 - http://www.ibm.com * Jetty 4.2.20 - http://jetty.mortbay.org -------------------------- -- Installation -- -------------------------- * Copy sitemesh-@VERSION@.jar to the WEB-INF/lib/ directory of your web-app. * OPTIONAL: Copy sitemesh.xml to the WEB-INF/ directory if you need to specify a custom decorator mapper configuration then the default configuration. * Add the following to WEB-INF/web.xml: <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> * ORION USERS ONLY. For performance reasons, Orion does not auto-load tab library descriptors from Jars by default. To get passed this you will also have to copy sitemesh-decorator.tld and sitemesh-page.tld to WEB-INF/lib and add the following to WEB-INF/web.xml: <taglib> <taglib-uri>http://www.opensymphony.com/sitemesh/decorator</taglib-uri> <taglib-location>/WEB-INF/lib/sitemesh-decorator.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://www.opensymphony.com/sitemesh/page</taglib-uri> <taglib-location>/WEB-INF/lib/sitemesh-page.tld</taglib-location> </taglib> -------------------------- -- Getting started -- -------------------------- Ok, let's assume you have some basic JSPs already on the site. These should contain vanilla HTML. If you don't, here's a JSP to get you started (test.jsp). <html> <head> <title>Hello world</title> </head> <body> <p>Today is <%= new java.util.Date() %>.</p> </body> </html> Once you have some content (preferably more imaginative than the example above), a decorator should be created (decorator.jsp). <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <html> <head> <title>My Site - <decorator:title default="Welcome!" /></title> <decorator:head /> </head> <body> <decorator:body /> </body> </html> Now you need tell SiteMesh about that decorator and when to use it. Create the file WEB-INF/decorators.xml: <decorators> <decorator name="mydecorator" page="/decorator.jsp"> <pattern>/*</pattern> </decorator> </decorators> Access your original JSP (test.jsp) though your web-browser and it should look pretty normal. Now if you add some styling to your decorator it shall automatically be applied to all the other pages in your web-app. You can define as many decorators as you want in decorators.xml. Example: <decorators defaultdir="/decorators"> <decorator name="default" page="default.jsp"> <pattern>/*</pattern> </decorator> <decorator name="anotherdecorator" page="decorator2.jsp"> <pattern>/subdir/*</pattern> </decorator> <decorator name="htmldecorator" page="html.jsp"> <pattern>*.html</pattern> <pattern>*.htm</pattern> </decorator> <decorator name="none"> <!-- These files will not get decorated. --> <pattern>/anotherdir/*</pattern> </decorator> </decorators> -------------------------- -- Further support -- -------------------------- You get the idea. Play around. See the SiteMesh website for full documentation. http://www.opensymphony.com/sitemesh/ -------------------------- -- Credits -- -------------------------- Thank these guys: * Mathias Bogaert <NOSPAMm.bogaert@memenco.com> * Mike Cannon-Brookes <mikeNOSPAM@atlassian.com> * Victor Salaman <salamanNOSPAM@teknos.com> * Joseph Ottinger <joeoNOSPAM@adjacency.org> * Hani Suleiman <NOSPAMfate@users.sourceforge.net> * Scott Farquhar <scottNOSPAM@atlassian.com> - Joe Walnes <joe@NOSPAMtruemesh.com> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/build.xml������������������������������������������������������������������0000644�0001750�0001750�00000016554�10446416452�017015� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0"?> <project name="sitemesh" default="jar"> <property name="build.compiler" value="modern" /> <property file="build.properties"/> <!-- Classpath --> <path id="cp"> <fileset dir="lib"> <include name="**/*.jar"/> </fileset> </path> <target name="jflex" unless="lexer.uptodate" description="Generate Lexer class"> <echo message="Generating HTML lexer using JFlex"/> <mkdir dir="build/java"/> <java classpath="lib/jflex.jar" classname="JFlex.Main" fork="yes"> <arg value="-d"/> <arg value="build/java/com/opensymphony/module/sitemesh/html/tokenizer"/> <arg value="src/java/com/opensymphony/module/sitemesh/html/tokenizer/lexer.flex"/> </java> <delete file="build/java/com/opensymphony/module/sitemesh/html/tokenizer/Lexer.java~"/> </target> <target name="hostedqa" depends="example"> <taskdef resource="hostedqatasks" classpathref="cp"/> <upload file="dist/${name}-example.war" account="sitemesh" email="${hostedqa.email}" password="${hostedqa.password}" resourceId="18"/> <playsuite suiteId="16" clientConfigs="17" appConfigs="12" account="sitemesh" email="${hostedqa.email}" password="${hostedqa.password}"/> </target> <target name="compile" description="Compile Java"> <!-- Determine if lexer needs regenerating --> <uptodate property="lexer.uptodate" srcfile="src/java/com/opensymphony/module/sitemesh/html/tokenizer/lexer.flex" targetfile="build/java/com/opensymphony/module/sitemesh/html/tokenizer/Lexer.java"/> <antcall target="jflex"/> <mkdir dir="build/classes"/> <javac destdir="build/classes" classpathref="cp" optimize="${compile.optimize}" debug="${compile.debug}" nowarn="${compile.nowarn}" deprecation="${compile.deprecation}" source="1.3" target="1.3" > <src path="src/java"/> <src path="build/java"/> </javac> </target> <target name="test" depends="compile" description="Run all unit tests"> <mkdir dir="build/test-classes"/> <mkdir dir="build/test-results"/> <javac srcdir="src/test" destdir="build/test-classes" classpathref="cp" classpath="build/classes"/> <taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask" classpathref="cp"/> <echo message="Running unit tests..."/> <junit printsummary="no" haltonfailure="yes" fork="yes" forkmode="once" dir="."> <classpath refid="cp"/> <classpath> <pathelement location="build/classes"/> <pathelement location="build/test-classes"/> </classpath> <formatter type="brief" usefile="no"/> <formatter type="xml"/> <batchtest todir="build/test-results"> <fileset dir="src/test"> <include name="**/*Test.java"/> </fileset> </batchtest> </junit> </target> <target name="javadocs" description="Generates JavaDoc"> <mkdir dir="dist/docs/api"/> <javadoc sourcepath="src/java" destdir="dist/docs/api" stylesheetfile="docs/api.css" packagenames="com.opensymphony.*" classpathref="cp" author="true" version="true" private="true" use="true" windowTitle="${Name} ${version} API" doctitle="${Name} ${version} API" footer="&lt;a href=&quot;http://www.opensymphony.com/sitemesh/&quot;&gt;www.opensymphony.com/sitemesh/&lt;/a&gt;"> <link href="http://java.sun.com/j2se/1.4.2/docs/api/"/> <link href="http://java.sun.com/products/servlet/2.3/javadoc/"/> <link href="http://jakarta.apache.org/velocity/api/"/> <link href="http://jakarta.apache.org/velocity/tools/javadoc/"/> <link href="http://freemarker.sourceforge.net/docs/api/"/> </javadoc> </target> <target name="docs" depends="javadocs"> <copy todir="dist/docs"> <fileset dir="docs" excludes="*.css"/> </copy> <mkdir dir="dist/docs/dtd"/> <copy todir="dist/docs" file="README.txt"/> <copy todir="dist/docs" file="CHANGES.txt"/> <copy todir="dist/docs/dtd"> <fileset dir="src/etc/dtd"/> </copy> <replace dir="dist/docs" token="@VERSION@" value="${version}"/> </target> <target name="jar" depends="compile"> <mkdir dir="dist"/> <copy todir="build/classes"> <fileset dir="src/java" excludes="**/*.java,**/*.flex"/> </copy> <jar jarfile="dist/${name}-${version}.jar" basedir="build/classes" excludes="**/servlets/**"> <metainf dir="src/etc/tld/jsp1.2" includes="*.tld"/> </jar> </target> <target name="blank" depends="jar" description="Builds simple web-app to get started with SiteMesh"> <mkdir dir="dist"/> <war warfile="dist/${name}-blank.war" webxml="src/etc/blank/WEB-INF/web.xml"> <fileset dir="src/etc/blank"> <exclude name="WEB-INF/web.xml"/> </fileset> <lib dir="dist"> <include name="${name}-${version}.jar"/> </lib> <lib dir="src/etc/tld"> <include name="sitemesh*.tld" /> </lib> </war> </target> <target name="example" depends="jar" description="Builds sample web-app"> <mkdir dir="build/example-temp"/> <copy todir="build/example-temp"> <fileset dir="src/example-webapp"/> </copy> <mkdir dir="dist"/> <war warfile="dist/${name}-example.war" webxml="src/example-webapp/WEB-INF/web.xml"> <fileset dir="build/example-temp"> <exclude name="WEB-INF/web.xml"/> </fileset> <lib dir="dist"> <include name="${name}-${version}.jar"/> </lib> <lib dir="lib"> <include name="commons-*.jar"/> <include name="velocity-*.jar"/> <include name="freemarker.jar"/> </lib> <lib dir="src/etc/tld"> <include name="sitemesh*.tld" /> </lib> </war> </target> <target name="dist" depends="clean, test, jar, docs, blank, example" description="Builds distribution archives"> <zip zipfile="dist/${name}-${version}.zip"> <zipfileset dir="."> <include name="build.xml"/> <include name="build.properties"/> <include name="LICENSE.txt"/> <include name="CHANGES.txt"/> <include name="README.txt"/> <include name="src/**"/> <include name="lib/**"/> </zipfileset> <zipfileset dir="build"> <include name="${name}-${version}.jar"/> <include name="${name}-example.war"/> <include name="${name}-blank.war"/> </zipfileset> <zipfileset dir="dist/docs" prefix="docs"/> </zip> </target> <target name="clean" description="Removes all build artifacts"> <delete dir="build"/> <delete dir="dist"/> </target> </project> ����������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/lib/�����������������������������������������������������������������������0000755�0001750�0001750�00000000000�11157130030�015710� 5����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�11157130004�016073� 5����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/features.html���������������������������������������������������������0000644�0001750�0001750�00000003373�11157162710�020616� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>SiteMesh Feature List</title> </head> <body> <h4>Java</h4> <ul> <li>Built with Java, the industry standard for enterprise applications.</li> <li>Conform to the <a href="http://jcp.org/aboutJava/communityprocess/first/jsr053/index.html">Java Servlet 2.3 specification</a> (final release).</li> </ul> <h4>Open Source</h4> <ul> <li>Open source software distributed under the OpenSymphony Software License (derived and fully compatible with the <a href="http://www.apache.org/LICENSE.txt" target="_blank">Apache Software License</a>).</li> </ul> <h4>Simple</h4> <ul> <li>Non-technical users can now create professional Web pages while effortlessly maintaining a consistent look-and-feel across your web-application.</li> <li>Dramatically reduces the time needed to develop and maintain a web-application.</li> <li>Eliminates the need to create multiple web-apps for different audiences by allowing the decorator to be changed according to the useragent or a request parameter(s) (e.g. printable version).</li> </ul> <h4>Very flexible</h4> <ul> <li>A printable version of your entire site is only a matter of minutes!</li> <li>Map a decorator based on a cookie value.</li> <li>With the <a href="api/com/opensymphony/module/sitemesh/mapper/RobotDecoratorMapper.html">RobotDecoratorMapper</a> you can apply a special decorator to all your pages when they are indexed by a search engine robot (also known as spider, crawler). Currently supports over 200 robots.</li> </ul> <h4>Integrated</h4> <ul> <li>Supports <a href="velocity-decorators.html">Velocity</a> and <a href="freemarker-decorators.html">Freemarker</a> for writing decorators.</li> </ul> </body> </html>���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/api/������������������������������������������������������������������0000755�0001750�0001750�00000000000�11157162710�016655� 5����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/velocity-decorators.html����������������������������������������������0000644�0001750�0001750�00000011120�11157162710�022766� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>Velocity Decorators</title> </head> <body> As of SiteMesh 2.0.2 <a href="http://jakarta.apache.org/velocity/">Velocity</a> (.vm) decorators are supported. <p>Here is an example of how such a decorator (e.g. /decorators/main.vm) might look like:</p> <pre style="border: 1px solid #999999; padding: 5px"> #parse ("/includes/decorators/header.vm") &lt;h2&gt;<b>$title</b>&lt;/h2&gt; <b>$head</b> &lt;img src="<b>$base</b>/images/logo.gif" border="0"&gt; &lt;td valign="top" class="body"&gt; &lt;div class="header"&gt; &lt;span class="pagetitle"&gt;<b>$title</b>&lt;/span&gt; &lt;/div&gt; <b>$body</b> &lt;/td&gt; #parse ("/includes/decorators/footer.vm") </pre> <h3>Installation</h3> <ul> <li>Download <a href="http://jakarta.apache.org/velocity/">Velocity</a> 1.3.1 or higher and copy it into <b><code>[web-app]/WEB-INF/lib</code></b>. The SiteMesh distribution comes with <b>velocity-dep-1.3.1.jar</b>.</p></li> <li>Download <a href="http://jakarta.apache.org/velocity/tools/">VelocityTools</a> 1.1 and copy it into <b><code>[web-app]/WEB-INF/lib</code></b>. The SiteMesh distribution comes with <b>velocity-tools-view-1.1.jar</b>.</p></li> <li>Download <a href="http://jakarta.apache.org/commons/collections/">Commons Collections</a> 2.1 or higher and copy it into <b><code>[web-app]/WEB-INF/lib</code></b>. The SiteMesh distribution comes with <b>commons-collections.jar</b>.</p></li> <li>Add the following to <b><code>[web-app]/WEB-INF/web.xml</code></b> within the <b><code>&lt;web-app&gt;</code></b> tag:</li> </ul> <pre style="border: 1px solid #999999; padding: 5px"> &lt;servlet&gt; &lt;servlet-name&gt;<b>sitemesh-velocity</b>&lt;/servlet-name&gt; &lt;servlet-class&gt;<b>com.opensymphony.module.sitemesh.velocity.VelocityDecoratorServlet</b>&lt;/servlet-class&gt; &lt;/servlet&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;sitemesh-velocity&lt;/servlet-name&gt; &lt;url-pattern&gt;<b>*.vm</b>&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; </pre> <ul> <li>Modify <b><code>decorators.xml</code></b> to reference a .vm decorator.</li> </ul> <p>A working example is included with the SiteMesh distribution, under the <a href="https://sitemesh.dev.java.net/source/browse/sitemesh/src/example-webapp/">src/example-webapp</a> directory.</p> <h3>Context</h3> VelocityDecoratorServlet puts some things into the context object that you should be aware of: <table border="0" cellspacing="10"> <tr> <td valign="top"><strong>$request</strong> (from <a href="http://jakarta.apache.org/velocity/tools/javadoc/org/apache/velocity/tools/view/servlet/VelocityViewServlet.html">VelocityViewServlet</a>)</td> <td>The HttpServletRequest object</td> </tr> <tr> <td valign="top"><strong>$response</strong> (from <a href="http://jakarta.apache.org/velocity/tools/javadoc/org/apache/velocity/tools/view/servlet/VelocityViewServlet.html">VelocityViewServlet</a>)</td> <td>The HttpServletResponse object</td> </tr> <tr> <td valign="top"><strong>$session</strong> (from <a href="http://jakarta.apache.org/velocity/tools/javadoc/org/apache/velocity/tools/view/servlet/VelocityViewServlet.html">VelocityViewServlet</a>)</td> <td>The HttpSession object</td> </tr> <tr> <td valign="top"><strong>$application</strong> (from <a href="http://jakarta.apache.org/velocity/tools/javadoc/org/apache/velocity/tools/view/servlet/VelocityViewServlet.html">VelocityViewServlet</a>)</td> <td>The ServletContext object</td> </tr> <tr> <td valign="top"><strong>$base</strong></td> <td>request.getContextPath()</td> </tr> <tr> <td valign="top"><strong>$title</strong></td> <td>Parsed page title (&lt;title&gt;...&lt;title&gt;)</td> </tr> <tr> <td valign="top"><strong>$head</strong></td> <td>Parsed page head</td> </tr> <tr> <td valign="top"><strong>$body</strong></td> <td>Parsed page body</td> </tr> <tr> <td valign="top"><strong>$page</strong></td> <td>SiteMesh's internal Page object</td> </tr> <tr> <td valign="top"><strong>Anything else</strong></td> <td>Search for the attribute by that name in the request, session and application scopes</td> </tr> </table> </body> </html>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/flow.html�������������������������������������������������������������0000644�0001750�0001750�00000000375�11157162710�017746� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>SiteMesh Flow Diagram</title> </head> <body> <p> This diagram shows the flow of control within SiteMesh. <p> <img src="images/flowdiagram.gif" width="614" height="693" border="0" alt=""> </p> </body> </html> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/CHANGES.txt�����������������������������������������������������������0000644�0001750�0001750�00000023734�11157162710�017726� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-------------------------- -- Changes in 2.4.1 -- -------------------------- Fixed error in Page.getRequest() implementation. Now deprecated and removed from examples. -------------------------- -- Changes in 2.4 -- -------------------------- Mostly minor fixes. Bug fixes * [SIM-156] - Style Tags are stripped from <HEAD> * [SIM-172] - Unclosed quotes cause parsing problems * [SIM-180] - Header content after a <content> tag gets treated as part of the body * [SIM-186] - SM should honor (at least) 304 (SC_NOT_MODIFIED) * [SIM-197] - when bodyContent is null,page:applyDecorator will throw NullPointerException * [SIM-198] - Deleted '<' in included content * [SIM-206] - XML Declaration in XHTML * [SIM-216] - NoSuchElementException in com.opensymphony.module.sitemesh.html.HTMLProcessor$1.currentBuffer(HTMLProcessor.java:44) * [SIM-241] - ArrayIndexOutofBounds exception in HTMLPageParser * [SIM-247] - OSDecoratorMapper == FAIL * [SIM-249] - tlds are broken - shortname does not conform to NMTOKEN Improvements * [SIM-151] - Allow the forced session creation to be optional * [SIM-174] - Simple (but measurable) Performance improvements for DefaultFactory and ConfigLoader * [SIM-192] - Need more user-friendly log error message when decorators.xml is missing Tasks * [SIM-229] - Update Sitemesh testsuite to use Cargo * [SIM-230] - Remove PageFilter, in favour of new SiteMeshFilter -------------------------- -- Changes in 2.3 -- -------------------------- Default parser has been moved from FastPageParser to HTMLPageParser. Misc bug fixes. Added components to enable decorators to be built with Tapestry (contributed by Erik Hatcher). -------------------------- -- Changes in 2.2.1 -- -------------------------- SiteMesh 2.2 introduced a few critical bugs, which have stopped it from being a seamless upgrade to many users. -- Fixed critical bugs -- * ClassNotFound: DefaultPageParser This is a class that no longer exists but may still lurk in sitemesh.xml if based on a 1.0 version. The config loader now just silently ignores this. * Head of content page chopped off This was caused by setContentType() always resetting the buffer, however sometimes setContentType() was called half way through a page (for instance by the Servlet engine whilst doing an include). -------------------------- -- Changes in 2.2 -- -------------------------- This release fixes a number of minor bugs, and no code changes are required from 2.1. The following improvements have been made: - The <excludes> tag in decorators.xml now takes into account ServletPath, PathInfo and QueryString. - Overhaul of the main Servlet Filter to remove unnecessary complexity and more gracefully handle situations where the order of calls on the HttpServletResponse, PrintWriter and ServletOutputStream occur in an awkward order. JIRA issues fixed: - SIM-125 Internal Tomcat CGI throws NullPointerException. - SIM-128 HTML parser cannot handle attributes that span multiple lines. - SIM-86 Requests that use setHeader("Content-type") instead of setContentType() do not get decorated. - SIM-134 Not calling setContentType() caused NullPointerException. -------------------------- -- Changes in 2.1 -- -------------------------- This release fixes a number of major bugs, and no code changes are required from 2.0.1. We recommend all users upgrade. This release mainly contains application server compatibilty changes. Sitemesh is now compatible with more servers than ever before, and this release fixes the number one bug which was decoration of static pages under Tomcat. - The URI's for the SiteMesh tag libraries have changed: sitemesh-decorator becomes http://www.opensymphony.com/sitemesh/decorator sitemesh-page becomes http://www.opensymphony.com/sitemesh/page There have been no other changes to the tag library descriptors (.tld) files from the previous version, so you don't need to replace you existing ones. - Added VelocityDecoratorServlet (SIM-62; see 'Velocity Decorators' in the documentation and the example webapp). - The example webapp and blank webapp use Packaged Tag Libraries (specifying the URI of the taglib). - Hardened ConfigLoader to ignore whitespace inserted by XMLBuddy. - A new method, isPathExcluded(), has been added to the Factory interface (SIM-98) - There is no longer the concept of a default parser for unknown content types. JIRA issues fixed: - SIM-82 IllegalStateException when decorating static pages in Tomcat 4 & 5 - SIM-114 Sitemesh truncates content on non-decorated pages. - SIM-73 PageFilter is not final and you can now subclass the newly protected applyDecorator and parsePage methods - SIM-83 RequestDispatcher.forward() support - SIM-91 Remove singleton configuration - SIM-55 applyDecorator tag doesn't work on resin - SIM-73 Make PageFilter subclassable - SIM-89 <url-pattern> mapping on deployment descriptor - SIM-97 Sitemesh captures the response even for non-parseable content - SIM-98 Add the ability to exclude content from being decorated -------------------------- -- Changes from 2.0 -- -------------------------- Chris Miller has been working like a demon on FastPageParser, and it's now as fast and efficient as it can get. To give you a rough idea, 2.0 is about 3 times faster than 1.5. 2.0.1 is about 5 times faster than 1.5. With regards to memory usage, it's basically been knocked down to be negligible. Previously (1.5), a 50k page parsed 250 times (separate instances strongly referenced, with an explicit gc call to remove temporary objects) used up 37mb. Currently, it uses 25mb (and it's no coincidence that 50k * 250 * 2 bytes per char == 25mb). - Minor DTD fix. - Updates to documentation and build process. - Added ParserGrinder to load test FastPageParser. -------------------------- -- Changes from 1.5 -- -------------------------- - SiteMesh now hosted at http://sitemesh.dev.java.net. - FastPageParser performance improvements. - DTD location has changed; now http://www.opensymphony.com/sitemesh/dtd/sitemesh_1_5_decorators.dtd - API change in Decorator (check your custom written Decorator classes): Added new method getRole() to enable role based decorators. - Updated documentation to align with new Opensymphony website. JIRA issues fixed: SIM-16 Tomcat IllegalStateException SIM-41 NoSuchMethodException with Orion SIM-2 Response bug on WebLogic 6.1 SIM-13 Tomcat4 throws IOException after response.sendRedirect() SIM-29 WebLogic 7 doesn't work SIM-40 Let properties be retrieved programatically SIM-27 Example apps don't work in Pramati SIM-17 Can't set headers from decorator page. SIM-8 body tag not correctly parsed SIM-56 Decorator taglibs allowed to contain body SIM-37 role based decorators SIM-46 Place TLDs in Jar file. -------------------------- -- Changes from 1.4.1 -- -------------------------- - API change in DecoratorMapper (check your custom written DecoratorMappers): before Decorator getNamedDecorator(String name); after Decorator getNamedDecorator(HttpServletRequest request, String name); - API change in Decorator (check your custom written Decorator classes): Added new method getURIPath() to enable cross web-app support for decorators. - New (shorter!) decorator xml format (backward compability is maintained), check above or the decorators.xml file in the /example/WEB-INF directory for an example. DTD: http://www.opensymphony.com/sitemesh/dtd/sitemesh_1_5_decorators.dtd - Default SiteMesh configuration if sitemesh.xml is not present. - When the request contains a Page object (under the key RequestConstants.PAGE) use this one (supports SiteMesh aware applications) so we don't need to parse. - EnvEntryDecoratorMapper: allows the reference to a web-app environment entry for the decorator name, and falls back to ConfigDecoratorMapper's behavior if no matching environment entry is found. - Cross web-app support for decorators by specifying <decorator ... webapp="anotherwebapp"/>. This will first try to get the decorator from anotherwebapp and fall back if not found. - Small performance improvements in RobotDecoratorMapper. - Some improvements to get SiteMesh working on different web containers. If you need to detect on which container your application is running, have a look at the com.opensymphony.module.sitemesh.util.Container class. - BUGFIX: DefaultDecorator returned bad init param - BUGFIX: small fixes to make SiteMesh work better on Tomcat - BUGFIX: javadoc fixes JIRA issues fixed: SIM-1 Finalize RE support in PathMapper SIM-3 Page filter strips <xmp> tags SIM-4 PathMapper order is incorrect SIM-5 Add a mapper that uses environment entries SIM-6 When using the EnvEntryDecoratorMapper, decorations fail for html SIM-7 Parsing of body should strip doctype SIM-8 body tag not correctly parsed SIM-11 Parsing the text "<>" causes problems SIM-16 Define how charsets should work SIM-20 Cross web-app support for decorators SIM-21 FactoryException thrown when starting testsuite on WebLogic SIM-22 Create template web-app SIM-23 Distribution bundle SIM-32 A smaller than sign (<) in javascript fails -------------------------- -- Changes from 1.4 -- -------------------------- - complete support for WebLogic 6.1 / 7 - complete support for Jetty 4 - internal optimizations to filter - BUGFIX: StringIndexOutOfBoundsException in RobotDecoratorMapper -------------------------- -- Changes from 1.3 -- -------------------------- - changed package structure from com.sitemesh to com.opensymphony.module.sitemesh - many performance optimizations in FastPageParser - various bug fixes and small performance improvements - BUGFIX: memory leak in PageFilter - BUGFIX: meta http-equiv tags are now added as properties with prefix meta.http-equiv.x where x is the value of the http-equiv attribute (eg refresh) - BUGFIX: the configuration files are not case-sensitive anymore ������������������������������������sitemesh-2.4.1+dfsg.orig/docs/README.txt������������������������������������������������������������0000644�0001750�0001750�00000013116�11157162710�017604� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������************************************* ** OpenSymphony SiteMesh 2.4.1 ** ************************************* SiteMesh is a web-page layout system that can be used to abstract common look and feel from the functionality of a web-application and to assemble large webpages from smaller components. Pages and components can have meta-data extracted from them (such as body, title and meta-tags) which can be used by decorators (skins) that are applied. SiteMesh won't tread on your toes or force you to work in a certain way (except for cleaner) - you install and carry on working as before. It seamlessly fits in with existing frameworks. Forget the hype - just try it! You'll be impressed with how it can simplify things. -------------------------- -- Obtaining -- -------------------------- The latest version of SiteMesh can be obtained from: http://www.opensymphony.com/sitemesh/ -------------------------- -- Requirements -- -------------------------- SiteMesh requires a Java Servlet container conforming to the Servlet 2.3 specification. Versions prior to 2.3 are not enough. Currently known containers that support this and SiteMesh was tested with: * Orion 1.5.4 and up - http://www.orionserver.com * Tomcat 4.0, 4.1 and 5.0.19 - http://jakarta.apache.org/tomcat * Resin 2.1.11, 2.1.12, 2.1.13 and 3.0.7 - http://www.caucho.com * Oracle OC4J 2 - http://www.oracle.com * WebLogic 7.0 SP2, 8.1 and 8.1 SP2 - http://www.bea.com * WebSphere 5.0 - http://www.ibm.com * Jetty 4.2.20 - http://jetty.mortbay.org -------------------------- -- Installation -- -------------------------- * Copy sitemesh-2.4.1.jar to the WEB-INF/lib/ directory of your web-app. * OPTIONAL: Copy sitemesh.xml to the WEB-INF/ directory if you need to specify a custom decorator mapper configuration then the default configuration. * Add the following to WEB-INF/web.xml: <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> * ORION USERS ONLY. For performance reasons, Orion does not auto-load tab library descriptors from Jars by default. To get passed this you will also have to copy sitemesh-decorator.tld and sitemesh-page.tld to WEB-INF/lib and add the following to WEB-INF/web.xml: <taglib> <taglib-uri>http://www.opensymphony.com/sitemesh/decorator</taglib-uri> <taglib-location>/WEB-INF/lib/sitemesh-decorator.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://www.opensymphony.com/sitemesh/page</taglib-uri> <taglib-location>/WEB-INF/lib/sitemesh-page.tld</taglib-location> </taglib> -------------------------- -- Getting started -- -------------------------- Ok, let's assume you have some basic JSPs already on the site. These should contain vanilla HTML. If you don't, here's a JSP to get you started (test.jsp). <html> <head> <title>Hello world</title> </head> <body> <p>Today is <%= new java.util.Date() %>.</p> </body> </html> Once you have some content (preferably more imaginative than the example above), a decorator should be created (decorator.jsp). <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <html> <head> <title>My Site - <decorator:title default="Welcome!" /></title> <decorator:head /> </head> <body> <decorator:body /> </body> </html> Now you need tell SiteMesh about that decorator and when to use it. Create the file WEB-INF/decorators.xml: <decorators> <decorator name="mydecorator" page="/decorator.jsp"> <pattern>/*</pattern> </decorator> </decorators> Access your original JSP (test.jsp) though your web-browser and it should look pretty normal. Now if you add some styling to your decorator it shall automatically be applied to all the other pages in your web-app. You can define as many decorators as you want in decorators.xml. Example: <decorators defaultdir="/decorators"> <decorator name="default" page="default.jsp"> <pattern>/*</pattern> </decorator> <decorator name="anotherdecorator" page="decorator2.jsp"> <pattern>/subdir/*</pattern> </decorator> <decorator name="htmldecorator" page="html.jsp"> <pattern>*.html</pattern> <pattern>*.htm</pattern> </decorator> <decorator name="none"> <!-- These files will not get decorated. --> <pattern>/anotherdir/*</pattern> </decorator> </decorators> -------------------------- -- Further support -- -------------------------- You get the idea. Play around. See the SiteMesh website for full documentation. http://www.opensymphony.com/sitemesh/ -------------------------- -- Credits -- -------------------------- Thank these guys: * Mathias Bogaert <NOSPAMm.bogaert@memenco.com> * Mike Cannon-Brookes <mikeNOSPAM@atlassian.com> * Victor Salaman <salamanNOSPAM@teknos.com> * Joseph Ottinger <joeoNOSPAM@adjacency.org> * Hani Suleiman <NOSPAMfate@users.sourceforge.net> * Scott Farquhar <scottNOSPAM@atlassian.com> - Joe Walnes <joe@NOSPAMtruemesh.com> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/decorators.html�������������������������������������������������������0000644�0001750�0001750�00000016767�11157162710�021160� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>Building SiteMesh Decorators</title> </head> <body> <p>Once SiteMesh has been <a href="install.html">installed and configured</a>, you can begin writing decorators for your web application.</p> <h3>Introduction</h3> Decorators are the pages that "decorate" the original, requested page (the page that is <a href="flow.html">handed to the SiteMesh filter from the web container</a>). Most (HTML) decorators are a combination of: <ul> <li>meta tags (keywords, description, author)</li> <li>stylesheet (CSS)</li> <li>header</li> <li>navigation</li> <li>footer</li> <li>copyright notice</li> </ul> First, define what different navigation/layout schemes you need. For example: Do I need a default decorator (a standard one for all pages)? Do I have a special layout for the index page? Is the header needed for my documentation files? Do I need printable version of my website? <h3>Web Application Structure</h3> <p>Here is an example structure of a web application. This is not needed for SiteMesh to work.</p> <table align="center" width="80%" cellpadding="4" style="background: #eeeeee; border: 1 black solid;"> <tr> <td width="15%"><b><code>/decorators</code></b></td> <td><p>Directory containing all decorator files (e.g. <code>main.jsp</code>, <code>printable.jsp</code>).</p></td> </tr> <tr> <td width="15%"><b><code>/includes</code></b></td> <td><p>Directory containing all files to be included into other files (e.g. <code>header.jsp</code>, <code>footer.jsp</code>, <code>copyright.jsp</code>).</p></td> </tr> <tr> <td width="15%"><b><code>/images</code></b></td> <td><p>Directory containing all images (e.g. <code>background.gif</code>, <code>logo.gif</code>).</p></td> </tr> <tr> <td width="15%"><b><code>/styles</code></b></td> <td><p>Directory containing all .CSS styles (e.g. <code>ie4.css</code>, <code>ns4.css</code>).</p></td> </tr> <tr> <td width="15%"><b><code>/scripts</code></b></td> <td><p>Directory containing all scripts (JavaScript, VBScript files).</p></td> </tr> </table> <p>Good practices:</p> <ul> <li>Define a stylesheet to use in the entire application and include it using <a href="style.jsp.txt">this script</a>.</li> <li>Use includes in your decorators (e.g. <code>includes/navigation.jsp</code>, <code>includes/style.jsp</code>).</li> <li>Try not to refer to the absolute root ("<code>/</code>") path. Use <code>&lt;%=request.getContextPath()%&gt;/</code> instead. This will make life easier when moving your web application under another context path.</li> <li>Making your decorators compatible with multiple browsers (IE, Mozilla, Opera, ...) will (probably) make your entire application (all decorated pages) compatible.</li> <li>Be careful when using frames, because decorators may NOT be applied to frames (<a href="api/com/opensymphony/module/sitemesh/mapper/FrameSetDecoratorMapper.html">FrameSetDecoratorMapper</a>).</li> </ul> <h3>My First Decorator</h3> Basically, all you need to know is what <a href="tags.html">decorator tags</a> you can use. The <a href="tags.html#decorator:title">title</a>, <a href="tags.html#decorator:head">head</a> and <a href="tags.html#decorator:body">body</a> tags are most used.<br> Here is an example of a decorator (save it as /decorators/main.jsp): <p> <code> 1: &lt;%--<br> 2: % This is the main decorator for all SOMECOMPANY INTRANET pages.<br> 3: % It includes standard caching, style sheet, header, footer and copyright notice.<br> 4: --%&gt;<br> 5: <b>&lt;%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %&gt;</b><br> 6: &lt;%@ include file="<a href="cache.jsp.txt">/includes/cache.jsp</a>" %&gt;<br> 7: &lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br> 8: &lt;html&gt;<br> 9: &lt;head&gt;<br> 10: &lt;title&gt;<b><font color="Maroon">&lt;decorator:title default="INTRANET" /&gt;</font></b>&lt;/title&gt;<br> 11: <b><font color="Maroon">&lt;decorator:head /&gt;</font></b><br> 12: <b>&lt;%@ include file="<a href="style.jsp.txt">/includes/style.jsp</a>" %&gt;</b><br> 13: &lt;/head&gt;<br> 14: &lt;body bgcolor="#FFFFFF" background="&lt;%=request.getContextPath()%&gt;/images/bg.gif"&gt;<br> 15: &lt;script type="text/javascript"&gt;window.status = "Loading: <b><font color="Maroon">&lt;decorator:title default="INTRANET" /&gt;</font></b>...";&lt;/script&gt;<br> 16: &lt;%@ include file="/includes/header.jsp"%&gt;<br> 17: &lt;table width="100%" border="0" cellspacing="0" cellpadding="0"&gt;<br> 18: &lt;tr&gt;<br> 19: &lt;td height="20" nowrap&gt; &lt;/td&gt;<br> 20: &lt;/tr&gt;<br> 21: &lt;tr&gt;<br> 22: &lt;td width="1%" nowrap&gt; &lt;/td&gt;<br> 23: &lt;td width="16%" valign="top" nowrap&gt;<br> 23: &lt;script type="text/javascript"&gt;window.status = "Loading: Navigation...";&lt;/script&gt;<br> 24: &lt;%@ include file="/includes/navigation.jsp" %&gt;<br> 25: &lt;/td&gt;<br> 26: &lt;td width="2%" nowrap&gt; &lt;/td&gt;<br> 27: &lt;td valign="top"&gt;<br> 28: &lt;br&gt;<br> 29: &lt;script type="text/javascript"&gt;window.status = "Loading: Document body...";&lt;/script&gt;<br> 30: &lt;div class="docBody"&gt;<b><font color="Maroon">&lt;decorator:body /&gt;</font></b>&lt;/div&gt;<br> 31: &lt;/td&gt;<br> 32: &lt;td width="1%" nowrap&gt; &lt;/td&gt;<br> 33: &lt;/tr&gt;<br> 34: &lt;/table&gt;<br> 35: &lt;br&gt;<br> 36: <b>&lt;%@ include file="/includes/footer.jsp" %&gt;</b><br> 37: <b>&lt;%@ include file="/includes/copyright.jsp" %&gt;</b><br> 38: &lt;script type="text/javascript"&gt;window.status = "Done";&lt;/script&gt;<br> 39: &lt;/body&gt;<br> 40: &lt;/html&gt;<br> </code> </p> <ul> <li>Line <strong>1-4</strong>:<br>An explanation of the decorator. This way different people working on the decorator are quickly up to speed.</li> <li>Line <strong>5</strong>:<br>This is needed for the <code>decorator:</code> tags to work (also needed on all pages that work with inline decorators (<a href="tags.html#page:applyDecorator">page:applyDecorator</a>).</li> <li>Line <strong>6</strong>:<br>Sets the necessary response headers to let the browser cache the page. Omit this line if your application is real dynamic (changing data).</li> <li>Line <strong>10</strong>:<br>If the requested page doesn't have a title, the default title is used ("INTRANET").</li> <li>Line <strong>15</strong>:<br>The status bar gets a message when the page is loading.</li> <li>Line <strong>30</strong>:<br>The entire body of the requested page has the <code>docBody</code> class. This way the navigation and body do not have to have the same font.</li> </ul> <p>Now open <code>WEB-INF/decorators.xml</code> with your favorite editor and let SiteMesh know there is a decorator (with a mapping):</p> <pre style="border: 1px solid #999999; padding: 5px"> &lt;decorators defaultdir="/decorators"&gt; &lt;decorator name="main" page="<b>main.jsp</b>"&gt; &nbsp;&nbsp;&lt;pattern&gt;<b>/*</b>&lt;/pattern&gt; &lt;/decorator&gt; &lt;/decorators&gt; </pre> <p>Now deploy the web application, go to the welcome page, and the main decorator will be applied.</p> <h3>More examples</h3> <p>More examples are included with the SiteMesh distribution, under the <a href="https://sitemesh.dev.java.net/source/browse/sitemesh/src/example-webapp/">src/example-webapp</a> directory. If the examples don't give you enough to go on, take a look at SiteMesh in action, download the petsoar-app at <a href="http://www.wiley.com/legacy/compbooks/walnes/">http://www.wiley.com/legacy/compbooks/walnes/</a>.</p> </body> </html> ���������sitemesh-2.4.1+dfsg.orig/docs/navpanel.jsp����������������������������������������������������������0000644�0001750�0001750�00000004172�11157162710�020432� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<p> <h3>About</h3> <a href="<%= request.getContextPath() %>/sitemesh/">Overview</a><br> <a href="<%= request.getContextPath() %>/sitemesh/requirements.html">Requirements</a><br> <a href="<%= request.getContextPath() %>/sitemesh/features.html">Feature List</a><br> <a href="<%= request.getContextPath() %>/sitemesh/history.html">History and Crew</a><br> <a href="<%= request.getContextPath() %>/sitemesh/README.txt">README.txt</a><br> <a href="<%= request.getContextPath() %>/sitemesh/CHANGES.txt">CHANGES.txt</a><br> <a href="<%= request.getContextPath() %>/sitemesh/download.html">Download</a> </p> <p> <h3>Documentation</h3> <a href="<%= request.getContextPath() %>/sitemesh/flow.html">Flow Diagram</a><br> <a href="<%= request.getContextPath() %>/sitemesh/install.html">Installation and Configuration</a><br> <a href="<%= request.getContextPath() %>/sitemesh/charsets.html">Character Sets</a><br> <a href="<%= request.getContextPath() %>/sitemesh/decorators.html">Building Decorators</a><br> <a href="<%= request.getContextPath() %>/sitemesh/velocity-decorators.html">Velocity Decorators</a><br> <a href="<%= request.getContextPath() %>/sitemesh/freemarker-decorators.html">Freemarker Decorators</a><br> <a href="<%= request.getContextPath() %>/sitemesh/dm.html">Decorator Mappers</a><br> <a href="<%= request.getContextPath() %>/sitemesh/testsuite.html">Test Suite</a><br> <a href="<%= request.getContextPath() %>/sitemesh/faq.html">FAQ</a><br> <a href="<%= request.getContextPath() %>/sitemesh/tags.html">Tag Reference</a><br> <a href="<%= request.getContextPath() %>/sitemesh/api/">API Reference</a> </p> <p> <h3>Services</h3> <b>JIRA</b><br> - <a href="http://jira.opensymphony.com/secure/BrowseProject.jspa?id=10000">Issue Overview</a><br> - <a href="http://jira.opensymphony.com/secure/BrowseProject.jspa?id=10000&report=roadmap">Roadmap</a><br> - <a href="http://jira.opensymphony.com/secure/BrowseProject.jspa?id=10000&report=changelog">Changelog</a><br> <b>Wiki</b><br> - <a href="http://wiki.opensymphony.com/display/SM/Index">SiteMesh Page</a> </p> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/style.jsp.txt���������������������������������������������������������0000644�0001750�0001750�00000000551�11157162710�020601� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<% String userAgent = request.getHeader("User-Agent"); if (userAgent != null && userAgent.indexOf("MSIE") == -1) { out.print("<link href=\"" + request.getContextPath() + "/styles/ns4.css\" rel=\"stylesheet\" type=\"text/css\">"); } else { out.print("<link href=\"" + request.getContextPath() + "/styles/ie4.css\" rel=\"stylesheet\" type=\"text/css\">"); } %>�������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/requirements.html�����������������������������������������������������0000644�0001750�0001750�00000004271�11157162710�021521� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>SiteMesh Requirements</title> </head> <body> <p>SiteMesh is a Servlet Filter and therefore requires a container that conforms to the <a href="http://java.sun.com/products/servlet/">Servlet 2.3</a> specification.</p> <p>As SiteMesh is written in pure Java, it is platform independent.</p> <p>SiteMesh is tested and works on the following Servlet containers:</p> <ul> <li><a href="http://www.orionserver.com/">Orion 1.5.4 and up</a></li> <li><a href="http://jakarta.apache.org/tomcat/">Jakarta Tomcat 4.0, 4.1 and 5.0.19</a></li> <li><a href="http://www.caucho.com/products/resin/">Resin 2.1.11, 2.1.12, 2.1.13, 2.1.14 and 3.0.7</a></li> <li><a href="http://www.oracle.com">Oracle OC4J 2</a></li> <li><a href="http://www.bea.com">WebLogic 7.0 SP2, 8.1 and 8.1 SP2</a></li> <li><a href="http://www.ibm.com">WebSphere 5.0</a></li> <li><a href="http://jetty.mortbay.org">Jetty 4.2.20</a></li> </ul> <p>The only other requirement of SiteMesh is <a href="http://www.java.sun.com/xml">JAXP</a> (with a parser implementation). This should be supplied by your servlet container.</p> <p>SiteMesh is compatible with JRE 1.3 and higher. For best performance, JRE 1.4.x or higher should be used.</p> <p>To build SiteMesh from the sources, you must have the <a href="http://java.sun.com/j2se/downloads.html">Java SDK version 1.4</a> or above, and <a href="http://ant.apache.org/">Jakarta Ant</a> version 1.5 or above.</p> <h4>Service Packs and Patches</h4> <p>SiteMesh currently does not work flawlessly on Weblogic 6.1, 7.0 and 7.0 SP1. For more information, visit <a href="http://jira.opensymphony.com/secure/ViewIssue.jspa?id=10045">http://jira.opensymphony.com/secure/ViewIssue.jspa?id=10045</a>. However, SiteMesh does work correctly on WebLogic 7.0 SP2, 8.1 and 8.1 SP2.</p> <p>SiteMesh does not work on Weblogic 8.1 SP1 because of various bugs in the JSP compilation engine. Apply patch <b>CR112789_81sp1</b> to your Weblogic installation.</p> <p>SiteMesh does not work on WebSphere 5.0.1 and 5.0.2. Apply patch <b>IBM iFix PQ80592</b> to your WebSphere installation.</p> </body> </html>���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/tags.html�������������������������������������������������������������0000644�0001750�0001750�00000020704�11157162710�017733� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>SiteMesh Tag Reference</title> </head> <body> <p><b>SiteMesh</b> is bundled with 2 tag-libraries.</p> <p>For installation instructions, see <a href="install.html">Installation and Configuration</a>, and for usage instructions and examples see <a href="decorators.html">Building Decorators</a>.</p> <p>Note that the tags below are listed without the namespace prefixes as these are defined by the user when importing the tag library into the JSP page.</p> <table align="center" width="80%" style="background: #eeeeee; border: 1 black solid;"> <tr> <td valign="top"> <b>Decorator Tags</b> </td> <td valign="top"> <b>Page Tags</b> </td> </tr> <tr> <td valign="top"> Used to create decorator pages. </td> <td valign="top"> Used to access decorators from content pages. </td> </tr> <tr> <td valign="top"> <a href="#decorator:head"><code>&lt;decorator:head /&gt;</code></a><br> <a href="#decorator:body"><code>&lt;decorator:body /&gt;</code></a><br> <a href="#decorator:title"><code>&lt;decorator:title /&gt;</code></a><br> <a href="#decorator:getProperty"><code>&lt;decorator:getProperty /&gt;</code></a><br> <a href="#decorator:usePage"><code>&lt;decorator:usePage /&gt;</code></a><br> </td> <td valign="top"> <a href="#page:applyDecorator"><code>&lt;page:applyDecorator /&gt;</code></a><br> <a href="#page:param"><code>&lt;page:param /&gt;</code></a><br> </td> </tr> </table> <h2>Decorator Tags</h2> <p> These tags are used to create page Decorators. A Decorator is typically built up from an HTML layout (or whatever is appropriate for the original page content-type) with these tags inserted to provide place-holders for the data from the original (undecorated) page. </p> <p> For more details, see <a href="decorators.html">Building Decorators</a>. <h4><a name="decorator:head">&lt;decorator:head /&gt;</a></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Insert contents of original page's HTML <code>&lt;head&gt;</code> tag. The enclosing tag will not be be written, but its contents will. </blockquote> <p><b>Attributes:</b></p> <ul> <li><i>None</i></li> </ul> </div> <h4><a name="decorator:body">&lt;decorator:body /&gt;</a></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Insert contents of original page's HTML <code>&lt;body&gt;</code> tag. The enclosing tag will not be be written, but its contents will.<br> <br> Note: the content of the body onload and onunload events (and other body attributes) can be included in the decorator by getting the property <code>body.onload</code> and <code>body.onunload</code> (the named attributes).<br> For example (the decorator): <code>&lt;body onload="&lt;decorator:getProperty property="body.onload" /&gt;"&gt;</code><br> <br> For more information: see <a href="#decorator:getProperty">getProperty</a>. </blockquote> <p><b>Attributes:</b></p> <ul> <li><i>None</i></li> </ul> </div> <h4><a name="decorator:title">&lt;decorator:title [ default=&quot;...&quot; ] /&gt;</a></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Insert title of original page (obtained from <code>&lt;title&gt;</code> tag). will be used instead. </blockquote> <p><b>Attributes:</b></p> <ul> <li> <p> <b>default</b> <i>(optional)</i><br> Value to be inserted if title not found. </p> </li> </ul> </div> <h4><a name="decorator:getProperty">&lt;decorator:getProperty property=&quot;...&quot; [ default=&quot;...&quot; ] [ writeEntireProperty=&quot;...&quot; ]/&gt;</a></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Insert property of original page. See API reference for <a href="api/com/opensymphony/module/sitemesh/HTMLPage.html">HTMLPage</a> for details of how properties are obtained from a page. </blockquote> <p><b>Attributes:</b></p> <ul> <li> <p> <b>property</b> <i>(required)</i><br> Name (key) of property to insert. </p> </li> <li> <p> <b>default</b> <i>(optional)</i><br> Value to be inserted if property not found. </p> </li> <li> <p> <b>writeEntireProperty</b> <i>(optional)</i><br> This writes the property with a <strong>space in front</strong> including the name ( propertyName="propertyValue")<br> Accepted values are <code>true</code>, <code>yes</code> and <code>1</code>.<br> For example:<br> The decorator: <code>&lt;body bgcolor="White"&lt;decorator:getProperty property="body.onload" writeEntireProperty="true" /&gt;&gt;</code><br> The undecorated page: <code>&lt;body onload="document.someform.somefield.focus();"&gt;</code><br> The decorated page: <code>&lt;body bgcolor="White" onload="document.someform.somefield.focus();"&gt;</code> </p> </li> </ul> </div> <h4><a name="decorator:usePage">&lt;decorator:usePage id=&quot;...&quot; /&gt;</a><br></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Expose the <a href="api/com/opensymphony/module/sitemesh/Page.html">Page</a> object as a variable to the decorator JSP. </blockquote> <p><b>Attributes:</b></p> <ul> <li> <p> <b>id</b> <i>(required)</i><br> Name of variable to assign to. </p> </li> </ul> <p><b>Example:</b></p> <blockquote> <code> &lt;decorator:usePage id=&quot;myPage&quot; /&gt;<br> &lt;% if ( myPage.getIntProperty(&quot;rating&quot;) == 10 ) { %&gt;<br> &nbsp;&nbsp;&lt;b&gt;10 out of 10!&lt;/b&gt;<br> &lt;% } %&gt;<br> </code> </blockquote> </div> <h2>Page Tags</h2> <p>The page tags, are used to apply decorators to inline or external content from within the current page.</p> <h4><a name="page:applyDecorator">&lt;page:applyDecorator name=&quot;...&quot; [ page=&quot;...&quot; title=&quot;...&quot; ] &gt;<br> &nbsp;&nbsp;&nbsp;.....<br>&lt;/page:applyDecorator&gt;</a></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Apply a Decorator to specified content. The content can either be inline by specifying a body to the tag, <i>or</i> by using the result of another page by specifying the <code>page</code> attribute.<br> </blockquote> <p><b>Attributes:</b></p> <ul> <li> <p> <b>name</b> <i>(required)</i><br> Name of the Decorator to apply to the included page. </p> </li> <li> <p> <b>page</b> <i>(optional)</i><br> Points to the external resource which should expose an entire page (<i>e.g.</i> another JSP file producing a valid page). This attribute can be relative to the page it is being called from, or an absolute path from the context-root. </p> </li> <li> <p> <b>title</b> <i>(optional)</i><br> Override the title of the page available as <nobr><code>Page.getTitle()</code></nobr> or <code>&lt;decorator:title/&gt;</code> from within the Decorator. This is identical to specifying <code>&lt;page:param name=&quot;title&quot;&gt;...&lt;page:param&gt;</code>. </p> </li> </ul> <p><b>Body:</b></p> <blockquote> The content to have the Decorator applied to. </blockquote> </div> <h4><a name="page:param">&lt;page:param name=&quot;...&quot;&gt; ... &lt;/page:param&gt;</a></h4> <div class="tagDef"> <p><b>Description:</b></p> <blockquote> Pass a parameter to a Decorator. This will override the value called from <nobr><code>Page.getProperty()</code></nobr> or <code>&lt;decorator:getProperty/&gt;</code>. This tag is only valid inside a <code>&lt;page:applyDecorator&gt;</code> tag. </blockquote> <p><b>Attributes:</b></p> <ul> <li> <p> <b>name</b> <i>(required)</i><br> The name of the parameter to override. </p> </li> </ul> <p><b>Body:</b></p> <blockquote> The value of the parameter. </blockquote> </div> </body> </html> ������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/dtd/������������������������������������������������������������������0000755�0001750�0001750�00000000000�11157162710�016657� 5����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/dtd/sitemesh_1_5_decorators.dtd���������������������������������������0000644�0001750�0001750�00000002230�11157162710�024063� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!-- DTD Version: 1.5 This is the DTD for the SiteMesh 1.5 decorator.xml file. It's style and order are based on the web.xml DTD file listed in the Servlet 2.3 specification. This means that the declaration of decorators and mappings follows the same format as servlets / servlet mappings or filters / filter mappings. Valid decorator.xml files must contain the following DOCTYPE declaration <!DOCTYPE decorators PUBLIC "-//OpenSymphony//SiteMesh 1.5 Decorators//EN" "http://www.opensymphony.com/sitemesh/dtd/sitemesh_1_5_decorators.dtd"> --> <!-- The decorators element is the root element of the file. It contains decorator and decorator mapping elements. --> <!ELEMENT decorators (excludes?, decorator+)> <!ATTLIST decorators defaultdir CDATA #IMPLIED > <!-- A list of patterns to exclude --> <!ELEMENT excludes (pattern*)> <!-- The decorator element contains the declarative data of a decorator. --> <!ELEMENT decorator (pattern*)> <!ATTLIST decorator name CDATA #REQUIRED page CDATA #IMPLIED webapp CDATA #IMPLIED > <!-- The url-pattern element contains the url pattern of the mapping. --> <!ELEMENT pattern (#PCDATA)>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/dtd/sitemesh_1_0_decorators.dtd���������������������������������������0000644�0001750�0001750�00000002562�11157162710�024066� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!-- DTD Version: 1.0 This is the DTD for the SiteMesh 1.0 decorator.xml file. It's style and order are based on the web.xml DTD file listed in the Servlet 2.3 specification. This means that the declaration of decorators and mappings follows the same format as servlets / servlet mappings or filters / filter mappings. Valid decorator.xml files must contain the following DOCTYPE declaration <!DOCTYPE decorators PUBLIC "-//OpenSymphony//SiteMesh 1.0 Decorators//EN" "http://www.opensymphony.com/sitemesh/dtd/sitemesh_1_0_decorators.dtd"> --> <!-- The decorators element is the root element of the file. It contains decorator and decorator mapping elements. --> <!ELEMENT decorators (decorator*, decorator-mapping*)> <!-- The decorator element contains the declarative data of a decorator. --> <!ELEMENT decorator (decorator-name, jsp-file)> <!-- The decorator-name element contains the canonical name of the decorator --> <!ELEMENT decorator-name (#PCDATA)> <!-- The jsp-file element contains the full path to a JSP file within the web application. --> <!ELEMENT jsp-file (#PCDATA)> <!-- The decorator-mapping element defines a mapping between a decorator and a url pattern --> <!ELEMENT decorator-mapping (decorator-name, url-pattern*)> <!-- The url-pattern element contains the url pattern of the mapping. --> <!ELEMENT url-pattern (#PCDATA)>����������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/index.html������������������������������������������������������������0000644�0001750�0001750�00000017046�11157162710�020111� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>SiteMesh Overview</title> <meta name="keywords" content="sitemesh, opensymphony, decorator, decoration, framework, layout, consistent look and feel, integration, java, j2ee" /> <meta name="description" content="Opensymphony SiteMesh - Web-page layout and decoration framework and web-application integration framework to aid in creating large sites consisting of many pages for which a consistent look/feel, navigation and layout scheme is required." /> </head> <body> <table align="right" cellpadding="6" cellspacing="0" border="0" style="border: 1 black solid;"> <tr> <td width="180" bgcolor="#eeeeee"> <a href="http://www.amazon.com/exec/obidos/ASIN/1861005512"> <img align=left width=111 height=140 alt="JSP Site Design" border="0" src="http://images.amazon.com/images/P/1861005512.01.MZZZZZZZ.jpg"></a> <small>SiteMesh is featured in a chapter of <b><a href="http://www.amazon.com/exec/obidos/ASIN/1861005512">Professional JSP Site Design</a></b>.</small> </td> </tr> <tr> <td width="180" bgcolor="#eeeeee"> <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0471463620/qid=1061085068/sr=8-1/ref=sr_8_1/103-7730642-5726207?v=glance&s=books&n=507846"> <img align="left" width="111" height="140" alt="Java Open Source Programming : with XDoclet, JUnit, WebWork, Hibernate" border="0" src="http://images.amazon.com/images/P/0471463620.01._PE30_PI_SCMZZZZZZZ_.jpg"></a> <small>SiteMesh is featured in a chapter of <b><a href="http://www.amazon.com/exec/obidos/tg/detail/-/0471463620/qid=1061085068/sr=8-1/ref=sr_8_1/103-7730642-5726207?v=glance&s=books&n=507846">Java Open Source Programming</a></b>.</small> </td> </tr> </table> <p><i>You can also start by reading Will Iverson's <a href="http://today.java.net/pub/a/today/2004/03/11/sitemesh.html">Introduction to SiteMesh</a> over at java.net or skip all this and <a href="download.html">download SiteMesh right away</a>.</i></p> <h4>What Is It?</h4> <ul> <li><p>SiteMesh is a web-page layout and decoration framework and web- application integration framework to aid in creating large sites consisting of many pages for which a consistent look/feel, navigation and layout scheme is required.</p></li> <li><p>SiteMesh intercepts requests to any static or dynamically generated HTML page requested through the web-server, parses the page, obtains properties and data from the content and generates an appropriate final page with modifications to the original. This is based upon the well-known <i><a href="http://c2.com/cgi/wiki?GangOfFour">GangOfFour</a> Decorator</i> design pattern.</p></li> <li><p>SiteMesh can also include entire HTML pages as a <b>Panel</b> within another page. This is similar to a Server-Side Include, except that the HTML document will be modified to create a visual window (using the document's <b>Meta-data</b> as an aid) within a page. Using this feature, <i>Portal</i> type web sites can be built very quickly and effectively. This is based upon the well-known <i><a href="http://c2.com/cgi/wiki?GangOfFour">GangOfFour</a> Composite</i> design pattern.</p></li> <li><p>SiteMesh is built using Java 2 with Servlet, JSP and XML technologies. This makes it ideal for use with J2EE applications, however it can be integrated with server-side web architectures that are not Java based such as CGI (Perl/Python/C/C++/etc), PHP, Cold Fusion, etc...</p></li> <li><p>SiteMesh is very extensible and is designed in a way in which it is easy to extend for custom needs. </p></li> </ul> <h3>The Problem</h3> <p>There are many web application platforms that are in common use, and even more frameworks. Typically, a web-application is built for a specific framework on a specific platform (e.g. using custom JSP tag-libraries on the J2EE platform, a custom Perl collaboration API using CGI, or a pre-written application using PHP). A web-site may usually consist of many web- applications built with a variety of technologies.</p> <p>However, while individually each of these web-applications may look and perform as expected, they are often hard to integrate with the page layout of the existing site and can often end up isolated, attached to the site merely by a hyperlink. </p> <p>The most common reason for this is if a site is a mixture of custom developed pages/applications and pre-written 'out-of-the-box' software. This software may not be configurable enough to be given the desired look and feel of the rest of the site, or may be developed using a different technology to the rest of the site, restricting the developer from using fragments of the application in other pages of the site.</p> <p>For example, how many times have you been to a site that has a very consistent feel all the way through, only to get to the 'search-results' page and wonder if you were still on the same site? Or how many times have you seen a framework or web-application that you would love to use on your site but it will not integrate with what you already have?</p> <h3>The Solution</h3> <p>The solution is to work with the HTML that is generated by the various web-apps instead of hacking at the underlying code (although SiteMesh is primarily geared towards HTML based sites, it is built in an extensible manner allowing it to be easily adapted to other mediums such as XML, WML, PDF, etc). </p> <p>Each application should produce a plain vanilla version of the HTML content it wants to display. How this is achieved does not matter - it could be a static HTML page, XML/XSL transformation, Servlet, CGI script, etc. </p> <p>The HTML content is intercepted on its way back to the web-browser where it is parsed. The contents of the <code>&lt;head&gt;</code> tag and the <code>&lt;body&gt;</code> tag are extracted as well as meta-data properties of the page (such as title, <code>&lt;meta&gt;</code> tags and attributes of the <code>&lt;html&gt;</code> and <code>&lt;body&gt;</code> tags).</p> <p>From the extracted meta-data, an appropriate <b>Decorator</b> is determined. A decorator can be thought of as a skin for a page - it wraps a plain looking page with a consistent look and feel. This decorator then overlays the original page.</p> <p>To use SiteMesh, it needs to be <a href="install.html">installed, configured</a> and <a href="decorators.html">have some decorators created</a>. This process can be completed in minutes, and no coding experience is required. No changes need to be made to your existing web- pages/applications!</p> <h3>Visual Example</h3> <p>2 pages are produced from different systems (one is a JSP and the other is a pre-written CGI script). Both pages are parsed and have a decorator overlaid to produce final page of a consistent look.</p> <p align="center"><img src="images/overview.gif" border="0"></p> </body> </html> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sitemesh-2.4.1+dfsg.orig/docs/faq.html��������������������������������������������������������������0000644�0001750�0001750�00000014161�11157162710�017544� 0����������������������������������������������������������������������������������������������������ustar �twerner�������������������������twerner����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html> <head> <title>SiteMesh FAQ</title> </head> <body> <h4>How fast is SiteMesh?</h4> <p>Fast enough! SiteMesh typically has a 10-20 ms processing time, centering well around 10ms. You're more likely to have process timing issues in the pages being decorated.</p> <h4>Can I change rendering order on the fly like a portal with Sitemesh?</h4> <p>Yes. The decorator isn't hardcoded; it can choose what panels to include, and in what order, <a href="dm.html">at runtime</a>.</p> <h4>What languages can panels be made from?</h4> <p>Any active content your appllication server can create: CGI, PHP, JSPs, servlets, velocity pages, freemarker tages, Tea, etc.</p> <h4>What is the advantage of using SiteMesh over Struts Tiles?</h4> <p>Tiles seems to just replicate the <a href="tags.html">&lt;page:applyDecorator&gt; tag</a> (albeit without the advanced page parsing of SiteMesh). However this is a very small part of what SiteMesh.</p> <p>The strongest attribute of SiteMesh is that the decorators are applied with a filter - therefore you can decorate pages without the pages themselves knowing they are being decorated (so you can apply a single SiteMesh decorator to a site that uses PHP, JSP and ASP if you want).</p> <p>Also using DecoratorMappers you can map which decorator/s are used in a number of different ways (ie have one decorator for printable pages, another for robots and another for Netscape users - all without changing the underlying page).</p> <p>That said, you can also alter which decorator is applied from the underlying page (note, the decorated page doesn't need to know it's being decorated - however if it does know it can pass parameters and choose decorators in SiteMesh - powerful).</p> <p>Also SiteMesh has a full property system (ie decoratedPage.getTitle() or decoratedPage.getProperty(meta.description)) which allows you to build very advanced and flexible decorators.</p> <p>More info available <a href="http://wiki.opensymphony.com/space/Compare+Sitemesh+%26+Tiles">here</a>.</p> <h4>Where can I find more information on Java Servlet 2.3 Filters?</h4> <ul> <li><a href="http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-filters.html" target="_blank">A JavaWorld article on filters by Jason Hunter</a></li> <li>IBM's developerWorks has an <a href="http://www-106.ibm.com/developerworks/java/library/j-tomcat/?open&l=101,t=grj,p=TomcatTricks" target="_blank">article on Tomcat Filters</a></li> <li>A step by step tutorial <a href="http://www.orionserver.com/tutorials/filters/" target="_blank">here</a> by the OrionServer guys.</li> </ul> <h4>I need this functionality, but I want an offline version!</h4> <p>See <a href="http://www.pols.co.uk/downloads/static-mesh/">StaticMesh</a>.</p> <h4>What ports of are available?</h4> <ul> <li>Microsoft .NET (stable) and ISAPI C++ (unstable): <a href="http://sf.net/projects/sitemesh/">http://sf.net/projects/sitemesh/</a>, see the <a href="http://wiki.truemesh.com/sitemesh.net/">wiki</a> for more information.</li> <li><a href="http://xaoza.net/software/phpmesh/">PHP-Mesh</a></li> </ul> <h4>Does SiteMesh support HTML frames?</h4> <p>If the <a href="api/com/opensymphony/module/sitemesh/mapper/FrameSetDecoratorMapper.html">FrameSetDecoratorMapper</a> sits in the decorator chain (sitemesh.xml) the frame definition page and the frame pages are <b>not</b> decorated.</p> <h4>How do you get a reference to the (parent) request from inside an inline decorator?</h4> <p> You can use Page.getRequest() to access the HttpServletRequest of the original page.<br/> For example: <blockquote> <code>&lt;decorator:usePage id="p" /&gt;<br/> Path Info = &lt;%= p.getRequest().getPathInfo() %&gt;</code> </blockquote> </p> <h4>Is there a way for a decorator to pull a property (&lt;page:param&gt; value) via Java code, not just via the taglib?</h4> <p> You can access the Page.getProperty() method. A Page can be accessed either via a JSP tag, or through an attribute in the request. <blockquote> Example 1 (using JSP tag): <p> <code>&lt;%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %&gt;<br/> &lt;decorator:usePage id="thePage" /&gt;<br/> &lt;% String author = thePage.getProperty("meta.author"); %&gt;</code> </p> Example 2 (pure Java):<br/> <p> <code>import com.opensymphony.module.sitemesh.Page;<br/> import com.opensymphony.module.sitemesh.RequestConstants;<br/> ...<br/> Page thePage = request.getAttribute(RequestConstants.PAGE);<br/> String author = thePage.getProperty("meta.author");</code> </p> Example 3 (<a href="velocity-decorators.html">Velocity</a>):<br/> <p> $page.getProperty("meta.author") </p> </blockquote> </p> <h4>Howcome I cannot decorate my error pages on Orion?</h4> <p> Orion applies <a href="http://jira.opensymphony.com/ViewIssue.jspa?id=10180">filters incorrectly to error pages</a>. For more information, consult the mail archives. </p> <h4>How do I enable SiteMesh to decorate error pages on Tomcat 5?</h4> <p>Replace the <code>&lt;filter-mapping&gt;</code> element in <code>web.xml</code> with this: <blockquote><pre><xmp><filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> </filter-mapping>

sitemesh-2.4.1+dfsg.orig/docs/images/0000755000175000017500000000000011157162712017353 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/docs/images/overview.gif0000644000175000017500000011151011157162710021705 0ustar twernertwernerGIF89aI9æÿ„..—@<0»»»ŠŠŠÖÖÖGGEE£ïïï™™™YYYPPP@@@000 ……… ®®®,,,++(EEEHHHiii@ÆÆÆfff,$•••ÿÎ ¾¾¾22<<<$$$aaaÎÎÎ}}}aaÚÚÚuuu¡¡¡òòò¾™ÞÞÞÂâây¾¾²²²((}eªªª8880™™®ÖÖÿ0ÿ¡ÚîîqqqÿÿiÎÎttt444‰ÆÆÊÊÊ008ÿ@a¥¥¥]®®yy¾ÂÂâi¶¶$‘‘ÿLßßßÏÏÏvvv@¡¡ÿ] ……ÿ®yyyL¥¥ÿuÿºUUUÚÚî®®Öÿ™ÿÂζ¶¶‰‰Æii¶YH]]®ööö …‘‘‘úúú‚‚‚ÿ81aLq]^^(( 88@ HPPæææÿÿÿ!ù,I9ÿ€‚ƒ„…†‡ˆ‰Š‹Š‘’“”•–—˜™š›œžŸ Ÿ|Œ¤‹i¡¨©ª«¬­®—<¥ƒi²¶·¸¹º»¼#.ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐμ¥)ÑÙÚÛÜÝÞßÅ&'·)/ÕçèéêÕ¾}îïðñòóôõö÷øùúûüýþü.¨­;tíŸÁƒ*\Èpžq¶Ê œH±bºv 3jÜȱc½€ôH²¤É“÷’3²¥Ë—…0¢œI³fC-GÚÜɳgJˆ²$ÂJt¢L›8phôñ¡ï~@MøCˆ7¢ø„‡3¤Î­ð’úczO‰Õ_Š•WÕê#ÿÿ¤öÑRReD–EóêÕu´æÚŒUœNíscðÁJç ¶«Å¯`Ýýåǘ^”¦}|yrpò;ÄïŽPñWØGbvƒââŒA9 ¢¡Ɖ)"ÈHD{¯oE}Âíƒcô¸8~ÈûEyÚ*Ê•¸;’\ Ó¡ÿþ® Üæ?”R¹ü#­½§Ÿ¡&ÿAw¼rJ¶K~´»Â}ŽüÈê.:fý˜qäXE%¤ÝpàiE\t}TQ]~o§a)yJPá=T ׇ‚ N·ŸVã¡¥R8L¨à}§%× ƒ –—_vpVUn”š5«ý 1 ² ‡¨"*  ‚ÿ 2œ¤!Fþ&å!Á-t„VXõA)öñÄ O$¥Å \p&~GH'–pQÑzJp—Ù }ÁÅŒ8ùÄfça…ÕS]j&™_<ÅÅb]~ÉÙ}ÖùPèJ(µg?he¥£}A§€yuAF2âŘw–§f¥ ñÅ?ŒÖaž\LúN 7º'>lZOUWºC*¥_Dê¥Äá‡Þ•°Êz_xI AœJTA'Má—+a>˜,q+2´#)B A @@ä$Dpä1,@Â2¨ûÚ IB ~À+/»îêÁ¼SîU¥BZÁ*?HKk&õשïK,atåªYÿR—ºsí •rVœ;J¬˜­akŽ\v s©ÔµØÞ°ðšŸ]űyO˜F¬®;ÌçFRT BJÜ á‚IEÈ…T<ÅòÄ’%fzï„ 2®ºíÃðTáæfÉ WÍ ·²®bß·(aáòÅ8˜µçta;'¶Ú=´Fß2® 꺦/‘9œÀä82Ä@C)0y® õ"8âŠÃk8ä2,p^+”U‡š©˜Ÿ…‡ß•ÅB„þË£«ŠCÜFÅ1<è™þ´Øb±|òç¯všdˆ=Šs¡c­QÏýŒfEÊlqZri›2]¶Ü¦‡¦`R,k‰ÕhîPqöÿçÏs<±¹“½~,NÛb=±õ—§ÓYZbÌK7P<¢nAZ€ˆt‚,é$ˆÒ¼Ç8Ë nDR`/'°td?U8•tD3‰j8ì™Øeꔽ\}ÉWʵ¦Ö¥:UfµÃV«îãÁ¹a‹ƒ3ò]<ð3)ü$Mn+ä”K”gƒÍit’‰BÛÜ¡´MágLë …DÂPÍ-ÌOª(*¢OR›j[uÈÄUmª`̳]Z¢`¿lm3ÝóÿÀÕ#uùá4 os‰'X@ ”„,€P Á?rÔKæ…‰-fY7ŽXÔæ²baÿ„”:]S؈¨ëZAÛÏ °"'zÄP*_Ú&W†¹p,“ðO<ò¤ê½…N¹ÂJ·2‚¼ñšÚOZÔ¦Å(‡:d™Ó~L“©Dó––âÜ¢Y#\EùáXSx9͵°q?דKNS¨ù *ûif¡ÞÒ©TAGH&Zö·ÿi)Ø ‘ÖÐ J'(h" Á@@þ!¡‚häCj¹HÂd’‘¹‡ñ4F¶¦e”‰‘Ö;6ʳN=æSå‡â¦Î|¼p&$KÞ±7©rýƒm"ƒq$ q¹ÀT`> î)* `ðÓ¤F@¨% FSŠ‚ýΣTÿ…‡¨³Ï“sÇÌ*<¾”¢ŽŠ5«3UDMiЛ Â  ^³$bIu¥— ìªSºî`Q}ÉTÏ:£6¦T­‚Îf’¯ª#¬„Õ˜a"KÕ´&¢¦ÍlEKÙΊձ逬gG›RË"³šM­:8KÚÖú´è­kg»Ób=R­nÏÁZÚúÖ«&%JK\ŸØÖpÃn—‹Ž%X@Юt§KÝêZ÷ºØÍ®v·ËÝîz÷»àõ.$\²„÷¼èM¯z×ËÞöVw`®|‰bƒ"à¾øÍ¯~÷Ëßþú÷¿°€LàøÀ~C\ò øÁްÿ„'Lá ó+˜¯†]bløÃ‘$Aœ›xJ+Èð‰W\³øÅD1‰aLc—¤¸Æ8f„‹sÌcuȸ%/(q‡\™È;>²’mñãyÉP.…‘£\ã$SùÊ…h²EžŒå.bÊ^>±•ÃLe-W„Ëd¾2˜I€4[tÌnV²™)‚æ8/yÍŒØì08ó¹ÇsžHÿ‚z %Hÿ„NQ­k×S²8†äpN˜u:Hõ*{(à~<¨„"QH%Cbt)À„„p€‰$„§Pf†„‡pò6$OB' z¸à€H¸¸zXWsñ§t„WHï~>e‡@ƒô‚ˆ}Ç8ˆø-~”Gˆ½—{‹Ós쇀ƒº ƒˆ0@@2}‚PpGî×$ù{%8é2‡rx$„¦Xæ’9ïr‰”‹>µ8G¥$rh8ù—/IÕqN"‹Yˆ.H÷P(`‹„.·WT?"} ÈŒãò{ê‡<ø|puv(py( {¨ÿ{×l })xÚ¨.쇈† ˆŽø|‰‰ƒÇŽí(ƒ—hs¼W‚16[V¹ C$¥ˆ}‚8@kÇwÓ·Œ ùÓ÷z„p„HUm4@aG/¾ˆ‚{U„•SPr'E¨‹ìRb‰…D‰$fèùòsãpoET¸ ߈‡áˆã˜Ñ×pçnÏ÷{§WW}X×…²‘p¢èxÎ~ë‰öˆGÉ8rŽƒoi'7(gF»2@T…t–g.CQ¿Æ÷ké8ëb.g©>'„ø‘‰’ëò#†DrEH€|3EhmçBT5Ù{N8qfˆÿ“ê°“=É ?‰ÎgƒW7/ñVbr(ˆ¡t¿§8K9mÍh$ÍõH•‘˜™ é•â²nïo‚£P™“-Á‰¹à‰‰(uÿÇ@½‘Tù2@lœ¥XPü—&9—Õæp¿‰|Lu‰ ùPëB0°m´x$<(.²Q˜,y˜Ýw€˜~p/‰¹WŽ™™º0™èt¦•–ã™”Èn27mD¹TïG”ͧyŸ@'uƒoß•D)–.a›¸€›(‘ù÷ÔxÙù$´—'dÅXœX˜MBI2W y/V˜—Ïy„!?W:Åzr¸Úy)¨5WPHT)@ 7ÿžöH›¹pžèùrG·¶ywÉ…ƒ©}¢Økm·m^(v$ ¤v)$ªS}ôpSZ¤†$І0H† yú•3Æ ZZHì£|´„‡¬ç–´VkjS…°B7HæÂntŠìBx´öœ±'mªz¹¶.•c.O"§Š §…ô$?²Wyk>ÂzI¢£u(|ýÓ£>j©š… ·  ˆ ‹† “wµ ª pwtx³%¹pªoŪÁ£˜Z ꫵ –tf ´ú°š«Š0«¼Jšj œú«±«Äj¾z¬>f«‚†«Ê:Æú¬‚¬ÒZ Á* ÃZ­æI©t¤­…@­Þšÿ ×Z Ù® È­zÓ± ®æÊdÌúhÎÚ®¯Š®‡&¯ì*¯¤0®¤P®øz Ñ*­÷ÊPx5°…àqŒ°$%yñ²/–¦¯ŒÀ¯ý* ÿú¬›”ø‰oóÆšEòˆˆ{øI…‰æ°‹±K «¬ x“xuÓ§±P±Yªx“—~q&²Š@²%»'{¬)kˆ„}siƒˆ@•†À}üwGëÆh6›8›³‰°³ÄÚ³˜(•&¹~~ÐS·‘ dIHOÙlX †´yWËGR§.­h{!!@·ö¥„`£|„ïצài/¯×$J¸…’Ê K‹Më´‡µ¿*µþ}`[µçBÿŸ:—/Î×tî‘B %W—ŸIùyHK‰Íf Iò±"Ÿ€j–Ú‡ ¬ïÊiñ*¸:I¯”f¯?šTw–«ˆŽ7š@[•Ÿ}¦y¸.Šo ››«²rª’ùy_M·×W–P¹ ç.•ƒotm9£ÒK½úg­§›j©«º;ʺ¡æº1w±Á«¸ôòlØè|Tø‚>›ÑçƒB9x ½mm ;B'§(è[bT™p ˜pš8–Ù+lÛ˽þê½®¾qmx%P^ÙŠ@w$D«¾S§6È}u¸^©±Œq0KƒÎ—…˜‰ñ·‡¸,„Ë«†;GPé ß×¹ø6ÿ$ç;»JÉm)в6ˆlƒ\ Â7¼W‰<(l*¼Â-œ«/\ ×{ŠÈ—wÃð8s•BªšµKñ–¿Àç•o¢$€ŒÔFgÄ&üÆë°Ä…ÐÄüÄ´Ű1x(ˆO2mŒÃ!¶ø6}ù—¸ª¹š‚8Ææ(ܧ‚*@Ó‘|s¿v»nœÄIÇüm¼ÂR†ÀǦÀ»šû$Š8x!Ð¥Y•B§¾ð¢sW·kM—zIKµ[YšÛ&”Též“÷.â—¦–[•$ŒÄB¼¬aêÉè`Çëúºë)¾xzsïwu p”|¸Ï«sÕ6ŠW¨¶¬¸ÿº;ºÜ|Í«<Ã|Î'¼ÉüÖÉȬ³ Lnꊩ=;°Ûqçk»Wõk+W* u颟¸¶ÚÏ[I$0À¶'w0@ЇÐ$Wqûl/l—rLt̽Ê,ÏÌœf.ûb=­ºm©=»bÍb!-K¿›vÆiœŒS¿3]†9™o*²9í¢…p½7ͦ©Ö‚7…{úPsí {¥Ö^ê#’μ•îè^h_~‡a.抰ç¶@Øx”$~€Ø&©Ø—-à´Þ»q¡õšß /„©• œ…mëxœ¸Ö$DvçÄ—çÞ êºpÚõz{KœÛ³­ßw¤ß0@=õPó2‡G%r?§UêsyÿG¿VÞŸ¶éàȳÄíéEKæ9hæ‹ÜËÝÜÏÍÝIçÔ¸Ý%q Uè¼>‡&iFò'j‘‚ð0Ú–½.îÂÔånîψî¨î'xï-˜¬}.×=ðžHùb u.ù¾º>ð ©í?— ¯ß=æëwìÚ*ì¹°àGˆ¶ž²y²±ÓmÝ.5Íú>P4P’^P‡Äƒ:o$ëôEŸÓ¯é:®­*_­,¯ð€ò.×ôÒúô /õ)GõÏjõæŽõ·lpeab`®zWcö¦\ˆÀõžîõþ¶lð 0÷t_÷v÷xŸ÷z¿÷|÷ ¤à%Ð÷„_ø†ÿøu:Êö³Qû,v³gv’ÿÏ µ$—ªdæöæ¶l €¥ ¶oZ¿­‰ÀøE90?’zh~WÍPiê¦>]Õähšnœïùú Ï\ Fú…Ð;œæ A¬åôR.(ˆ$T î^VûÉvû*­Î¡ŸÌÞëûÏøT0ÄÏ.dŸîýÓ¼T²ï7Å„âoH·‘—mÊgÎOlпbºî£Ïð·éð;øývGÑM¡k (*!*( ‰‚4 ‡( *ˆ—„žŸ ¡¢£¤¥¦£++§)/«¯°±²³´µ6£ $µ¼½$ ¦·¾Ä¼©¢ÀÅ¢/)Êÿ“$($*'~)(Ж*’ÝßÕ0 ÜžØÚ‡Ö!ãí!Îóô¢Ç¯­õúûü§Ã¢ºú LVêŸ@~÷@ÜÇl¥G1ÖùA!ÆÃpÖ0Âû“#c§‰)ÁÉîáÁ“´žÊ‡²¥Ë^A|élᨘ4‰©ôd³^CgbdÊ1­¼1yó¸Ôh¦Ü2Ie‡täºg9³†ÚYŠ¥Ö¯`áô4³Ó7R»Jå8Ù3ÔØ°±¸>j;ï§²'ò.X £Y E2šIúÓ÷Ïà¾0òæ•gX±¤¿ .brÆp³Êå5³g”o•}´” h¥ V×gY›ÿÐuf÷µÿíÛ¯b‡êŒ»w±ÐF7*ÝNQÒE2Šc"¬È/Šfä²!m”0 è)`p”QÝaèŸf{îÛSlñÅj—_ï[7(Þìã¿"/|é¯Á'2AËv턟½í$§š7ƒÐ0 'Ð`XG~Lt ((˜ ˜ñÄ)äÅwÞ…ú¨'߇p¹÷ | – }i™ÅÎ#4¨ §ýqB ”Pà •]¢b#BE`Ž)Ä ƒ 7Ê(cd~ Å¡(²·a?š(¥K"zBâ”R¢øIiÒ™_Œ'DDÉ.$Ä€Âq;¶sÚî”“Ý 9@ k!³¤[®aù$?QÂB‚‚sQ"'‚‚š(!ÿ ”¼I…Š¥Nªàãʤ˜jéIiA5cR)0–] I޳¢}j6Ir(XÃÑ(è=Òäz{2Þ,ÙDPgq”(‚ª'݈’Ÿ(ˆP¢Í°‹i/Uvrå³òij Ø&"Ms@ØÌ „ɸpIÚ`‡ü‘¸ƒý%[77†ëÇY ÝybžSæÚ᮲”ƒ¢&9O&Ú ÒbÁf%ÆI&›®ø%;00l° S [¥«LkñzÖJY«XøJ©¯OüÆBBÿFŠ‚ö…‚˜ó#ajCH˜¯¦é‡ãÄ@ãt‰¼üëÆ¹a¼Ò¥DƒØ±‰ÿqky#ÓÓg-/+ÿræR…¶Ã‚2BR2ºݬÃ%²ˆ$ã06N„t4,Ѳ‚ôÛñ-]bÓO·g´…P–ÜKÀ‘#C¸Û(µ‘I‡¼œ­jù< áæeø©t“w#WþšÝ ⲉQ×å7/ÓX „I^4ÜŠ&¥pØ ’¶¢ ùe´ËÚ«knÊåêέ{oœ‡Â i T܉ñÃ?‹ç´H\‹ñ)íý‹½´NõfÎ{„* Ø FìœQ*ˆ_ͯÉÖ˜ÃÚë/ þï¨HO |'? ô¦áÿ*Áƒâ¬Rž8Ö'è)PðÌ‹… Z•ý™‚8ѳSßæAJ¸#I…êZe䚬Eÿ'9PEb¢?0Ê‚Ú)T#€vñ¿ÿ5â€4KžÃ&‹ÂI*Ä€`ÁY„®z0ÌâVd( ø°#£¨â#)ëubŠÂ“T¦>׉úˆ¢UáÒŽ%h‡œ#Õ‘f࢈#®oY-ˆ§pâ+p¾¶‘‹GyÔq‚A%Br„›Æ‹©i~¼ó"'ªs‰pAA‘Û9t‚&i‡ÍPÁ_$§f ²¯š‘aôH­!‹!‡ºJe B–Æ—–°„¯ èËÒŠzãac)ÊÑ*yL„k ˆV¡.hDBÿ†!„ýVqEeXò’ºË$ õ²ˆ]„êˆ +D/Í HAØOUêzG7Ž% 2Æ“?ò†'eËN¬(˜øšäè,ÿ ³][#Y AšLˆPŒ%ÒQ¸yo$’¤ùdFpjNœäÄeÅ=¢žßÒZT¬D£”„’xY^‚†´íKý|D7Di ¨»#£NÌ•ÒÚÅÎ|• ¸ÚUF4@„ QSotTi’uãn^˜æ1P¨¡I@ΣŠ.d[# ?¬K–Þè#æ#ˆ@Ô2òHíîBËQ^\gW¯"|'!›´|Ò¾…PP¡eByð·P+ÛE€¥UÕ²VZŠÉQ'Eðç] Y!¥èËhÇ]ƒ£ìe0g·ZÉìݶ 2Lu3=¾ †F¤Ð$ÂDMOµÙK3wZS %h€DÕ>âÀ¤+°ýâI9tìÕÕ<ÿbã;¢ÉÇ2•£ÌÕåX½>2- 9dZäÔ7G.щ¹šâW0YÆNŽ11§ÌfûtÃÊÁ²¹¸vù%_îM˜A4f_t5g~1š¡L–ËÐ…fʬà 9“UËwÆs‘O¡Æ›ò÷—¦/¦ÃºŠ=¨Ï½ø3Q+ÔÔ–@u; ®UûÈ`µ5<üªFÉ;æô!é–么ÜæB Ò&’Øi’ÕP’÷Eh'b~(´¥]¾‚1ÌÚ„À6a†C@1ÌÛ½n¯Ã}_Ï+ŠÝ¨ß¥@jl§û’°Y/›dä®Ü¸óÍ_Ël-°ýYRòâÿ#Ö0ÖšíH6zÉjƒ7ôØLÅ ¨+Yf~šÎï±³Å÷ñk-¶¹+—(i¶–|Z"ï–ÑZFHˆ'ÛI÷–ZÅ7s³jœæôÈó?9"VGëžè*gLì–×{R¯…¨q^sK1] ¿&‡G¦Ñ2NÔêŽ(íš‹n OË'é´XúÓõfó±÷{Ò¦8Ó7äÌö=’3RAl-QZ¹Cñç]w¹½7ªd³ë ã#º¹ßa‚öRp'Aü$%ZxiI ÊôÅFH¨ÆoC/ÇUÌE7ø|ÞJ‚ï¼— Ï4½#}óX½˜?/­Ð«>yÆ×18EØþö¸Ï½î=Œ{Èÿìž¶¥û,Äþú±^nÅÿ éG|ô¿óÙÉWvÙ£Oø\ˆ¸s¦w~((©ô™ó;¿øÇOþò›ÿüè?²:}êÛbù¢˜bj<¢ŠÍßôæîéŸïä3Á ,€8€X€x€ØÇ·oîGdÖ· ÀVlÈuIdlÍçyü'sÑ÷Øø¨€ìçt 8zx xÄF\m0G¤AÄÖ5Ý¢r.˜w(2¨çMÞ—o‚>øƒ(‚§À€%ˆy'˜v®CYt÷9“rGJùá.–®3RN˜3–}¸}ÇFq€ØS0c @X€R`† ¸€Ç‡ÿ9®W„xr„¥n!R5vDþ„u–`mogLx/{Ç…¢U|=(€h0hÀp0mp†˜†(„ëÕ~p8ð ;'Là².ÅVA'àb&htú§}õ2ˆ¯WˆcxÀ@dЈ, ´¨,°bx,pdp·ŒŒh€’|mØ;•{—è?Ñ0u ‚h\w[ŽÀX[ÇPJrƒHö‡©Gˆ`8€j0d°‰xSàŠdp³€SRÐŽ,0Ž»xï‡hŒlH‰Ë¨mt}¡4·ÕS¡Px.>rEå#(NؘF¸‚Ø^þ÷ˆmpÿcp¸˜†Á¨ˆ°càŽj8¨†SˆxŒ–“Œ™³É$‡¤ç6ÜöY“<ÚA14é Ù¶m;IŠiŠáÑ…Ý÷…¨ŽhŽ™†kpc b(’H’‰,)™$è’ü(þ(³×t§(‘Þx”'€kp€RÐR ‹,’V Ji’±˜•#˜1oȕȓÌWŠ[8–}W–(c0S@x‰©˜NI‹ôh•˜íh•dp—¨’ñ£|‡ñ•ñ–šÇ:h”ˆ’Ž„šYV[Ù™LÒŒ¡©…8Hš(fš©y›™©•zéšA) É¢ ÿ59X›‰›Æ„ºy4¼y° œ²¹9˜©H‘Ç鈫¹Eœ¹œ¶ÒœëœdÐG˜Õ™š× Dèš±wÞÙÂ' ÄÇoªxœ—©šÉi -Ù™éië)qÃIf¶Y˜éƒåù 牟’~é—  º  Ê † Р:¡Š~7Ç}a·ƒäŸHŒ¶¨Áx€´g€îŒp¹†y©œÚ ˆ/š:|n*€j`†÷(Âx0™¾(†W¬p’‘XŸ]±—\q1ª 3êž5Úk7jˆîH’g9¤, S0¤“€j 8 æÁ’Lê’Núÿ¤Ä¥±ðž» @kµKË©U›µÑP³?{³I;¶÷Z¶fûµ§¶Q˶•ص$ ·¦ ·NK·ph·!‹·¥ ·k;µ\ë¶Y ¸¤ ¸FË·Eè·‹¸£ ¸A˸%è¸ù ¹Ë ¶‹K¸´j¸V‹¹¡ ¹8K¹ h¹í º  º3Kºî °»²;»´[»¶{»¸›»º»»¼Û»¾ûÿ»Àë»ýEÐÈ›¼Ê»¼ÌÛ¼Îû¼Ð½Ò;½Ô[½Ö{½Øk½€ »œP5¾â;¾ä[¾æ{¾è›¾ê»¾ìÛ¾îû¾ð¿ï{Ð)C¿ú»¿üÛ¿þû¿À<À\À|ÀœÀÜ~ØEöZ‰à"0Á\Á|ÁœÁ¼ÁÜÁüÁ Â"<Â!\õË)—±Â,ÜÂ.üÂ0Ã2<Ã4\Ã6|Ã8œÃ:œÃÐÀuf«LÂB<ÄD\ÄF|ÄHŒÁ&l¿*¼ÃNüÄPÅR<ÅTìÂ=ܽ¼ÄI¼Å\ÜÅ^üżÄ(ÜÄU\Æf|ÆhœÿÆ0|Å[û¢Z ÆpÇr<Ç,ÆûÂjœÇz¼Ç|LÃl¼›žúÆt<È„\ÈHlÇú€Ç}¼ÈŒÜÈeüÇ.z¨‚lÈ”\É–Æ'|ÇdìÈœÜÉž,ì©@,Á—\ʦlɈ\ŠüɬÜÊÊȤ,Ä[@lµÜ¸,`]@ÁоlËÆÌüË@`F\Ä<Á]`ËÌÜËlVPÁüÌÎ,ÛlÝlÁM€ÌÓ¼ÌF`ÍÉLÍÍüÌÑ,]Ðf@ÁÄÌÌ ` M`ÌË,V`ËMpÎDœÊô°Ê7 à6+lÐ~P `,¬ÿÑ Ò ½Â=/ÀÂKPÑ—! ¢KðÐ-\½Â"íK Ò ÒÒ.œ+MÒ&}­)}­Ò  ­ÑPÝ m R%}$`*; Ëõ:ÊCÜ[AF a@F ÕMÍF@[ ÏD FZ­ÕlYkMÁýÜËA@Z @pÖ DÐÍe@e`Ö=Ø…}ÁzÍ"p×y½×o×s=Áu=ÁA@Œ-ií×Èl]MÐÖÁ¼×Z]·<Ä=mÃÁÅi@ ýÚ$àÚÁ~Û+L~`Û*Àÿ¾Í,,±¾]?}Û2ÀÓ~àÛ@iÐÂ2 Û+¼60Ü-ÝÔíÂMy!°ÉÍËÝÜ+,Ü<@ÜáMǽÝ4Ò<°ÛÐ}ÝM¿Í (³Í"$Üi°Û:LÕ3dÕBLñìÎgMÏL]€Í@@Á~­Ö ŽÁž}àÍ–Öl]ÁÐájÍ×üpM×á<Á@`ÚžË>Á®ÙÍ[}Ú,¾×áxÝ×]­âí<Â©í «MÃë­ÒÍí& 2/ -Ó»ÍÒ0œÜ—ñã dKÓܽÂûÝÂ:=Ô¶ ÞBå+<Ó¹-ÓÈMåüíÞÀN.ÿÓQÎÓ`ÞfÎÞà"¶íÛÒÂðÞPRçýíÃà$\Ëa}àAPÁ[àÙkÌPÖÞÖƒNÁp­ÕFÍ`pÖ@àÌw]Ál]ÁMPaðà_mÐÍŸê<ÍüŒË—ÎàÞá.é”néÀ,à1ôLã¡­ÕñLÚZ ã$¼ãÊÐã4ŒÐçDÞÂÉ-äs^ùÍÛ¿çî]ßL} -ü=å¹Mç¥Ò¯­&½í7­Ò.DÛ=æ•ÞÐÓÓ^íK ýã4Bç<ß¿}­MÛçÏ=Õ|x~NÂePË Íâom蓎Ï_­ÖD`Ì9éž Ñœÿé[pÖ©Nâ«Nð%^ÏM@í Ÿã"PèÞ¼à/™Žãñƒ>ñ½àØ<ëžàŸ­Ï÷ì×~=ð¨É‰¼É7LkîPàäá½Þ<0ÔÇnÛº½ÔÁMÒ*Ð"öîÞ míO¿Â`žs®ïÜíôXÛp>ôïà"R_îîÍôZ?çñžæ6 îBIîÛ×pÑRô4€å!ïÚÍÃýzÿ.ÂÈ,mòß`àÙnĜ֓}Á+n`ПÏi]ò5žÌñî\ÁŒß÷ü|ÏÞž/Ø’¿ê‹ßø•ù~Ë›=èzMãoò7ÎÕ­óªÌó4œóÒ}õönÿÔöíÐjŸä0íÂL¾ûËmJ]Ýc¾ï]ŽÐ6@-]æúNA¿ÂÏíìDnü·=îÔ¯ûß(PPüÇ¿Ý-ýÜU>çQ%ç.\çóþÐó~÷xÅ®9É üÕŽájÝΗácˈ@"ƒ„ƒFF„M`V`‰AD„e‚„@]„DaVˆƒ[‹œ"ž„M„FV’”† ŠŒŽA”]D‘@AƒVDˆD·…@œaD—…ÄÅÄ5ÊËÌÍÎÏÐ)I!ÔÕÖ×Ô$6ÕiÛ6KÕÛ~^/"LbÑ(CÈŒ™AÃn™ ÿŸÿýAûñ—1·ôç€Ã 8H`Èà"@X`ÅÄ€…Ü’`„"lÆ}ò×á ²Y2èÕ4wî@A‚AÖð K % 5ö@aÒŽÖèhÒ td;v ô˜dht'£‘.QÑ&yäŽ@ ‰ä’8†Ö£”;ò`O”¡…I&‹Ô€ç“M)¶éæ›p.£ž‰tÖiçxæ©çž|®YœËP†æ „j衈&ªè¢Þ©Ù›€F*é¤4ÍÙ祘fªé¦œòg¤‚2*ꨤ–jê©Õ8ʤ”¶êjœ–v*무Özé§€†Šê®¼öꫨªîÄê«ÄK^¬ÿ¶&«ì²Êâ§®¿F+í´Ò«Ó°Æf«mzD1ëí·àÞŠ"¨+Rkî¹è2jmNØnëî»Ê î¼ôÖ[ˆ³pB›î¾üöÓLkŠïÀîÊkïÁ7;n®åúëðÃæ®‹S»WìªÁ g¬±¦ø¾©/Ä ‡lªÄ5 lñÉ­b¼ñÊ,ßÙ±›‹,ó̇’É(ç ¨%ìàóÏ@-ôÐDmôÑH'­ôÒL7í4Óv,ülTmõÕXg­õÖ\wíõ×`‡-öØd—=6 ?гÎl· +Ä-÷Üt×m÷Ýxç­÷Þ|÷í÷߀þ7LJÀ‚'®øâŒ7îøãvŸðAxÿmWî¦ X®ùæÐÀ¤/¤ÀùèlÇM9é¨ó„yê¬ì9袷.»¶¦<ûíˬŽû.iè¼iíj ߺîÆ'žï‘¯üóå¿êÚз|õØ÷Ä< Îgï½NÒ Ký÷_OþùÌlg÷è·ÿGø×Žï¾»æÏÿ½úp²oÿ÷ð³+ÿþƪ«‡¿7éo€ÕëßÄþ‡@W °É+ ›Áä)°dÜ`zðƒ ¡GHšð„(L¡ WȲ0v‘" gHÃÚð†8Ì! èŒ ƒ@ ¢‡HÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢§HÅla!ÿ¨¢·ÈEÞÀHè¢ÇHÆÊ}1ŒeL£×h¬3²ñpŒc›Ü(Ç:ÚñŽ9¡#÷ÈÇ:ê±€ $ÿ(ÈBRŠ„<¤"‰ÄD2ò‘¬ ##IÉJ¶o’–̤&Ÿ‡ÉMzò“³ë$(GIJ͉Ò]С*WÉÊVºò„X(%%O¹­ ¸ ¸Ì¥.wÉË^úò—À ¦0‡IÌbó˜È4æ$ ËHÒR[¶L¦4§IÍjZóšØìå2› Égf+šÙ §8ÇIÎrþr›Üd¤7NsšS 8àB.«€ƒdr8ˆ‚žàÎ~éTä:‹ÕNŠB B. „^RÁÀÿôðÉÐ(8¢Í(@jÈ« Å&Žpƒ\Þ ¡}x‚ª€K%X´UðFs)Qš¢T¥u).c:ÓŠs£¤G_RŸVŸ7à§”ÐÐ(Ü?ˆ~ .(áPU‚.kjR|á©$jU¯šU£þ”™Aí(ÙVT³JŸJPèj*–r¡¡8€¨Bûàƒ’ÚT—7ð*Kû€W½â²¯nÍ&PÓÚÇ¡ºª­‰=&>«PÒ–°BȬ|×>há7-eo0W”â2°O8h ëYІ6²×\,c÷èØVA¶ÄÄgžªÐ†š¢‚øZR™ÆÔ´OhèÿöÊZá·Õ”ílïX[JݺÁÔ-„Àφ^ÕT(éHïú0t«EªE—ë¦>a¼B(ïy±+MéN×kÕÙuéëK- — {­g¨W\¾×¿ø|¯.ï‰Oð3¥øÔ¸p`x:XÀüý'ZïËÇêNj¿±ˆ5ÌáÆæ7g ±ŠW¬Í —˜º'FYŠYLãÛ÷Ålô°¤f\ãgøÆ8V£Ž#Åc·@r‡ ¨ ˜ÀP޲”§Lå*[ùÊXβ–·Ìå.{ùË`ö²\¬d829N @ÁÖÌæ6»ùÍp޳œçLç:ÛùÎxγž÷œçü°Ìr<3œfÿðg3€Ì€^£ ßDè:Ñq\´›]âGCú’n¥ èK2Æ'Ûô}-íi!ƒÚb¢ž.©K½äSW,Õ³]5«Ç˜éÁš±²žukž[§5׺Þ"¯Ïãë ;ØU¶yŠÍÑc#{ŠÊ.³êìgG1Úä™v:«mí'b{<Úæ&·»ÝÄoK&ÜÍ7¹—hî  [–ê^wÛ ”w—2Þò>"½boRâ;ßEÜ·Oú“œàà'X ”‚,ü08Až!ƒ 0Ô\,® (#â§ ”±€Œ3c(ˆÁ›þ ð! ¼'§ÉÅn(#ðø3T`ÿ8#5·¸Òf¹‹û<6ÿÈÿèmÐh8 üà&–·<ˆ/çIÌ¡ueÝã8×9 B@œŽ÷Ü2x8 †¾ ”Z2йÒ=.’x|ìTßy® ? ì_xÜ•1øËP§Åu®‚‘ èúàÎ÷°W½ÓWWbÖw²õgt=âSÿƒå~qä`òC¿¸NóÿaäË8AÍÙþ‹Ë>8GùÅeÐ ?Ȉ JÞG¾ôнT^û¤7ê8ï  xžwÐç]ÿýòžóËgŠ›×Iç|Õ[ ä–OÊU€qÔŸ€ìŸI ºïŒùOÿ<Á¯}ðó÷³ßù$·z€t¥6¥aqTwq|qq çs½‡>§xN‡z>÷x#u7€¡ÇsÆ—"V÷}~91~Ï'²ÇzôG*ÈvÔ§ P7‡· (ƒ6'{:‡s¸ÀwÇ× ørCysƒu÷pIƒ–g„Í—‚ö§ grå‚"ˆ@$ˆ&ˆxiÃs3ayU8|3ƒPˆÌÇt)°p7„:xs=§ 4ˆx(z`|2‡]‡„uÈ  yM‡Ou²‡p'‡É×&X˜…´…4Ñ…6˜6ø':aÇsëƒq…~pq?ôT‡r'ÿC  ;˜ˆA8y ·x(k;>ȆG˜tI5Ø9™ˆ>7ˆòW!#·v‚˜ÇˆDäˆÐ‰2Xsª×Šv¨›ˆqÀW†™ØuÃnjۧt3·„¤‡ÈÇ|PG3G{ó§z±³‡´˜Žž;ówÓ‡y(Pã02t‹WXŒÆ(DÈø Ê(z)˜‚æ  .8r$kø‹¯®ç*…F°w¿{< ðùq1°®÷2€‰~¨L7Œ^ØwI4À7ב¢r)’Ëð„ĸšçjóÃۢ€æó„籈90@90È’ÅŠ}…¸rú¸”’Ô”ðò”äøø®'J©•äÓÎà•ŒT–fé=hÙ j¹HlÙ–Øó–Ì—Š4—t =v¹ xyHz¹—ÊÓ—Ê𗆘‚i<„ù†YHˆ™˜Á³˜)H ™»#™©jYi™L‰F93™T™œJ\ù.  H¢9š­ƒ™Ž¶™ªù=¬Yi®ùšÙ›œF›d›£6›¸É—¥é.§ÙG©Ù›œ£›šIœöcœ±Æ›È©˜¿)X@rp…¯T%PØ™+”™Í ›Ï_T0ÒénÜY9E@ɱžìÙžîùžðŸò9ŸôYÿŸë9œÝÙ6µöE$žä9Zwžm“žöY z š î‰Ÿù©3ûIBþYž\( lC  z¡š¡Ê  Š2_” ¢":¢$Z¢&:¢b€B  pI¡:c¡£2:£íÉ¡j1ü©*z‘-J:0J£@¤j£7J0 ðJº¤LÚ¤Nú¤LÚ*Ú+0,z—.š3?*¤\Ú¥óI¤EZ=9B%@¥VZ‚‰r£ÈUé.[ê¥p§¨¦aÊI T¦Uz¥hÊ ¿‡ƒmº-o*§‚Ê¥tZ§Éžfª§ʧG(€rJgp=X‘'às)‡Vè&:¨œ:£…jÿ¨Âƒgšm‰p10|¬y)ò¸{±ø‡THtp²©Z«Êœ ÊE¢vp1p)P©( Cq÷«‘w‰*«µ'«oB«¶Ú¬ú©¸™±ôÒê*p=‘ 0)»z∂(€†y>ÇsÇJ‹Êª©êé¬ì:¤¸š«8AØú0®ÂöÊ@ÜZª3|çºv§~äŠzç:}’'ÌÚ® ŸÐ ¯ËP¯®"±úʯ’"j 0Š«TéŽË~Ð8s ') Û°&{Ÿï ±ÏP­XÀ€Î€)  @±<° -û²1« ÀA<« @.Ëÿ¯9ÛAb ³.ûÛŠÀAÕª YÀ ûÚ¯>º®'ûµ›²*Û  b0<µÎ°fSÂAö:´ 0CÛ³WÀg›0ûW·_Ô³_”<07·x;9_ôöš¸S‹­{Ë`)Á‰% ¶&û°¯)±’« ¯Ë0 ³ÒÁ¹ {8zûËÀ1kÛª  º9» 0¹H« ; @ºYðг€{±YŠ2—‹¹ «¹ª)±Y´ÂË ·±Ÿkp½Šk½;¹ž«½¡«½Ó« W@Zk½¸û¶ €½ ºÌ°µÆÛµÊ;ÿ¿ÉÁ¼£I±¬ËAª+½À õ*ºµÀü ¿ßË î¾7ûb@пÀû¶ À·Þ«  (•{ÉK¿Íj¿œY¯0¹¢ ºÒÁ>[¯W@±€=ûb° 4+*<»áË“ÛÀçûxË»<€Ä;­`Ã\;:ÌÁµêÁ– Â0+³_4¯Ê°A1{‘›¸`¯Xð“ÀÃû™£¸Øª»JëÀAü»!l¾ÀÛ³$Øš¶ÛêÅR[¼”{¼'SÄFÌ©H ™‹·Ä¯Ë X ³ð¼öŠ.ÛA@ºz¼³±DÈô»€À¢£Û»09ÜÈO\ÈpÁq’ÿÁæAÇu,¨w¬šŸË»Î0@¼ W0NüÄ¨Ü ¢jÊÍ€¯Ü µ¼Â Ë¢ê*ž\ Êq:Êcû=½L¿ Ì^*ÌÜ=Å<nj̄*¶ËÜDÍ,Ï ÍAªÌÓ =Õ׌Í4ªÍÛ¬<Ý ß Î2*Îãl<åüçŒÎªÎKYµãAÏ“r­])ÇóÎð|«ëì*,-)øšÏòÛÏÎ*Ï<9Ð@ÁЀâÐÅ"jd· ‡¼^‹ÐG,ÍÃ,¹:[Å0/,¾ÐÊÃ[³7›¯K[´Êð³K,´D+¼G›´ ÈMKÉP»Å†<­1 ǃVªÃ˜‚ѬÑcÛAÿÒ pÄ+¼³Û l«ÇèË· @·v+¸y»·r¼È;¸Vm¸•l¯l‹ÔØú·Ç|úÓh‹yŒÇwÓ7)ü,ÔÏJÔ*ÈËð¿+“ózmË“\ºö:ê›û+­ÛDZ;Ó´k»,±<`N ¿ÛÔñ{10}*€{˜H*૽êÙÁZ{1’${Ñt-Êv ±3Ü¿;œÂ$¾,ºê¹Û Ø ¾büã[¾ý¶½}»´Á¥Š6'Gîx„ '±ÃÙ€2׫mŸ ½¯­ |ŒºÍ@Ûÿ+¹œÛ»=Þ¬À Ü<Üý[ÜìÓ9éièÿtGxs)H|kª°ª]ÝpzÝÆÇbàÈ.Áζ'ÌÊ*ÌÂàÂ0,2|º™SÃ7ŒÞ;¼ IšÞ”²«jÚ}×Ü2HßÀ|¥)Ô­ß_ÚÚðú²oK±¢+Ù3»ÄR,±ŠkÅXüÑ+µ]ü_,Ä5LÆŠ»hÜÒ_$ÜîÞô]{! ©á‘Gß¾—¡}zÓß$ÍÿܼÇ}üf —|åƒ\È֋ȤÈÃ æŽ É†|³N[É+ È|,´½mÜÌ0ÑùC1¼7WçJ÷áúìÌR>åÙlâK˲üæ4q˪Ìʳ¬è¸,ËÌ@Ë©ì¹@ü¹ÆÒÎ>1â‚þÿžüM—pµŽ@˜Þš¾é5JèÓüˆD£Î¥nê([åcÔê;ñê°>§¨.ë$jž½ ÔÔ·.¤®ë©³«ÎÀì@:ìÄN:»Ú«E¾’§rM’+ù"èÊîÏÍ®E»ª½Ô‡ä2°?4²2)päë.×Ú¾í Êìݾ9ßN­˜‚¡=}—îÍ7€H¾†­bëÁ.ïón9ßþ‡ïÈ=²'IÓ«Åçîðι^ðösðËMWrpWrL§ GñŸÎñî£ñö~tž}¼×tÔQÚ½žÚ'ò*/E¢„$Ñq9wJ×qË`ÿ‹H‰ß9£¿óŸùç#ð·¾ôLjN?0PëR?õ¯Võðrõ¦žõZï”\ÿ.^¿é`ö¦™™º§päñ§ŸüîIoÝ)öØÃëÌWqmåqŸ¡gO÷Ú‚±®r)±—±»î'P{z)Gøêº÷Üî÷HÔó¼úg8YòÞJ’3á«*ñ4 x›È{Ò"e/è}/ùÍÇzpäZßT$í Ô6Øq™jÌpùòyú¨ÿ*¢Æ’)H‹ç›v,™tJNú¹¯ûaÛûGøÊúKüK®ùµGw°(Ž—®¸ïü ÊûÐ?äÌgq¼ÚÇ{·©ºÿ:÷«¾zýHþøà_×ã_D·†”°‚ƒ„…†‡ˆ‰…E~Ž‘’“”•–—˜™šš ŠŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±„3$²¶‹›º»¼½¾™·ÂÃÄÅÆÇÈÉʱ´Ë¬Œ¿ÑÒÓÔÁÎØÙÚÛÜÝÞ©ÍߢÐÕåæç”×âëìíîïð‡áñ¸èö÷Õêôûüýþÿ¤æ ÊqŠîÈá[Èp“>€#JœèM 0¥ˆÐN!¥ Aö‚1 ×/T4”ö¢Ë—0c²¸@Æ ?9þÀX°!Œ)jÊà©3OŽŒöübè › - AÊã$²Z€ a—ÿ»"@;vï8|QP̷̓pãÊ$… C'¡Â. !þ¤Ñ÷nMQÿäp‚F_Á6—²* †2¸êúºÙ‚—G,˜íás¯$IÚÎ]ͺµ¿ºw Id÷mA"¨HL"ÅÇ!ìæd›„í6«æªTgHj]º$%¡Víº½û÷Ûž¨%Èrß´UØþƒ·n„ vQ 2,†Tb'ø±Ÿr—çÈ©=HVæù¡YÛùAz!$b÷Hw*\8[Ž@Ac%¡VcIØ¢yl`"2X˜ÿéUÒ|@)¤+D•`)ÀÐßCéw[Rº-9X w  !,€ƒ–påÅ—ÛåèÇ4Ãz~lWÒ†`ùŠnŽÉ…– ¦Òo¦X¦x¢HÞWf¢ÉbZgFˆæ%?©è¢Œ&"PR'DŠc œÃnOæÖW¤Q]ÄÓFÃý‘˜™BY$d¥*¦ƒØÅáfZÆê‡ÜIr¨$X°\µæéˆ’—w{²Z›·úèV£Ì6Ë죂dTŠ“¤(xÊ©8˜¦®¹öè¦Ý>‚'±( _~™f›“Xǧ%9èaŠŸaj¨yæÇ¡ãîû¡%‰:+ðÀ¬A‹ÿ µ¢Ä€BN¦.G‰¶ß†;¸ðŠË®lAàªøvb$(à»áÊìgX @º_6Â/²ÿ*KðÌ4¯f0*ÒŠBCΓ9|•i¿šmZ*û¯™Q‚ÐŽ|¥Tµt&ÓkõÑ0øk±#ɦ³lÍ`‡=ÑÍð`´#(µ…Id½®Jæf}&»n&§$èëHh£ùZèÕ~̧#jJ¨ÒË\ÇìµØŒ7þ}þ˜­'Y[¹Êõ½cY¾/ædB¢¶Ï‘‰ù°|¶x¯yUëˆì½,Zޏ¡ñˆè׎×nû7d¿#9Ÿ!E‡«š?BÒyë®Òqx¡›$Ã;<€Û~ÀPÿ¡x|žò)®·‹ßîý÷Ùäžè %ÁôJ  þúìÃ"~Gäßc"úô«ßþýø›ò>;»›ñôCŸýòGÀed!²àA2p@S4pû[GÿHÁ|Ю€ÄF‹+X@ Ø )2@bDP¬  1À ºÐ¹R M¹~¤p…8ÔE _ÈCT\![Q þÐÀð`?DÀ£#þÈŠ†Hˆ<ÀH@±`åTÄ‚v„À?Ì‚5äÇ sÈÆÙõð±xÀxÀËŒ%$À‘…=€üã?0Çȱˆ"0Ã\u‘ÿ‡ü2’1^4ÈÛÈII쎠T, Ä?Œ’ƒ3ô ù‡; Bfƒ ®PFBÄ“¹¢â(ÿp1”²•¨,!5¿N` ¥2EA€ âŽgÌÀLÉ8r¸¢)¥˜€_â–´À7Å)ˆ@ X f&ÿ±Écvò“ËŒç9h ³ŽÃ4sE€~úSXÈVpI[’3œã|âÀÀØs‘+¦;'úxÊS™£,å)1)@ÞуèPÐ+@@˜ Å%9ÿC&–¤Æ ¿ÑNŠæÐ¢ ¥éhGu B D69ˆ…L3›—ÿ+ *„ ¢¥ýCQ:LvJÔ¦îÄiNሀ12€T•ªPŠ f%JÄV²’C€³„·d©8pE òm=£LÓ¸šbU…ZÝ*i‰D WÀaªXV`aÞ4ÆL½á׿R0°‚u¡³0HîqH“íFe-[¿df6§ÌÊ" ŸÐrc´¤] fOK[¹¸v°múL[ÛÞ¶–¯ôÈ­nñ1[ß—"·Õ†p‡kâ÷¹In6–ËÜs8ºýH@-ù¸ÝbP1Z”j[ç"]lP·ºå¸.véaRÖêµ E3›êĸ”×çE/5Ô»^x|¥„x/1ÿ¬ˆù²4¨¶n<ò«_–ð¶¿/A€aùÈdጩýê ¸h×Õ¾ÒŽpb@³ðASÖŒDdÆËÄ "XÃ…bCtˆ<D‹?XJ±"…Z¸Žu0në ,3`šYäÀzDGby³}@PaœÅ%ŠYÛ\äéIÄi®rŽªC7XÇin¹Ë`=h!?UBòÀŸÝ+1›üÎ'CY"°s+(áê5Wèã x°Z Ô’r-h"SzFW.q Äè cCX@Òx]"Jç«éŸŠS©¿LudÉÿËîÊBÉÊ`2£yÁßG‹ãŒqŤVMx 8Ù1L6ú™;6ÕÊØÌ¦8Mm`¹º:¤óœ%.ŒÅ˜B5Û“Üæ» Q^uزu´±‚ì•*û¿þ$Àìí„Æ *&!X¯-×|÷˜:¦s²Ámg:ô ü€3/-N&¼Œèb­à²½Þ»÷[>0^ WÃ'ºù^?Q àvPã*—;”à0é€R1Й puÏÛªaAHœˆ‰&ñêøK ‘¤³L¹¢­ ò›Ê[äýè6RœGV^á3ëÁnÆ$UÃ4G+5:Þ¡JÕ¨næ Xé|NWÿ3@î¶ðçÎK.9+Oäò%Ž@¤²t©Iî¸î>^õ{ëÛð`)Ëš•U “Ä;¢b3ÿD³Z`¼ÿ¶cpD°•òg-%æ¿LçøúÕYYªCÏêд^ñ¤äT«VÆ«{¶¶[Œo<:ym´yÃàVùüÄåⱬµeò‹ÄÆ"±ÞÜ2ká…}BXÉ y1‚ÙÇnÜÀN†°…ïÆâ¿Oæ7矈={y¼ÝH?2ÖÏ~™¹ÿ%Y ûPTˆ`j ÐbEWŠ7>ýwYW÷è úw ü×€žô€˜Ç0ÆPh ¨"8uõ‚#˜SX ÿ],Ø‚.ø‚0ƒ28ƒPX h‚~@|)ˆAb¤@„B8„DX„F˜H`ƒ ?:Ø<؃VFiTX…Vx…X˜…Z˜… „‹Ö„ ñ„Pˆ?`•„ðpƒÄƒ&(†cØ>eh8 jøl؆ëó†g¸„ü|`Ø uh‡ßƒ‡ï‡Â0‡ø‡€x;‚è„x †Ø€ˆ˜ˆµ³ˆíЈ¶ðˆý‰’Ø8”È–( ˜È~š¸‰bÓ‰ëð‰±ŠÂ7Ф6¦(¨ ªØx¬ØŠ4󊸣‡ć}¸ µh‹ƒ‹ ø…½8|(Œ$Œù§‹(Ä‹ÅÈ ÇˆŒù£ŒÜÿ‹¯0‹U÷‹ÒØ,ÔÌHSÎøŒ˜ ÛØ(ݨ Öè ØräXŽ‹rŽáó”ŽâˆLîOðˆ éØ ëoíxB’(¢EõØ= J¹ ûø y˜¡´ÊЫÐÃöù™ © Éh¹‘íÑ‘Èð‘©’M6’$Ù&¹ùZ ‘ Ø’=ô’’“¸5“4é,i“s“Å€’¨ ’ ö“@Bù{}Å“=‰”IùKYU%Ø“•4•$ènVy•X™Œ`†ƒ¨“Êå”4 •_ùZ™xÄØ•~iy‹a ‡d9]f ‘h—±–èW—æuÿ—™—z|) ð‘’˜Š¹˜ŒÙ˜Žù˜™'PyЖy™˜™™š¹™œÙ™žù™ š¢)š%—ƒ)0…™Š)°¬Ùš®ùš°›²9›´Y›¶y›¸™›º¹›¼©›%à—§É,©é>À)r‚œþ0œ¯@”òtœÈÉÊI$Å9oÎùœô­ÀœñTÖ Ø9Ó)*£p$„`ž†@ž*Qêé„0žÒÂ3:Q—➤à*Ÿ‰ Ÿò‰ ÜÙîð«l;A@A $€ž*€Lq Q =ƒšô±Tb¡…ˆÑŸŠ`TâÉq*ÿ'ª ÿ  ì  ªlª¢)à!)27—²) A'€;“˜² 1Q‘ *žHaQ @Zµp£9Á9º£…*Iâ@Á6Ê¡X*Hr>º¢2£°Ð¢.*0 Ó™¢ö !Pj¤LúA¨1;…°Sº ‰á¡tª1p1µð¤ BEÊ ‚aŠ‘PQ¦H¡¡š~`©ð¤Qa14°$€˜j vz§Þ§¨ £ƒS**º±ª¢Â£SJª‚°Åú«â~€ ŠªžUšÿªöÁ˜"** 5šÆ¬Úê‚À¦j­ :¡A¬Qq¥†A%¹«¶jš¸ $ºz Àf£’®Lñ§!à®!`ÉŠ¬’¬iQÈj4¢2°¯éJ*p$Ù:žVaz­ +9°j¥I¡°ó‰|¡¢¢¨¬Ê»!±ØŠ¯Á*«¾‘¨‰!¢©p«ñê À‚sÆ‚P‰ái Hñ‘?ú¾Aµ ;B ;â³;¨X’›ôµk¹«É‘Ê0šV›^;:«´6q±9ñ6ñµXË$H˶f˶pë 0³Ê@EžÄY Á ´|ÿ@Á0î°·…0 P¸†{¸ˆ›¸Š»¸†›r ¯t»nPCXn€³Ê`Ÿ†5a$ð¹ º¢;º¤[º {¹­0·‘‹ 0„ Àˆx eª»ºÆ°C¸°k‹³K»Ä`·B»Ë ¼ýµ»¼+ “„–›»­H¼Å{ ­ „¯Ëˆ«Ù›Ô[½Ö{½Ø›½Ú ›¥Ù¼c»@ˆ»îð’Y¾æ{¾è›¾ê»¾ìÛ¾î{)ê½â»Z!¼ò{¿­q¼Y‘¼øÛ¿ó¼½þ;À`3Z!¾œÀC¿ö«À,ÇË¿<ÁŒÒºLÁ,$ŒÀÜÁïa· ìÁ"ÌnÀ¨;ÿÂ(¼sÂ,<Ñ×Â0Ã2<Ã4\Ã6|Ã8œÃ:¼Ã¦ 0@ÄB<ÄD\ÄF|ÄHœÄJ¼ÄLÜÄNüÄPÅR<ÅS¼%ÂàÃTœÅZ¼Å\ÜÅ^üÅ` ÅVL )p.pÆhœÆj¼ÆlÜÆnüÆpÇr<Çt\Çv|ÇxœÇzœÇ0ÅPÆ{È‚<È„\Ȇ|ȈlÇ}Œ eÜŽüÈÉ’<É”\É–|ɘœÉš¼ÉœÜÉžüÉ Ê ì~LÆ ʨœÊª¼Ê¬ÜÊ®üÊLÊŒ|ʰ\˶|˸œËºŒÉ²lÊ»üËÀÌÂ<Ì”ÜËÆÐÈÄœÌʼÌÌ<Ê¥< ÈÜÿÌÒ<ÍÔ¼ÌÆüÇ´\Í¢ü>àÊ>ð¡ìBÉãœÊ? Bp7ÚÜÊ×| ÑÜέüÍžLÏ–7€Î8 Ê8°Ï’Œè,?ðUàÉÜÜ_ Ï—üÎÐœÍ ÝÉ7ÐÍ®\Р,Îä¬Ê7àÏZ ýСÌвÏÊ>pŸÜÑ“üBð}ÀëÊý<É8`ÒŽLà ÑÝ|Ó#É ÏíÑGàÈ8@}ðA}íÈÐÐU0ÐJàÈG€? ß|ýÍÎ\AMÕ?ÐTMmÉýÈå ÖZÐc=Ð> U-ÕI ÉýÈýÔ?°Ô}ÿÕ7Ô:½Ó}ÐÓ° ÒíŒ×AÝxÕLÔU@ÕQÔA]ÒH­Ø ÖýÍ?€GàÕ–\BÀެY½ÕB ÕˆíØ}Ù} ÙyÍÕBMÓ}pÖ~]ÚaÍÖD½×}ÑG G=Ð(­Ð‚Ò?ýÐGÀÎêlÛ?@Ô_`Ò­7À.ýK}Q-ÆÔ6íÜ ]ÛŽ\ÒU`Ò\Î3Í*ÍÒ”ì Îê<ΚÛ+=Þ_ >ÀÜ Û¹mÕ>ßÒ½Öø¼×ì¬ãlßË ØŽÜ®@ØÚ\Û8ÀÎòÝJPÝ ­8 Î_ðöMG Îݬ׫ÙÌÓß“,ÿàÉÍÒÚ½×_ 7ÑŽáD­áã­Ò Ðý<ÓûLàX ÞâíÏã¼ÔàLQ­‡íÑ>ØÃ­ÐDŽá&MÐBpã+Ñ1Ú:=Îå|k]ÒTÝÏ?Pä%­ÒG°Ö«}ÛJàÚ>àÍágnÑXíÈJ@1]ÒJ-ÎPnÞ¹Î7ÀÝU JÀÜhÝOÞÏ+màGÎ ^Í}N—èÞÝd]á4]ÎÝMÓ n×ÝDÚ#ÉgþÛO»ý[NÕAÍ>@ò-ç€^ãþ|vnãžÐ€^ç¼-æSþã9ÐB`Õ€]è žä ½Î^àÞÏ.íSÞ þçWÞÍZžÿÙý|Û±mÒO`Óï-æoîÈß}^.é«îêB}ãÓ>çÅŽ ­ÔþüÈÝà®ÛV~ãæNèÏ, ‡^Í|¾ët.îÜ.äîÈÞ®êÉîáË>íªŽØê\äZ æ÷=êC½Ñeîâ‘Îês^Ù4ýß³~ãämíOpë¹ë§}Ü#íë­Pïíœ×{×KÞ?ð?°ÑŽLÖ«ÞñÓ>ð•>é|>çí è¿ÍéÞ>à·ÕqNÓ#ÞÍ*o×éîï/âlë-ý×!?ï>=ÒGÀÒ_NÓD®êS­êKíÜŸîG@Ôô-Ý }›^ÉÎmÞNóQ€ŠêBßÍÎ=å>ÓêÕ)ßòŠ-ÿåQMãKmÒ8 ëÞÜPßЮìåÌÑÓ®Îì|ÐdÏí«çm^ÎMÏd?×ã,çyÔ3­Î”=ÉgôÒ×Qç7ÍÍ%­øœÙ‘œù^Ò]nÒ§ÿÒòŽÍ#½ÜyÐø¬ÎÎ×öìú.~ÓýlÏÏÎø\ÕVíôÿŒç}çà¼Ñõ7íûÈîÏ]Ú¬Òg®Þ‹ÏüE-Ðy½×»ú7Ðù‚?Ë…_Éç^Ë_ÙGËéÏÉþüÝüþ½>øÂ}þóË\pÛp}‚ƒ„…O…ˆ‰Š‹Š\Œ‘’“Œ.˜™š›œž™)”£¤¥¦£ZG8ˆ8«§¯’Jª7_°¶°–ÿŸº»œ¡·¿À°7JJ7‡ÁÈÉÊ¿¹¼ÎξËÒÓ‰\>ÕŽÔ°U>ÇÚÒÍÏâ›Ñßæ·>×çëìÌ—ãðä¢íôõö÷ÉáñâåøþÿÒ·o\?*÷®à³ƒ #JœH‰ Chó(jÜÈq`Ë» vI Eº0àÀ²¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ>0@ÉkÁ H“*]Ê´©Ó§;…}Ø€„Õ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓ¢}Sdª®UÕÊK·®Ý»xó’eë–W } L¸°aÃ$fþów±ãÇ#K.˜rãɘ3kÞ,¸òáËœC‹ÿMZ“gÇ K«^ͱâÏ€[ËžM›òkÔ±këÞÍ;Óé©{ ^ú7lâÈ“s6>8¸òçÐ 3ž;ºõëS§v޽»÷gÚ›WÿN¾|§ðn¹›_ÿýöñìãwwOT½üûÊ駇¿?rý Ùç߀ºX&H› ¨àƒÅݶ˜ƒV¸œ„„Qhᆓ1 ‚†Ø!†â‰hâf^¤á‰,–b<+¶(#J/ãŒ8îS£A æè£C;ÂØãDŽäCC©ä.Gò¸ä“ñ4éW’PV‰‰”HZ©¥.X¾Eå–Kv9ed0¨`¦™š¨@Ã'*Àà Dà&o4¨¦„ÿ•y¦‰éɼèyfšsvÒ¦'~„ ÑA…ö¥¦.gšÉ'QeJæ§—‘`Á§Ÿž€‰ Dð ¢r²¨¤À[àù (æ)¨(ÄÐÛ¦½|ùÌ­ ¦:«°œ ÚI (Ë›ž&k®’–Ê&« à*J'Ôú‡ ×ÆëŸ¾•í™)X¤šê‰±ä´ª žÊ°¬²Òj+ fÊl¤ ’( »Œkf¹ç{*±˜„`Á ·ºÁ@ë¥S¥;m fæ°/¶Ú²ë­¿†Ëq&9Hk1c´.0'ª j§ö^‰1&0,ÀrÂ'Èp‚Ê'„ *sâÇÏ'ÿ¨ûGÙÍØ:çœÃ 9ãÌ/½™ÄÌÔÝ.BË sgͨ2ºI¶ ÄúÇÓ7cµ Œô ÐFö­&ëB6&%«ËîÏ@¯\´Ë˜L м€]4ÍE/p =ÿ¬´&C§}v¶'ä€I LC-ÃÓQÿÂ⛬ZpF¿7Ò¨Zþ‡ÖÈ2ªsßè>ë8''ÿá)žD|5ìKKm{­å]¸ÍÖvr‰e'Ñ£J[n 1,x«Ñ‹JjÜÓêºÂŠj ¤Z½¶šdC¹¦F¿²(ðééßÕ²Ïg˲ª½0ÔÍbâi 妚l ã[Ÿô`†ÔQLÚ’˜`³¢ÝîÿhX@ˤ=:LnÇÛO_”æNTÏ«Þô,è?„a‚€Û{VìPµ€ðY|™0úζ°xÊrï›`®G¿MàS@#Ü*XÁmµªe«Ö A$®ð|Ì©$§˜y ŠòúYµu7ª‘-x ø]ƾ̭Wª­he§“¹ 1cÙ`e4MDOuö‚ÕµH•ªè‰íJ*<š›Ø%zÊMžbTôê· ï­±Z d¹G.ÖJa–ƒ#öl§ÆO]kNtœ•¶òf0”i*ƒS©Û'šµF|}f…‹cªÈÆÇcYµ _óúh?FZrúÝšÈIDörˆfÿû lªWš]ðêì$¸ß]I^×s¦;Á7ÒXÜ#źh¶»±‹VPÁ³ƒÊ¾¨² wC—±,¶5:“–Q,3±ÈPÆ.U¤Ì„?›7cÝíTóDBE AÕ‘òœ–„à#ÆÁE ”Vž2»,–¬G2òcYÀȧ‚sŠªž²Ü'C¥¨RdšIzÿÄ›´:Óª ‹l5ÛB;1'xê\¥•Ùø–,j’ÏjÍÓÂÒ5´ †O¨µb¡EN;™3Uú¢Ùi‘^$ž å( Ù±Yv kòœ Ë…§lùÁŸµ„àV ©®E3’®Ê©vÚÈd2”®˜ˆžÿ¼ ºOXÉà]‡* f®Hjt”Òr™ rðQÇ-`M)­ÈzO.Sž L¦[ãWÃj°G£äQk¥WV6phÅ`%KÙÕ¡Àr‹\éJIp®“y,©ú3™»K38Õš®E®Çü@ö¹¨L^ãä©0ŠÕú*«JaU´ññé‡'pT!¨.R•JcíëIç°U-*‘ÈE¨Ù>75¿VRÙu¦£º0üLw-¥i¤)-=NÐT¢Cï)CºÁé"m¼›X~Ky·æj‚ò¯x­ SóF½|Â\4iÅ^WéÑ¿Òj-Õ軉êUñ˜ ¶W¶¬r\«U^íóíRgÿ Çô’8³eËeÌh¬œg,ÃJºXA7•^uñÖXÆ’¦£6ã“ðl{Q%ªn[-cËÊ«ÄjÎfx s&˜‰‚3kËf{ue51ç•ú£xÚrÌÐ æø©ªÉÌŠ_ñP·™2“a ¾ìT¦œ²ª…‘};óqù<¹Ž-«[.i•ËÜfLðùÈ[bG¡Åg8Mήl±³:íéd!Ô?, ffyê­ŒR,àE­›­-3nÔi^ØÏìÄçàù½µ6ã“Ä~í‚<ÖIuál}ÆëtFµŸ½‰„`Mµ³v¢ ó΋lQÕ>w-Ï-î4¹%±›à×kãíÿlÓŽ쎔Ø ¤e£¤Üɉ+‡¼—­Ï¢Èß6Š2m&Ìœ‘ W e¢Ï ¾ÔÌÃqÙLÀ 7ƒCòœä"Ú8(:Žò™œå-ßÊ/ó˜Wèå6×ÒÌ9žs+á¼çPÚùÉ® Ÿ]IB¯ùÑýcô¥ÿ(éN/RÓ£Ž#¨SÝGS¿z‹¬®õe½ë&â:ØYôõ±sHìfO9Â÷1ô´“ín—ùÚ…÷°Ï=áuWûÈó.÷®òýìwwÒß-÷Á¨ì†ïOá¯øÀóCéŒÿãáÑöÈK~ï–gúäÇ!Ìàó ½èGOúÒ›þô¨ŸÁÀúÖ»ÿþõ°½ìgOûÚÛþö¸Ï½îwÏ{ÛW -‡é|ê‡Oüâõ½O¾ò—Ïüæ;ÿù¬ÿ½e⢗ê“À °¾ö·Ïýîså =˜õ½Oì“ÿüèOZÀïwá¼ [™R0¿›÷Ç$$˜ÿc*ûß_þô§þ÷:¢¸1H€ðX ¨€âÀ€ûyñ€è HnèxLb€ HèÊ‚!ƒ€ðG‚Ø~˜0qVq’q¡1‚*È H¦'''iE4Xƒ¦a‚˜&Ÿ‚MŸRG¢ñƒ@x%Bø/Õá=óó)ó–J¸„7¨h+dbè4*sR'èÒÿSi5…DQ…@x…Èc?5É”X^˜X“M†A†5h†8¸M?c;ZÔcÅÃ5É¢Q¦B*br¨‚tøt4a”+±¢‡ZXp~;xƒH‚…x†±SH%¥/ 8‘'Çd,ºˆq˜‚KhƒMhˆÕ2S2*À‰?䉔$*¡èWƒ1‰X‰NH„%õ30ƒD `3ŠÂE²ø‡´(¶x¸e‡H*Ã+)Œ-£?É£XŠ\rŠ–ˆÄ3+o3*§&ÜhD‘èǸqRGŠBq¥ŽŸ' WuØ]jS+´>±5Þ¶3˜XÖè ÉèNÕˆ ã*¤0ÛÓÿ>úˆæó@…QŽñ°*é5=T5ùÔ ®&úÂùoOX+«rX±‚Y¶¢ÒÅI€©Œ™0q40qŒbQ2'ߥ.ÞV8q'=X‹¤8 óY0*sòC¥ ÉÞÑñè’Wb*Ž“/¸-618y.p"'Sù?ùÓ”‰‚ŽŸ-Aù)nó)ü–”«±”«Ñ’*²‹±’ÿ—)–Ž‘”«¢†e”?Ee…–ҴFᥠhS£8ÆE+Y„Q_&j)Sm´¶0¸†D[èp`y—îוÿh—‚—‹á—É=™,} Dµ20G¨Y-sRH@DªÙÿk@D›Õr)·UÎ,Y.ÜdBŽá™l'—‡A—÷'œ Bœþ¸°²ˆŸbjI–›çBÕ5=©"‘ŒRRã5”…”þS-v”röœFÔXÖ ašãƒ&°™!V–’™Ÿ¹™^yôÉlö鿥(¥i.Aé&™ …äc0õ?™âA= 4+f^{t„«S‘F4‘tf¡~\M¶ÈIyÊÉ•÷iŠ,ÈÆ9ÿó>Á¥5ÿ‰*ø#…j=Ê ;Õ‡Í3S¡.ª†)é–1š¡*7ù™œ 9¢LX¢õÇ™‚ÁJ3åHÖQøƒ?ƒ$=;J£j£@¥£3ºÿ£R:¥ ÓWGSö3¤ñ¡‚×'šyhJwûéÍ©–9Š–ú’š”ª6[ƒLÚœÔÄ¥€j*Ú“bCY: šR¤x÷¦Hú•J*€L敥ΒLAéf'°&IÙ,Œâ‘´0k¢@áIfªV€©„*Q—Ҝה‘:mš%ŒŠ¤±š¦&úª}á,¸V¡Yz+> -Ii”ܤ:¾)Tâ9=¤š¬Áu?òÉ äéY¿‰™!8kjyµúxGš´`@jÑÄLÕb4v%·09AÕò8—Édåu™ƒ DHX>@ «†«°ª¨Ã™­#z­²ª¦öªh ~oñ¦NDÿ°ÔöQ+­X¸¤êøj¤³º¯ ¢úzŸü !JÕyû üWÿÊ ‡9²ÐðŽÛ1:Î`3ñª øu5üÂb<Õ3ñF³”Q±ù:±‹³Øª³Øfœq8†q8Hà %“âÀ,ÁÅH|µMHhe8ë• .UË GCC2p@*  RD9p)a;'E2àl0@$0'0õs¶,K¶“>aêµëD6„'ØõGmû¶i‚çr;^KS_£ f[*ØU(1 ƒȳë³)¹›µ» /[E3âs[ú#A|†Qº²3-#/øƒ,HH9a”‰Ó—7òÿCV%'ˆÙ¹Ù­a¤/ç3V¿³3ƒ+¨Ä»T3>$öOBe9ËtWË)¹v§¬Ñ±Œ·¼h$P¸ÖŠÏk²‡ˆ*1p)t%Q…k®¤kžSFÉë»ÛBQeGiÕ6ê«“±«?³{4¢ò9²µ¹[‹b³‰¶³«Xê*…FT@òä*|T'¿5µؼUs½›¤X¸µè"´œaœq›e³çÈ»èÒAáÛV©[^UWö‹¿ƒq£B>ˆf´¢Ò@1àlG[RÍK´žày”LŽ¢¢:FÒ‹µ 8—ó‹!Æ6 Mƒ9ükŒØ«»°'²Ãtó„ÂâS?<ÄŒ!ÄD,/5³>Å™ÿÄGs@‡saçH0#AðBM<6 ŒÆóxŽêÈ-ó„Âñ Á!`3)øÂ$ÅZ-k¨yV+^d-ú"£J¥Ã–Û³»„? )/:ƒ‡C”©0Ü6“³œ(ÑJ­ô8Û¸ ìJmà®[7È!ñ‘`º:ˆ|’®bC<+v=<ZS>¦K8~Ð=ÂÒÁu-0s·£²E>‹Â·-ˆ/pT5q,*Ž’f´Â™È2Ü ?Z®•Mµ”Ã4ÂÉ—›k•B1Ä8{¬ÜXEÙæ[©Ô2‘5ê WÚ YÅMyvÒ ²P|&‰ŒÂØ|4ÀjecÔ¡ÞÌÅpDEœx6m/þ{[ËÔi©Ö‹>5ÿºi\>Fsq*Ð2ƒ”Núh-90l¶¬‰sX"Fg©Âº^ë¹ÉŒ¥¨’,3+Dk€¬MÊ»Î<¸wÊ´ð‹h:8+Û̃":®V)¾©.ãl(3*4ÎR0ç ¹7‡ÒìS,m;>µWzCÏ/ͱ\MsœÖ\Ž,[ëC90“=øÊL“0bC '¶ º>sòVt)¯Œqßæ9b£(³=ïÈ[zÕ^­ Š’Öb•Ã?qk*2©6(%BÍÎ*½À®TË.­7Hý4pÄ}ñÍdЬuêç(D;ª(æ V2âû”U)Ejâ(Xy(5Ýœƒ;¹ ‰'›‹&oÿ„ã(u¯˜WÔ²ø2¬¥ÔÃÒ$ðÔν‰çÄÓ{ÂÎ /Š#/-t4ŠíSš“ÊÁ–ŸJ8Ê›æI•:‘…ocÃ*¹b‘“)U;ƒ+›« «Â*qsΡ‚'ád E ’Çø7ØGgÕFÆ5ÉýÒµÒ4ˆ6Ó+ÜóÝ©ŠÄnñ¥Pcš†ª-͉Á¾Ù[ "A¾y-Э̟òº3ºj 9UÈbžªâIvL%?Å ní®Ï¢C´Ý°(1à*éÛÇ)ßC½±>YàÔ¢U N3숣æËÙœ› Ý¢ãô)ªÃ¤(×B¨R¸Õ’V°©+æLÍê üV€Ó*ÀmÿxþĘ –¶<ÎBUYºÁ·BŒ5¥¢A ²Y ›”Ù5Šæš”5”Ø“‘æ•¿0Ê ãh$0¾r]n…}àþJã#‘îc¡àê,fäáÙdBT£^êæ½:æzN;;ÍI¹”ç~Z¦{¹WÞY>x[îçîV·ªÙ³é~)‘¡‹n¨Ù)§¾ágˆ HŸH“\&$ç™·—ŽÃšì)͘G‘Rå˜ê7ê4G„_fÏìâwÙéù ¢‰ë:¾Óhâ™Ú‚·"/A©;†îêòzK'„àñæIU#ìSŠó.®RË«“Ű»Å4^ã ƒ›é µi¥ÚÙ¾É*ĬÒ-8šà¼9¡@ýØ+o9}[NÔ¦2ÇRÜ£ ¤2Lƒqy•+¯÷dßòÍ.Eofø2(2@ʃ_8@†ì’ûÑ1ûÖQûO¨.ZsÛÊÏü·ìßJúirS‡»0ã*œh½¶ýä(ýÐAýÑaý„î¢ÒÕ0|þ«c=}Éþ/)„…†‡ˆ‰Š‹ŒŽ‘’“”Ž$ •™) †0ƒ„0 „ ' 0„)9!1„ ™’‚³¶·¸‹0**¹¾¿…—ÀŠ›†!!…2Ÿ¤¦¨ª¬®°²ÃˆµÔרÙÚ¶ÂÛ…ÅÞÃÖáäåæ¿ÝÚàç·ãìïðñˆéÞëò“î÷úûÛôØöüå H° ÿ7LäL4p¡Ã‡‹ü]S‘PÊJÌF±âÅŒ nÖâÇ(ïœÈéŒȸ‘Àv2¥Mv+ô"‚Œ[$f^«y³h¸œ$[:‘"B ~fE˜F¨Ñ«Øæ²çEŒ)NØšJóÖ³ä´êTúG…XB1bò2Ä+*¶„ü¨ˆ:uWU³hgS{ËžÓ¥§ÚöÊ;÷ÏÝÅ~ÿô] ̪àË•oeûE„Ä„NĈ!ÊÏ §P#œ8‘CÆiÖ¼†³m\šgÙ#BFÔ¥£Eå8=[5ëMOø‰cvåÚ·£gFng (…øô†ª?'TîÕÏËVàÿiK_Ÿ)·&Î$`—µn„‰QHnCÿŸ ã½õ‹eŒÜe ‚`" ÒàB™ƒ"2!^ìýG]=œâr±a‡‚(¯œ€‚xÓøçÊ4á=—ዸWIG$œð’ˆ#~HŠ~d¹eYà]Øt“~…¹¢…ÒÕ¤ˆ¨èä”Q"¥t2êÆV}ž†ž<}*öÄ¢¶ãzYNbÏ?­8˜ ÄÄ£,Pzd‹)IL %Uƒ2™”]&re¢… jÈ•‹ÞÖæŒœe§‚k9˜–ƒ[9lwio@6§B _é⚨&2i$»y¦ `²Æi*<µÿ‹!pº'𳍩ê+ 'Z¡1”‚Â.#®F «‰âc±ò2b´2[J[bA{lg°l;í¶Ñ­êf‡ÛÅ  N Õ“ AUHOȸ»J‚¹øš*fâ>²Ó+ü†®¹ÜJB4È;¨*ò|*0`rìT4ˆ2¨ þ-@ŨäzBÄKž¸ Uÿ‘‚ÆêqOõ‚r¸nSÒCöÞ+X¾Ž¼ìPÌø—™ƒåê[05úI|>.w,þ© q[C[,–Ñžu&¡(I/mÍØ¼Î2Ÿ…5#ZÄõ"A‹üR¿½¡”J*Mˆ2nu%ƒÚRcÛ¨Äp+—6YI‹Õ7–-«Ó!ÿFcwmÔ׋„]Pቼpjk¿µ@ lƒ Õ lžä­ü-áå™»åäuû蹤s4¸G~ÎfêIÙÄ8"!ÈË3Ȥ‹2žrL!èJá ºÃ9ˆÄ½ƒòJ,˼ûñ @ß<Ëå(dû°[·î:õ.“»ZLbk¿ýÕ°³ti¼¨–ýøk"N g¢ñBêúì¿è>ØlueH Q½“oAëÉ)d ž˜Üê$š¼¼C ñÕ/0÷C„=lg¼• €Èàdõì‚ D†o¤HÌî‰àûŒÑ$¸¤`Tƒ(ŨX(ðXŒ4ÙT:ó„oI qBj¤|ÿk© ¡\CΰS~{!óP CdXʇÐHOøºê±E}VZŠizÑ0©ñI,§ðÃWêöðH äâáè {œ¦J¡£d>¡ÿ˜B[£^¢¿øÀ7ô2؆¨ ð9Æ‘I:Ä}G/…B‘Š´$÷ªÃ–?ÚS„¹¥ÌPxI£O d€ÆQŽ7QáþزÆdÑ”-"S)&²RLQB²X „xȱ4å;…JÒ$å¨B@*| ””Liv1!•¢ xc ýä’”'ʉÞ"H`†¦[„%ù8dO~®3Ý R2ûHˆA©œm‘Å0[HÄWêbrÁZÿÛb€Ä‹S¸%2P*¨Ãôòÿìb1áTAbZ¤—~Æ¢‘ OcÖ‰ÍCäÀ+ªi…j^ÑŠoòr5üêŠS`Qºi‚ETg@dù Î 5?)éL*µ©†*% ÕÌÙ™Vº(9ˆA°d#²ˆ&6›ÊŽ­|ôT*r ªRkIÁóš’ª`8`i*S%3V”’Ž£œTÕÜ€'QP(È@½ˆhbôr ƒÂ@q©?e š¢¢Cæ*[“˜á*{aL]1ä˜ÐDH {…D€PDƒ˜Låž‘«lÇî2©ÉE,¬qŒ7¿šŸý„Æ´é íÑÊN_DÓ4c1ù A:n摊ÿõJûÈI×szD'–àÊB@ôŒÏjIJ4QêÈDÉÓ™ø”[¬øu–¿Ðä#>S‰˜å+¯xÇKÞòš÷¼èM¯zÑ‹€ˆØŠÛ®$–“ ï&S˜}¹Üeߊƒêi ð[gfBÕÅŒv‡RÛÕ®¨‹:/Ê.²·±ÖKá [øÂãmÀ ÜÛZ”Ø÷§®TTP£ö¦F»8ÁˆK\T¥Y1‡£òæ ›$ZÙJÁÓ5pƒ;š’Ã@²WÀHEØ /‡»÷`j@mQq—ÿ`@°E`&š²;'}N…¾,ÁVeuÌÌ–œ$Z®[Ó&¢)²œçlÿÞ¼÷ÈIÞ°"®߀ؗ¶ñ`ó_Ýlˆ9–wF2Z”¼ç÷fu&0 "h‘AfÐ1ôšç% ŽÐ“¾J¥ûÌhÚkœ^´žUåh[zõ9F}é›eúÐ6Q žUíiÕ:?d!Sú5½CXm—.Å•GÁˆäEï´þõNmÝTŸ…ѬîpH ï'}bi&/å$^ÈàrÕµ[£øi¸h÷øÖ›~Ä®¯½êy´ZKÒž ó#ªè§hS±S6pDµèJÄÖKTá–…Ï݆7" ]+šÞ½þG­é7 00I”³üVEºØä´ÒhˆëæÌ*ÿªÀ!àÍ.`.óíA|Û§’"Ìó£öÃÚXÁ¶½µ ’ÇB5#¤üŸÎÕ“rž)Ñ;ÈÈÁ…÷ÄuûîýhiS{ÝŒÏ#Ž­ ‹wºÑDÏȇ©22uû—vë¢(x¥·[}b@S3ªn^ôœƒ½‚¤`no0GŠŸ ‡žÈŽÐ—ÕÄ0439´œEözý*B¿$×)•ï[()å˜-€±…(ÇI ³•«œÍ7ïw#âëŒzº4ÅÞ‡a3±ZÈÂCA‘ÊãLÁ\Wî¢0Š›×hg²ë‡›å†[o+jÜ»D±åzk¹ *,RŸ÷Õ;xù….r3(Ÿôquÿ5(¨Ýˆb¢{ ‰ÇZë? h –ë¤ N7òŃ^oͧp’Ö4À måVtH”aWnE€ÀÓV‹åwQXô"3|§v~{Nc$v6B€2L¢Ð~® !'Q~ ¦1'®IþçóÆùG ¯¦±&kåpøzâ§Qu]uƒÐ0ô ª¢°1·65r#ÓM¥bàye|—g™×N¬7.‡ƒ}µ…œ~…{â|ü MA0 0Т ¡ § ;Àó Áv=Óp¡@BhXl/Ø1ˆyý§…ÿÇ:^8Gßq<o0¸€8ƒ±#†…ˆ:Hÿˆo¦u’x…E‘…Á†¬²qás ±¥Ke- WyéVM""wä6xä}<†ˆ•¨ˆ~Ȉ‘@Ä6 š• šhyƒi…Q à$¼¡naÄÔtPÒ)¦(ì3‰¾‹¨&o´ØsGgU™ n™°‹Ò‹˜v ž`5Jòob„,UTå h( äˆĨQh 'T®ãŒÝòõ#‰ ]ïB/j¦1‚‰Ž "H ‰%!~m7É+Ž |手€‡ðÑ0¤c:w!H?QK#Š§Ñ„˜ƒL3rHU3bƒç‘÷B¶–ˆðLˆðZ¦Dn3éŒp|“°†ÿ"-RUªÀ,¦@PG*è–¸‰Üø’ÌrSõ—w£òwgstk¸n¼(š F2zSÙ5.Éqch‰VÂPãöP³w!r5n•–EŽ #âqþ1¹È7w'%D8ùIɋʋ C_AU#ƒOˆ’P9eCŒÃá#Ò ’˜*aù‰ö±`Uú¡U;ug]%5`5fås “™ /‡#´#LMª7 ɉY#‘±v ò›ƒ L‡(«õÊà ø‡(Èa:oã•ì#•9‘0ù(ÀYöYà¡ «ª@ôTBÞDÉ™|³H ·äL‰Ù|ñš‹¡ÿ1K"›¹‰s½…#­à6¾„CUc®±†²ðvË""”‡9¥ð¥SyÊI›’Pƒ÷`jdiÈ%5Ê¥, VÍ…1Ï5ZãöÒX °óãC£+|u€¢zzç—Ž *7‰eG èu êLÖSZ:V“=…9v"O,÷¨) ¬t 'Z&…ÐA²‹îR¢0›K)–,ú…‡èž—Ù^qr}´)×Á£Rµ2úacPñ ºˆg—míÙwQšËy›ÈäA^Ö/ôa „f–õASYv* ?Š…ë‘]¸¦ Ѧ~ö¦ˆv¡È‡¦Ÿ‰•P„:ÿ.Z›0*‹Œð‡€z¢Iä¨Er$ ÁsúÀ¤8©úb›‡Úœ¢—)á¤iŠ·(ÄDT÷  íFª5cª¥†¨¹¦ª(Áª*˜í, *¤¤Kºd1m1‚½à6Èê6þÁ7+rn´:ªSª¦UÊÇVy)ðXÛZA‰Ð­”𧙨¶ºBœz bg¬Å NËj£vÓ"Æi2K2­ÔúŠT~‘ “‡@“Ö$£79ŠŠqÞékçj 麮¼¤Kðê®6}òZ(ôÚ’åŠ?•“/'þÁ3ÓyŒ6R6ƒÔ+ªCg¦‹:²¿z¯¿p° ‹°fÔ®òÔ°ñ ­kD†š«¨j¥=`6–ÿ„á±[ 9*Cå)çÆUµ±‚H²˨ ¬¾0•õñQ«0Pû´aРŢ£pµ;tµ3E½À<ü:›8¸ kºÊŒe(5‹bg¤ :¦ I¡ZT¦ßY²}¸´(ë s<“³ };  Du2‚[…;÷)"T Š+RX?5k¶7Ë Ê#¥@š7ÊlÒ¤529r{Šw»˜:®šZGekƒ©³6¶æÊ´Ó£ãæI}tžD¦à!NfôŸë§¼¾Š·Öªº)ĺßzºz¶Q ádF_!\ª ±ðK -¶k ½ ¿«qƒ*¼ü¹¨;¹º`–2½ÿbP i€d¾¼°‹`;°¿ò;¿ô[¿k8¿Åc¿zi¢«½˽ÝK¼d¼*м!!®7‘½æó¿¬Þ{¼à»«îÛˆý»À®ÛÀ3%À‡¢ñ€ –*ºÓ˜Àäú¤–‰ÁñÀÁlz½¡À4HÀœº&,©Õêª×ºúZAh‚¬þjl}YÁ‰0º"\º·ÅÀ3ü(Ã*ÜŠê¶Ð4!‘¶Ö;Á™ ÄxÁG,I “ºÃGqE¯%pX7ºc#àAÆ?|´u›´& ¼6©*@gsÖ^9©ÁØå¨dˆÃ?ÁoÞ”’ …¸M|’¹FúcÈÝ©´ |¦qìÿ¿X\ˆLД\É–|ɘœÉš¼ÉÐë ˜iÅǰ[7äP]É£…ZÍqͳ¼½²¶Í¾ÜR°ßÌÍpÜÎy\Ã;xÃÉ Q¦ÿ¦ð|¿¡e¹bÌÃ ëÆ—Â6AÏ›É^ˆÏ¼<g j0hÐÏ¿,RÐļÅïÐÅÕFŤ+ËÍ,ÊѺS°ËjÀÿÏ,ÀË<=Òp°ÓºŒ0Ò&ÍÓÀ,ÐDÓÁ;–¬Žº,Ó‘HÓº<RÐÓ»<j dÀh0 -ÒR0Spm Ög-c gpÓ¾¬Ô0ÍMMȼÂ.=Äs]ăV Ög0cp,°„ÍjÕÍS }Õ#ú¬º ×½,׌|²uýºOĽª#ܪ©½Ëhp-Ø‚ýÕR@S0Ž}Ò,0¼lÒ•­Õ¼ŒÙ¬ÙsìÔÑËœÙ/lÏ¡fÕ†½Ë6ýØ`ÇÍØ±}Õ»¼¶íÜqÒãþã@îã`â®FË+mËTÚ,¾äàLáöºÙ ð#>åT^åVÞ.opÝR*ÚøM¨JÎäKîâýÍÛ1NYähžæj¾æ9þ($¨(>i_æ+.æJùäßÅ*¡Ç\ËÂ;ç,¾ÞÏvÊ$ÌœzÀ‡î¦®ÿât¾Ëg€Ûß\èż觚èûç}}ÏŽîËDÛDMÔ5ÔBÍpêÝLé*Í+ŠéÔlé6«º_~býÖ;-ÖdÛnÝÚ”ÝØ6ß"ÒöçeîêHÌçFÎêH^?³®Õ´M‹ Û:mÓÎMí,@’^ßMì]nìÇë’+ëÎ˧íÚ´MÛ·}®mÖÕ×Y-ìÛnÌÿííGìÄ-çã¾Ëd Ó´Mß³cÐÔîëîží>ìò¾Ùôžƒöç€öåû!´~ ðçØí®Ëï.ÌNžðy¾ðiÑð›žâÁŒ&ÞA}R@ënÒ(áp Ó0迬ÿêZÞçG.òßÎåîåùÌgÀÏ.ÿ躌ó^ï~ôBOØnôGÿñàþ½KÏô$ïôœNõtŽôÜþóYï M¯ðU õ^ŸêVïóJ?öd¿õf/Éàt_÷v÷xŸ÷z¿÷`òÅîöY÷!‰YÀ†øˆŸøŠ¿øŒßø†?äñ~õ øo/ù)Lù?—ôL‰ù4Ìö›Ïù×°êçÐê˜_öƒú¹ úæ@ú”oúú©ŸóÉ>úËû/îݯoû¡ùPªû¸!ø¹ïûöm/ü@üÝnü³ úåÀú€ïúɯüÃï÷Ñ/ýoiùJlý»OüŸ¯ýáŠübïÿý¯Lýá/þt ãÕoþý~®þ×ïù½ïþëÿ%,ÿñÌþ;oÿçOÿˆ‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’Š$ “‘) —›œƒ/)¡¢£¤¥¦•§‰™ª­ž ®±²³´‡©²¬µ¤Ÿº½¾¿›·´¹À›¼ÅÈÉÊ®ÄÊÇÏÒӱ̸šÔŽÑÙÜÝÁ–×Þ‹ÛâåæˆÖ±Îç¯ìîïé§ëî/$÷øùúûüýþÿ H° ÁƒßôÐ5¹w¹Å3Õð܆2jÜȱ£Ç CŠI²¤É“(SŽœÁ€!¶ˆö˜I³¦Í›8sêÜɳ§ÏŸ@ƒ ÚóŠYÍ¥Hÿ¢©Ó§P£JJµªÕ«X³jÝʵëÕ!-k%-—¢N³hÓª]˶­Û·pãÊK·®Ý»qï8@úâR¯€ L¸°a§`]F”‚ˆÇ#KžL¹²å˘3kÞ̹³çÏ™kì ·øïáÓ¨S«^ 5±Ø¾ïƒžM»¶íÛ¸sCÍwñÓ¬ƒ N<ªëa°ÝÉÖͼ¹óçÐ%ó&xñëØ³ >Þ»´ãèàËOyººäì¬k_Ͼ}ë°È}/'O¿¾}Ûæ›¡?§Þ½ÿÿÄqG_ßÝgà–7Úyò1Å<@%28E„NÉEBáSJ…a |HU>ÿe¢…N5bVUˆQˆ"ˆ&àT:zá†ʘ¡Z È w &©ä}ùµ2–8ýUE ~T™bUúaCS~Ð d•!t™å–NICNIàeSKPi dBõ¦…TvI—Yª•š2òðG–~¼h&šMñÉæš0ú¦¢l.BUð( dÚ%WFê'_žm@Ö…@XQÆc`Ñd4!©Ÿá*d°nFdeÌ*Bª@laÄ©“aEd¼Áj¥†1Y®¢~j…¡FVë­1‹ê°úª±¨ÞŠl¬Ã~û,°Ÿ5©Ê“ÞDI¢lY€¤M©°¥–4ÿ%•a:*U M¥Áh˜*èÂÿ¾+¡–94eÃ0Ò‚ð>šb™7ŃÃM‘ðo˜úK±À“Ƀ¢U껄£4¼øèˆ~ä@¼*Ô[$|ÝUÇ)gMlD@ ñs¨F±dM!B¯;ï¨;[í« >f;ƒôd@¡¬F4µ«eQFZOFj´A±3½>tRÓZ5ØDPËóÒD¬ ¶±@7½jàB{ š¹òì§”ƒYù!sbì”—~h\¨ $ë¿!¤Af[bLp†’7 zS7µ¡Æ2NÜÔé_üTÊevüyèÚPïÈaæ@Æ'¯ÿ í\’Àc¼c•©“Š“uófD˜‘íÑ@Û…ÒÂY×KsËuíý˜Ù³^ͪö¸6a·w‹àªG?fÅב¾Ò™aøcX‡¾ö› ··^¡o}_dܶ=jyqi”‡(¼Éq ƒJ 6X¡–‘ R[” Þ”°àN ØÆJ¦ÈɨTRŒÚDƒ”Ð)' A eW»2i‰„¨CáNv¯ ‘Œ ¤0¸Ä8ep+Ë;—Óõ<ÍxÊ ¼žd°¶>U‰E[šÎvæ7þÍíY¨¢ž²ÌW?É4¡ a@ß϶@®0Á  dÀ F´íi ÿ\Ú¹ÅÇ¥­Ñ`pUéf,.Ò#ÜÏôÈ–]ÝP—U@g(°pƒ<ˆ™ À;?¨ÀC®ãÜ”šB,a„*œÝS|w2hF0Q›nø(WÂ’‡\b†VÙËWn)xí*e„ p2”‘ÀC:¢Á3 àD©ì+4Plª¨™2x*pÿã_ÖWÈ&Ø‘oàzš¯¶`4qŠ` Gcãø$ƒ¿ê=& Wk'ª’¦+wÂÓøs'ÿÖ©ÏþýMÃ"õ×GÆ ·"§ˆðÆÙX’˜ä†&gB‡ýŽt“–ƒRÞò)œãØË<ô»Ñ½nc„VéÄ@ÙÐ)ÁËÿ)!ô;`>êKÂ\)O¡S`‰c$ª!ÊTF¼Lc®ËJ·)Д±l¤gCG3¸Ji=«LÿÆ×…ë5YØûß9÷HQd)2v,«´hV´t+ËÚVî!ÐŽp[øàæÈ@Ž|m#פ©ÒPð*#-Ô–4–0‘:Š_`*å)=„Ògò@M½sŠ ˜(äÀ„begßU!Q–C-+Ó G{19µ³mlãÅL}Ýëˆýúƒ3}$<ÈÑ ¾+)t43Å É3v”žôç>ï%òoîÃcVÃJ™±2Ô lÿ'¬§•Ñköäߨ¼g+Z…7h-C8½ÿÛ7ð" Œ„”¨`åGÀ6 ìá˼me”‘rŠ¿àİlHz‚‚¤°¨‰QØN€-(1ñ2!„° á”"Q)µQ'Å0f)ÃÖÝã^f‰ÅL‡”ÒáÄ^†¹,%›ÎµhØ Ï»É*{«BàÏæÙµ‡–ñ¡¥ ý+ÑOõS‹´ÚÂÏžå8ªY œ2ÖèðPÃByXûûbϼfúî¡_ dÎ\3¿<@xÎói¦Áª‚& eÈcdÐH3H×oàëBÓœ&ª¦}í¿œdÌPÆé" •&´d íǦMFÑ;{ô¦ ™UU: Ò[´Ó8].ÿKÑÀz޵¬ÃçKN1“Ü\’®w›‹Ž"£ÙØè¬‡Mì÷™@¼N¶²oãkQ›Â.¶´g]kŒÞZ£¹^¶¶·=™f‡âÙÓˆö´ÇçjÿúÚÁÎ6·×­mowÜÒ7¹çÝs;ÝÐV7»÷½kwsÞÏ7½Ž{ßáÖ7¿ž oàÊ8Á'.ƒ¿áñV8Ã7n‡_âÉ8ÅGž‹ÿã×8ÇW.OäÈ9Ég^“?åW9Ëwþ—KæÅØ€†Nô¢ýèHOºÒ—Îô¦;ýéPºÔ§þô";6 ØÖ·Îõ®{ýë`»ØÇNö²›ÿýìhO»ÚÉnWSu1ñÜ‹1‘W/&XÞ÷Î÷¾ûýàOøÂþðˆO¼â ‡ ÔùqŸ»äuQ÷·G$ò“Ï|5Àq¤ËÃBó ŸEåû ÷χþôªý½}ƒyÔ»þW§‡é_O{N¨þଟ}íw‰ÛŸ;÷¼¾$|rà ÿø >îKüæS‚óõ¼ó§oå_ÜøÔϾõ_Žód´>û¼ßþͱ~ç‹ÝGÆ÷ËOûósŸüì?¾ût`¬?þ¨Ÿ?úáÿðC¿ÀÌ×ò÷÷'€š§P¿p€8y HéW ø€s‹À€¾PèÿØ À30‚$X‚&x‚(˜‚*¸‚,XÐ0ƒ28ƒ4Xƒ6xƒ8˜ƒ:¸ƒ<؃>øƒ@¨ƒI³°"È‚H˜„J¸„E€Aø„P…R8…TX…1˜Ž' €\Ø…^ø…`†b8†dXo0H±…e¸†l؆nø†p(†g{X‡½@h¨Mv¸‡´€‡tȇ€˜zyX€Xˆ§à‡¯aˆŠxˆƒ}‹øˆ€ˆñ‰” €•˜‰ ‰§‰ž˜œˆ‰Ÿ8жp‰„HЍˆ ¦hy©˜Š¡xŠÜ)1 µH¦ƒ ‹) ‹³¨¨@‹‚)ƒÿ °ð! ‹»„ÈŒŒÊø0 ˆÐŒ„§÷Š¬è ¼x‹@ŽŒÑƒ³È)Œ$ Œ@ŒÆ(ÖhŒÜøŒÑ8‘`Ëè‡p‚à Ž¢è '@̦0àØ4C¢¹ é丹!`Œ ð 9@ 9ù Œ0Œ*°’ÐH' ˜óé0Іp̸Œ¹“‚°+‰ÔØ%­„‰Î¨“î@¶v™ÉAi•Œ¦T‘™‘PBY’"I’'Y’ éEÙ’Y “(9“5™•Aÿ”@É”C Œiy”É’Ky“9ù”«XÜð’„ Ž2ð‘( 1ðŽ™°‰é’y*p1 “$ ‘„ ÈH0P‹†I&0)€–**¹’'Y–ô()@‘)‹Ù˜tYš’ª‰˜™™š«ù’Ò蚉»ÉšËÈPimæ0š‚€˜ŠÉ˜›‰ !€™›I™2`™˜©™œ9s’ ški’ƒ`™Ó¹’ª¹›—éšfi’²IÖy›$I> ’Âɘ2à›èœ»™ÄùšïY›‚ù‡Óàœf”ù'# 9´ ŒÊ¨—*ž(Ù™¯I†9š @öùÿŽ9°’^–¹Œ+ ›£ ™ª ¹i¡»)™fIª’!Z”‰œ‘i æ°œ¿Wz’ú‘h²h–Š’JšÉ)²)¤šœZž2d‘/ ¢†9¢™œŸY’h™¢ö¹¢Úx’.J‘0*œ'Šœ™Y”šˆå ¨'yš ˘ŒD ’EZ’GꙂ¤%ù‘wòÎHšYù J™Sê™óžµè&Z’pš¢ïø’ )›° ’Š9ªžxz§s¤ç€£«—¦'IlÊ §Œ àY§1p§3:*¹§ºX¡Ú‹„p’29¢˜z¨³ š‹z¥oê©à“‘ ÿ¤~@©Hª«†ª©3šš8‰šð0˜vW‰Yª0°Ä8¬l“µ(£ –)¡'àŒ'Œnš™ñXª)P®eiá9¢À¦‡ú­,l §ÀˆÛ*(`k)›ªy­e¡ñš©Þº’”*†)* º|ÔŠ­oŠ­  ¯ ’dI𨮤9®Ò¯’I™èj¯¹®r* Û¬Ê(¯"ê lª${­(»¯Úˆ²þú’˰تž+k°cê™÷Z” û©ÒŽ›|JI©{Ü›„‡øP7Z´9*w°é´8 ŒL› Xûnµ÷ µåð°Uë5û±j‘9Ôz*`¥…:8²@¶Å7wgl ·Þp¶„p›ƒr[ T•­ØŠt;~‡ëŠ…Ëœ‹‹Š‰ûqƒû¸¹uK¹Ÿh¹?7¹˜š+¹›¹{}¡«‰Ÿû~¥›‰§+©«º£ª­ ‰«ë»Ó7»P»¶Û|¸Ëº»»ò÷º¡ðTW¼Æ{¼È›¼Ê»¼ÌÛ¼S—…±@¼Î;½Ô[½Ö{½ØÛ¼Ð ;sitemesh-2.4.1+dfsg.orig/docs/images/flowdiagram.gif0000644000175000017500000011361411157162710022342 0ustar twernertwernerGIF89afµ÷ H $  a $ $ $$$0 $(, $$$$$, (0(,0,,,$0<$0@(08… 000004800<0(444448(8H0<088888<8<8D848<@<<<0@P4@L<@<@@@4DU@D@@DH‘$$@HHDHHHHH8LaHHL_•ªˆjã&è ¡%•RbЧ¶Úÿð'‚cüÙ :cÈýó@ú(Bbëe´ÓH ¤ô@LCîô `»ÀEÇ.t®2#m.X€Ë?¤»@Ä?O—¾:)¡ƒsMè§7ž‹¡ºÚ;Vi£U­ˆ•§€ £…zø‡0ã½É‚ò5ØåzWT=~ŒÛîÖ5€räÿL.På¬Cí)`[pÌ?\°ÿ ë(mµVã"u÷\T2H÷úægµuÏ{ŽaÅ12iéLi^Ü3¢üTiV Ô”¼DEØDFÝ~T™ øaÛÛüÀºð…0Œ¡ gHÃÚð†8Ì¡wÈÃúðK_Òÿ ‚¾Aàd™äÄgÙ¡÷Kä÷±A`n~×Ý ÀŽÑLiŠðá@˜(ð* ü‘~*ØŠu‡‚$ÂѬZá ñˆnV Ìã€ È …*£ IÈBòˆÄ!'÷´!.-l4ˆËÇ5bså“"‰`Åó5íqpŸùÆDÆï+cKpÇjÈ­úIÞ¿²r§@¹'y­˜°…Ž"±ÇZu³J»HÈ£ky/Çøãöº§Ê´1’™|¤å$¹' d÷Àš º(J<‘þ»"Ó‡J4Q aSŠ RÙL•-UÅ‘Ý …!³= šØUîæÿ3aÀ“ŠÌ4O¬üê.ãI&÷ÚéLF®Nr!$ZkP4uÛ ã,;ÔunuDÝìB÷‘vŽ)ëd¨;«ò•bÌ+7ËŠÀÞs)¯Ô´Km„ÐŽ15•¦†k\å?ÖQIƒT²¨II©OOò¤Ù«0C ÔW2¶ÔÓ•/J­*IúõÔwM«¼Iç_² ÖÔ««ÚújYGÖµ>Š¥’q׿òíÇ #ÌÚµ£vµëƒ÷´ Uݯ¶v#gÏ?ÆT,bn¦+k¤i‡H[‘’ âYˆ ‚‚É“Jº‰Ù‰–öˆ–=ú£eø´»h´Q{ž@›¤"Ë“$kœ&«¬+˜²” ‚Mi³tœ$`ª½ø¢‰8•I¹”Èø†–ȕΩ”¼9º¶9§\ÉŠ )Ž!ºžÕ¸º¬X¨±»·l9ŠÉȘµŽ·Ù‹¨JT»»‰­žÉHž4Z‹›[šB)¿Ù‹gH—‡ØBY!º†Ô›ºh«›b¨¹¦Úˆ ÿ+¼eX¼ƒp»eú•k:š•ÉŠ À‘fИ¤–DY§½¿¶h‰É¸ºÔ늵ëSù¼Á鼯ú¸O¹Ë‰²•›ÀôØ’%Žâ8aHƒ̉ž8‚ Á(x(xÁ#y‚Ì’ 삼Áb(£!©¯sØÁL‘'Â#x¬È‘¬<¹ \Ã6¬ƒ*yÃTjÂñ0|2Œœ¬ÃD\Ä$8ÂFˆ<‚ièŒ? Al“CœÄT\ÅV¬Ä»œOüQ\“S¼œ¬ÃaÜ„Ml†W¼ƒc¼Â&¸ÄÎ(Ž[ì],“_l“i©tkìI”¹º¿Øª%XŠ*Š(Ü‚¡ÚŠ~|ƒ›Y‚øÿºˆ{Š‚Ô˜–Hì»,˜È!˜›­ØÈ–œõXÁ#h…³(Šè›–9øÉF¹‰w‚oÜq,s,“(*œëðž" ‚.üŠi<Ë'i‚Á’á[‚ùH‚¿ZÄ<®)LËùºËºì• i’Ù‚üh‚¼‰Éȸș¼§Ï ÌÕØ²,Âý8‚Ó¬ÂÝi‚9L‡9ŒÌDe…÷ÉÁûÌÇ|­‰ÎÆ,‚‰*¼ª™Ê¼±ÊÑØÊÒh‚i˜²ü‡)¼½[/›p ª!øžg)½&I”J¹‹DúšÈÀЛ;ž4»·3 Ñ«ºZŽC±ÎI@—×€Ò€œ˜ÿ{˜ÆH˜¥X¼)m–ñÿÚ©} ƒ§îúˆ{‰—¼ª,ÚÈAM¯p8»®Y—ëË«›Ð˜¼ªD¥µä¼›.}§ œ²  è–V Û+º mˆó›´y–iù¢C½™J‹Œ¬,Ä4L¹Ë¿ÖªŸë¹¸ „Á©“áùD (zѱLˆ( ت×L©L*ØO[¸h:Ÿ¤IžëŸJ­ˆ¹ÒLÀ ™È9¢Õøº:뵉I”@øÊÙ8šçª—‘°¢ï9·I+š„xŸKzŸâšŽ–›hØ*™Ò‡Ø×]©à À|ˆý§}ÜÁ}`ÌÇ=‚ ÙAùІù¡<úµCª§²=ÏæˆÏµÿ¡ÏÎÈÏј¦½‰‘ß*¶«¹žx`·¿ˆ¤‹Ê¨è ƒê¥k‰J:ߣЕñ]‚Œ-¦F­²iÔ ‰IY§æ­’¸Ò²¹±N¹­S{ŒÔè³" ï+»pZ˜©˜™AYÍpª¨‹¹Ønêœeâµú•€¾p•ó‹ß×Õ  ïÝÃ$hˆQ­ÖNùÈt8Œ—ŒÕ›Ê .‚Õà€Y¸Š˜«¬Ú±$.¼l­…U*ÞΘ¦¿½“>;¬£é¬8-ËÚ‚N«ÚÝ9Š­î®ï›ÅÈÈÑhjÞB.à™|˜± ’愈™ªàxH«ãúÙ@áçM‚ÙIµÆ|T®Ü¢è ™¡…ÿ~èÙMΖ(Ëb>Žk ãt*Ü$¨³pÈ¥=Þ‰u\Ž™±Ælç«ä9äcîŠɱèÚȉn IœmÃo-Åq²YÝî³x]އˆ–ÒãîìÏP;°Ý9ŠP‹à¹EÜˬJ´\*Ýl>éGÚ´ƒ í+]³j½Í›¨³šØ«¯»ç縋Ô(¸î:‘d¹TKêî®{;®vKéKTŠÛd[Ž ï_úî,íî–ï"øž½ÚŸ¿ Ú™Ÿž~£ÉÑí×@Zäâ.«Çx´¬¡Ýýê@ë^<ë̪ávË9Š¥œº[”©9º“¾¾GÍŠí\òôËŠ| ¼~-šGÿI®Ò‘Äxʈ™fy›=çú¿cI¼ÍKô¬˜Ò ¯¡Ÿ+º½ÙÐ,˜ÇK³SÙñsª¾±M‹mHŸøhŽ[)½áÙ¹Kíë­ÇvŒ‹;Éõ•X¨Ö˜¨«›Z;ôÁ··Ë›õ ä_ÒùKìök¦Õ æ+ãÃØä0ɬPˆ×킵ü‚û¨ø L†ƒç|ÎßÈÀjÌ‚èÉ–…"΂à¨ù-؈_‚HŠK úîŒùÝì‚£ïÝ´Þxøè°gŒÆLùµ/ƒœ¼…»_ƒlˆ~îú³û€(û˜Ë¹/ƒ™ŸüÌß‚¿ˆnlñPŒñr¬ñÍýØŸý0øü2ÿ)ü²AüBØâ?þä_þãOä`þê_þÚßþîÆÜ/Þà„JñþøŸÿ:ÿ>,ý\Lý±Nà@‚ DøOáB† >„¨áDŠ-^ĘQãFŽ=~RäH’%¢ˆeRåA&¡"¾„SæLš5RQ´R£Mž uþTèP¢EˆiÈ–=>…êçR‚Q_¹æ“êV®]½~+TiØ‹M­žE‹v*×÷îý÷o]%R Urû/«Â¸ÿHUZx­¸{.Hí%›XñbƉŽu\ÐlZÊ•k®Ýúo \À¹‡È?"\6úgAá5¤ãlþÇ4ÿ‘c^¿œ[÷nÞ‘!ïžlYøp‡˜©jŽ£¶BŸB­Z¯‹JÉcWrk¡‹½r{^üÏߺƒG/ÜøRͨSÚ:ôÔ«9»ˆ_iêÿ¸k/@$Рòr;/=Õʉ-úRëëŸJFk¯¾é¸¬¡c ûO¢?1ÄÜŒ,ÁO|j=¤*Œ …HÇ‚cÀ!"ºkÖá";Öùç\Üã‚"2ôND#Dr)3E'/k0³JˆÜ¬³{HÁÏ4¿8#ÅE\ˆ°€¶88Kî3"âJ2M5×4iÉÆš|2N˜T¸/šÐˆ¾ioT¸B©J7/\Çâ¦UŽh€ox¼"ø&·/Î €e#Æ«¸/rÑŒŒAáR–ÈDž´+P”¢Èä8ÇyïŒwôJ‘²F6BI~ñòÃè8H‘Ù‡TRã’>¢È[£ 9I‡‘—|Œ"ÍÃÈF.è‘T‰$%óÕ1Nët´$&UIM"ˆ“LÏ'—ÊI­h“˜G4~Îu#g—‹@0…¹Á{¥r•Ç,‰ÂGXÎɉ¹¡eÈiAÞEÿ#ˆÚ‹@7v¸¬h\ц•Df8Yùf63"²D ]×°¸ysè!è¾öÁß-k \ÃåÖ0Ø/qö³M­,Ñ+Í©žgFŠë  ¾tÇ;Ë哚kó\z·â”5Ü'úü¹Q‘(Ó(åè þh‘„â+|¹;©½¼W´Rœq= ›ÏävAˆ‘£7݈G‹Ò2G9hIï•RË•†¹¬ç<îY/4äïa6ÅiTûP& ´§iù©Q Æ-´wIş愸»lŽU©cýfà*U¶D§DáéU%UPÇDS_íäeæìµMðí’s=Ä™1 ±2¶Õ°¢ê›¬*×Òµ1ÿvå¢ÈHi¯RÊј‡ê[‡׫fµ(ehíuYÌÞT³BálO=KЊֵ¤-íFO”Ô†tµCi­kC ÛØös¶@©í@o+”Üê–’¼ím8û“àšs¸A)®q ‰Üäs¹:in3Ÿ u"ß}CÄ;Þ,dã»ñ/yÅk^ðªw½çM¯zÙ‹^÷–÷¼;ªn[¯»’ìÂr»?9(AŽ 8³È€ L`¯CÁ nðƒ á3x 7Ê/[÷«’þvò¿: p†Eœ˜ ›¤ÃüðJBwº#ŸF]¨?2jRÏÙÔAuáTíV·Z Ÿ`•.RõXéT¼Îõ®{-ì`ÿzØÆ.¶;€}*_+ûØÎN6¯çÐàD’SЃŽÉ¬;Rk[çÀÖ Ç´¬®p/kÜÚ*÷<Î nq“»Ýè~7»ÍíîyûÞòVw1h€aª¼z#±¦š¶ÿ9ÂíVçà¢ËòYú°YÌrrób¾` >ÁÎqâc9²(Gð»Úî»6¶_"ðœÔ¯×–@ —‚¬áó8ÁÜ^®Pý¬üÚ^ZEÖq®ø[#_É5bòM£ ÙâåÑXB¼8´êo-GöòECxóhÝ:X“®ò*êBìa|¶Ã¹5—S·z)$Ê9{ñ|+>ÏÐ3&ôŒ]ÒF'.ªÃY4nom›D7Ö6‹æAòÄ ŸåcN9´£mIå]f±·˜çÒsÅËÎÐ@u•j½q¢'FEφù±…ññQÍb7ÿ‰ÏßËïýf3ÁB.rˆ#†O4âsiËÇ¡^n=0ЂFÓßE®öm»÷j>¯ÏL© w>Ì1×;CÏù}‹Æ×Áö6ÛQ>ú6´!ê§E pô<ø>ñEg%Û$ʇB½¯©<¹Ûœi±êãš{ŠÖÓ¾Òž®éÏ?í ¿ò»Œ½Ú¡œ{‰š ¤© ¬—µ: ÀÃÁ3ã»äC´5H7•¢œñ=¦š¾ÁRÀ¦òñÛ¾I ™ª8œ@$ îI©ÈñÀy¨At*ù[4 ,‹üÓ?ŸB2Žé?ÿówP©¤‹˜#›¬ƒ9°ñÁð‘ºÊӫȱ&ÿ¶™´YЃ¸™šˆ8{ZÊÂôš0„©ÉûÉ+…Y˜=k"CA'œ(, )´d´ô3.¬—ÆÛ¡áù¹›–„«¢h€:©›Éy¹n¨²«¡‰Â rp;­[_¨¡£1;͉œ±¢¼<ÄyÐ;!*¿¹áÄ™›9S¬ú³?k«Âž€ÄŠÄ>£D}AD雤g4®ßû8%¢Âcœ«ÓBvØ—¥ƒF~¹¸9Çq\kD F¬GÜ•d¤ˆe¤3DÇz´Gßó¸u¼¿”ÉÆc„GƒP@`¼ÂnDz¼Ç…¬Gu<Á}”š~¬Â,ˆÿmÀH€m@ÈŽPÈM4«¡ò mªkÊ™¥;ɃӥøAºyø–ä¦rÜè£#ÇŒBˆ‰Ô?Š,0ÈHƒŽôȃ»Û—ßù˜:ÙCïq(mžI@¬{C48˜˾ËLJ4F²¤ ³$¡$ʵdK¤Ô'Ë»Š³(‡®Aƒ¤ Ø D´J˜›…¾l*MtEÛ!šÝѺ‰Ó:£qÀe:ÿ_ʹ‘Í‹TKÏÔˆ¶ÄA¼„@˜êšˆÊËI›ÐË·1Išyͯ“ÍZ<!–$Ÿ™aÀÒ@ÍÉ«í)žÙ1N{QÄLºLÌ” ç0(JéÔÜ—´ÎÜÑ;¥Š²ºzâNÌË  " ìíäžR°º¦³¦¤K›÷œ–ùìúT«&SNæaN‘ƒÎÊeÑuÑ…Ñ•ÑmÑÿ±i <8~!ÐÕ›ü:¾¼Kʦíûª“PÍñ ¦ºÁÓäA*R¯Ï·™ÏÙiY Ñ-åÒ.õR …;Qlƒ8ýdˆÿc@Œ¨ýË rˆ H…8x}œßÙüáÜ8IbðSïIÅ¢zÚËÆÔSš8–A’¨ q¼*z<+ Q,å0ð4]?ÈÂvÓA+Ó3åÔYÓ‹hS⋌T°?Ð…ØÑ}QJЩ,íÙ"íÊÝ1Ÿ{ ›*)ퟨ¬ŒË"b0„NŒ«[)͸Nä¦eո˗˜†RýOSk¹ƒ$3µV5eS7eŒi †ÈpdHB¢ÀuÖj-Ulý¹P}³Qmˆ{€ŽA Õ'¹"¸‡JØ×AÀ×|…|)ÑŒ·€ pEի莨À ppÿ«ꀉŀS ЇðÐt×-jµVy \Æ}n Ø8ãBvË¥ÌeˆÉŽ˜ÝŽÍÈ Öµã8f (¦Ý|%’2ÞQö•Ååç€eÙŠÞ%b«ˆÀr0H.âl=߇°ddöºè4µ*~ Qæß-†ÈõÅEcÇÝ\ye W eá7fŽ8Þ]ÞÜ^®cÍ…bÝmˆJ˜Øþe4öbBÞ]•¨LƒØažÀá4U„Nÿg kV[IFJ”m–Æ’c]›ûÍ_p áN6fì`¾%df"`áT^gVfˆ3g€õâ4UãY¾à‰‘ î`Áhÿàeÿ `.«u¹–ðý«3 ëA_»= .Nà‡èuo™ vbgþã©vˆuÏ]_7`Ïîo€ ÿ‡W 3€€ €!¦1 æ ™öúæ VWa ¹ômüÅŠ1á 0XvjÎór‰ŒF_6çõ¨hwƒÀh^9uy_åÐHÙîcmoé0‰ÓÜÚpcþ¸Ûþ¦†8Ü<¶™Ø5xS­ì†À’–]Ù’–% þØÛ¾piþ8“­¯ù:ŽÓù þ¨‹êëX{ˆ7 8…NÚ˜ x]ða9mù™ˆú~åàýå ÷À’Y_{íH|AùÉ–ß©{ÿ6jÛP¢'Ÿ‰›—ŒR·­‡è¨ f_…˜‡€R˜âÚå`•]qŸ¯Õðù°}wý…Üÿ|5ŒýM{Bÿõ‡ˆmÚ_ÿ\ ¡÷Aþàçy Ù¸4‘}ü’bØÍ`c Dî#r ˜†’¸‡cÿñ'ò—Œu¨¿ý2ß/ \Øwž}}‹ÃØ\¤ÍàG'`K§þ–ÝÑ \®ý+hð B?mÖ1lèð!C&¡R¬hñ"ÆŒ7r¬HEÄQ³8hпc\,XÀu €‹˜à,VraÈ: 'Y¸æ¢`Τ¸ü³ðÏEœ“=Z´3)'ãHEùïdÅc(DB¬W‘ —“DPrAú¬Xž],z” ÚAc+2õ™rÍ«VÙö,È´"×À!§ÿÉ A®#âÄŠuYˆCN0d†úS®X/ò:‡7:5Ë”K¥‚ƒÐDªôšÎ™à,Zw‘‚¨íê-Èw§Ñ¿bn(±2ðàÂìͤI«kÎn‹ñ^O¶×¦ÓþGä‘™¹QwÛ4Î5×£©ƒÃZ›¢VÌ^)º¨DýÞ?\J¶§^ý­_üõ§Ã§X×ETÜe_é†q"‘‡º ÷`eúøaA* †4„‰]™f!^~G•tUL¸ÈÝt)­ôl4H²E'Ú^>Ùç]G¼÷[†=ú˜XqÆ!WQR3„KÓ_AF¾e“ÕÁö“[.˜h AÎÙ¦\ÿu÷˜gBéE¶B0tÏ=þdfAйöOšA‡›pþ£¥w>AJ~útåYøP*øá3âp‹RD 2L3hCˆ&ŠÑ†uÈ™rÞ±™Ôh¥]‰[mþE’´ù åAf¤co<^:+­ÿÙÛÃàTÒƒ.ÈZ«c[T0Îh`hnù”[DðšÓ›[ÄÅXØ~Ù©AbBF&©aeZD¹ îIR…WD (8çÊ5HTýGŠNîžÇ–|T¹ ¥„Vë‹gG`"Ęc”ZJðA™ ¶©FRµjj ¢y.ƒÏâåŒêŽ£AÒòTRÿc;ÙvM² â¸ÛB;N1ÍÞŠY®Y‚ø8¤´&› TtÍ Î­CʈNòœe·?ßÉ2QJ2Ù¤{pö‡fV[yÑ5•Ìä\[]ék[ÇðvØ^ŸÅçк¦šœýyL%ë lH}Lª ƒ¶­¶Ù²!íšt~áMÂ(ÝI `[>Sd$Ö_+Œ„:ÙבÒlJ?T ãu7¹Î cWýÏ:•°ýÄ °ÉCg´dÛIÞô›f»vtÒ«+j:ë×,)7PH¬˜ÉZ3ô•ÝYΊUÂí¥×ùè­`àB/4­"¡{;Tè¡þ!%U(IÅ ê­t•ÿüFÁ6J&ëÔmÊÐe̪l¨tÔ¸`]”¤¤ƆÐ:Ê-€‹éO@´À:„¿xÁ(6° I@Ú1ÄvÑ;aBb«™¡°…™dª—˜©ÑJiâ^`¼W3^J|øaù"°Íø>s©N¼ˆf"\o‰5tâE£µäS\`Ѱø4„aÁÌ©T ’ÅáWLbÊjPÅ*…¥NÚ;ÊLbÇþp„™!¢ [ؼÈb3 Ì »9«`’–l¤8ñFº&!Æœ’œ¤Ú  (“Sô lVfÐìóW©„V*Ј敬d%GÖA€Áœ`.sI‚ _Aak_ì-v)´×–ꃄ 5ðaKŽñÁ ƒ¼FR•˜»0¥ºá´H<ýiZ…ú!9ÃWPFíÑdâ~ Kˆ’Ê-a\ÀxÈ£A‡PaêÖÈêÁÏjDɚƔ”oj„­ÍÄÖ…²€¶æõQ@Wmwÿ$åÇj6Þ¸½éRwá‘/}cnÉ´PÝa7–xŽŸeöReô¶ SØ²Ž²@YÂIr‹µÛòÑÿeæ›þ0Cltˆ5|$©å^xR-?ÑFßn¾“n6~ ÇzÝÈ TrE©(?w­žœÃ\ìž[‰c}K%ÆëÿëRÿr»&ôu¨¹žk×0âl¡¥¯£h:=êS¯úÓ×â«=ê娇èÚ¥ÚÓÕËdy0Ãmßmùz³cŽyÚ åÎAxHþyµ½!9‘~ÙŠjгñz$K)\¾#„r¨lÿ€Vg4<ªH¼ó°A߀Q”öGc~—ËõÔÑnÖG –Ÿk%l/Û|CxÛV G[` bàB»ÌXFÛ ^7``ОwØž‰DžâpËÎ=‰k\©ÐS€_ØåǤ=ýyX‚(ßòeHóGjY™U©XD ½XÝ@u ­½ˆOÅ"DMôW¦E˽3ÿŹ`áœMÕ˜ ªXyÜ„‹¬—5aüíXTìXiœ >EîQš)‹˜ý„nH`CÁ)FW%Tè[N¡Ç|¡ÙèÝ—B Š2E Å†| U ØålàÁðDÅ/‹j‡u8Þ’•E“ÙÁ‡}LÇh©Ý ^J ®ƒ )Mæ]øˆpqM$W·^úF†¹…ÙV†]Ä*2•EÜaCtžQá‚\\`¹„ƯˆÅX”U VÝ,Ž-½Õ‚  È™Ð9àæÙ¡,ÖÎ5UÆ+ÆbµHXˆp„~­ÖFøh‚7~£&Tâ%‚HÉÛuÄàuT ý NìÖÉqÄÝ•ÿÖ3^UV Eà…Ï`Ðâ\5GÆ\CšBG äM(E>®…ÒÛ÷I 3 3Îc Ec YãË\D!ó Ý6Yâ82_9âÊ9vÄ4FsYú…DRY„~D2Þ£U˜ZÏÌÅbÇtDE]• ™¤¨.#JàCB$îB”äQ"åEˆ8|¤C¨`GG&ÒTTrÄIvEUjDKÎâš}!/΋§ Ä¼œ„{h¸Ú: c2ÈbCrÛPÎcQfåRjäU9¥op¤\ ÇT†d:YÕö˜"JæåEleÖ£þY¾áéÛИe©¬ä‹,ä3¶%¥¼å3Æ¥`¦H4ÿeòáefRÆ^Bj°„¡Õ×ìÔþ £ Ðp\åC¤$­ð#ͦC¼¤f©kØ]Ι TÑÕPääèÙ1ù$DRæ X¦,bæg]v›]F„g.'q<§ ñ¥bì`l-ÇGý b„J†¸¦CÀæuvyjXu)ebÐæCtþ0VJŒ.”Dy Äõ”D.I³8ÊøÁö¥% ¬eK§… ç*çr2%uB¥tfDh>È‚ŒÐŒ‡ñeÄ„"x6„xªf‰…¤ù¢ŠMIšW©Ø¨‡z>V€ OÔ a h‚¨èg"hg.¨^R'8Ygb`gXÀŠ)E¶ÿ&`båpüU¶õ@Q!¼›À)©“>ȉB„0@Ñ%ÊpþdqåFàVÒhfÚ(D((ŽZDƒ d‰¨Rsdw¢gG\(CdèFøœ¾üï)›¬AH•†-öˆ¨z¨qȨŠ©`’éC˜é™RDš wê„GÑ|瑾æp(aˆøøéÅ»‰§j B„BH‹ž*¢ö†¢ £æ%ò•itF*FLjpTê³awz ÚgI`~ÜЦ†çƒôÅä 3ñZXŒ* ú•žjH¼$pl©´¶*f¼êæÅê%öC!|¸~øè‚;œë#`º®k¹ž«; ÿ„k¸*?Ôë'Èë¼Ö+?Ü+¾~½Úk¿ú«¾ò+¾þ뾬Á,¸Fƒà*pTªiâÝ?ÕÖ\Ì…\D±¾#¥ªÊ²ðˆ.b~Œ¡©J« vezª¥É®¶F†¶ ·®à:Ð@1Ô¬ÍC8̃ÎZÃÍÚlÎîlÏÖìÏÎÏíÐmÏmÐâ¬ÎíÒ*­Ñ6-Òƒ+ø@ÃêèLñh­¼ÑFÄ#eÐiéeH'"DI¡®lH¤jÂHæÊ¶,d¼,·Åìò­ƒ4­ÝÞ-Þæ­Þî-ßö­ßþ­ß†Ã\m‚Pe­€k!n£+†BŒ•EÚrµUOr)«zi3‚ÿiKÊ-KÖ-à~.膮èŽî<ìᚣÑùe€­RiŠ@närÅ †ÊÆ.Ëb®Cj.QJä‚Ò-éþ.ðïçšîp8¬­–"fÈC?,/ó6¯ó>/ôF¯ôN/õVoóÚ.W¨­Bº(öº­`À-¥pîÚùîïFƒðÎC9”à¦/èƒèoŽ®Öž)Øb¯ý¢-µZëýzo`€ï ˆ¯Ñ‘ïèà ðm¸¯ßæAàmD€G1°ÏCüí LBè²C6œ.®(¢|0‡°0 —° Ÿ0 §ð¢(ãÞ¯ £­š Bíº0ÿr…ÿZ¤‚ ï0÷°‹p,ÐÀèvÿÃ<pÛ­ùæ-ãm4Lð¹U{úêôP?²7çØöLñF³u/A«ó6´zŒ6^«o?21r”B*·zËúö'r)÷—2'Ëúz9“óC7m¦»8§_;q“úµ‚z¶ŠzUk»šºŸó­ï¶7õ«GunëÿìwŸ‘ï¶Ÿ7­ªï¶ú2ó¼£û»;¼ë{7\qèúº{w1ëö¥kùoKÏ‹c»Â¿3¸ª˜3™ÃrÃož¸;qG‹r*Ÿ38Gu{t«/²2vÞN°"{ô­/²);±§s*‹ü+t”BÇ‹²QÇû4é—¾éŸ>ê§¾ê¯>ë·¾ë¿>ìǾìÏ>í×¾ìó²íçþéWÂè¾è Á&ø¾ð?îê‡Âs>€[ò”×+ûsýsqnw´! r)ú ô€]?µ!øg£ADw´o¿¾gó"ù$q”Ãgcpõ45oýÝŠ÷pèÇæ¿þï?ÿ÷¿ÿÿ?@¸8`Aƒ&T¸aC‡!F”8‘âÀ*fdH"€Æ‚BXx9ÒàE’ iÌS¹’eK•yò¸”)sV™7_ÆÄ¹³å’I*#ÈÜ÷hQ£G‘&Uº”iS§O¡F•:•ÿjU«W±fÍ*ã˜V¯HÉAøJÔ ¼±g¿rEËtž-a¾•ih–\¸:íÞœds^4¼,‡®<˜paǯU›XjسeG&ºqÛ¼—1gÖ¼3°dÏŸA‡}˜ò裎ÇB6=¸´aË›aÇ–}“]¶Õ·qçÖ ºõmÔ_UïöÚ›ðëÙÇ‘kîæCxsçÏ¡C%nú·×àÑ©N\oMrïßß.Ç>ž|ùÕÚEW×zݼSôkñ—?Ÿ¥øö÷ñç?û´ú¬ìõCŠ¿³ò±‡’.L°‹aìið@dÐA#lÐ@ ´ðA%¼Â7TD Gì $LQÅ—Ð3ÿ°ÿEÏ"çšq¼¦ž¢lÌñƉêÑG ÿ2G"ÄIä‘IdrÉ&Y¬ÒJÜ@Ë-¹ì’Ëk„ƒñ*W¤ñÊ3ÑLSM¥¸eE1­"SE3׬ÓÎ;ókóM±R3 M:ñ TÐAsÓSE8«’3E@ mÔÑG 34ED©R4@F!ÍTÓM©’4@J§²T?L9-ÕÔS­U*Qó#ÕWa5:U£b?WeÍU×]?£*[ïÕ×a‰-ö+_ŸÖØe™mÖTdRÖÙi©­œJˆºgp!‚‹uþ'.HÁÚ¦¤­VÝu‡]Ç¢*‰£Ûkpqá p¹† sùÿÎOvØY"Êuaò½Æ…k,è*¿s™JWà‰)~ô"À!âÞA8D[ ,ˆƒßÇþuîžJÖÙ.ˆèJ\rÿäb‘ÿY'‚ÿ9™"°ý§"·Ûo+.Úh¢,€ya¤Üç>ˆ—’X2†>ø…ÝÍwߤõÝ×…J™®„‹kH!eÞzn{â8Þý‡®>ûl¶Ÿî׺’›S˜¨8⸑‹A.*nw±÷…ýþ'Ž÷% á—vÛruI‰üŸcÆ-7ó8œÎ›äèwapŽ!<ä{ „f†çx",p :öøòݧµM¨•’:²ÆgÚ‚Û‰ºÿ=q¢Wœã¢~®œ÷é™]Gó+OJxÆÇR®œ^{- %ñm¿;öAÈÕw¹ë“úùé_-{¤¶Oìä¢RæùžÏ†»÷Åf8ÛßæŽŽAðŒ(œƒYý 8¬|íit+Š[1h4Oéç~GÉ_n4–ARlƒÓÛzø6B®04%YŸXCJÆ…¢ƒáa*qp… ¡[J½âõôðc“g˜DÝÔ°=4ÊŸ’ÃÒÉo)ÔŠôв°"2‹Jôâj˜h'ŠFÙ·œ¶Ränƒ¨¸Ðãt nD¸bÆÀ–ëd)ÓÐÀqŒyìqìJÿѳœ-pN[Ù5§iÑaqø^òâh*~‘“¢ cyÆH–fÅwI‹Ù 6·kxn73Š*Iñ®µÙ˃ЗúÒg@‚-–÷øÞ*ñ…‹ãŽ Š¼ÚÞå‚–¡òÊL-Ç>ð‘+k‚Üd'±IC7ê„ÿ%VâP‰•Ù‹Œ›"ÒŒR¹d&ŒnŠÛœâšg”ð%LÅ‹ÙãÎx”y6S~šT'ãPWN´¹Àž]ÌæAóIò„òe,J!+QH†ñóœ¬3ÜEØ1šÝ“yþlà éÉO¢ òyFäãBÊÏÊ-laÇÞˆ É]¡5ŒBÇÃP‡E rcE§ÿN£hÒ[^áÉR¢àŒuK³§ëJZ¦¦Ôë§UQçÎ n¦6õ*apŠ~+ÊDú®QM¡•úzünY˸‚-}Î+'á¶z¶ÛáB˜ ÌçHïšÌÀý” úÒXKÑgËÌ „£éW!›•°Îª›1"ëUpá0”ùL‡­DGz”6¶[¤oÆGE.0u#%¤!ˆÖ&Ö’ƒ)¼î±EŸ’[<md«•ÉBg¬±Â¢Aƒ›ÜHmsR•Óe3%Ç¢HW¹Õ].oh]íÖo¸Ï).šÚðØíŽw‰Ìý”sãÝQ‘¼í-/vý•&a¹—¾gé®s¾{¦ùÿÖ—¿’5/Ñ›(õ¶Š½ý5pdîÛœü^i¿v0T¦WjÀ·*ðƒ1,˜ïfÁVjp†A|” ë¦ÃUúpˆQ<âÜ”xFFñ AÑϘÆ5¶ñqœcëxØñd!ç8òArd%/™É7€šå({ãÅjA ‘e-o™Ë]öò—Áf0›@ b6ó™Ñœf0bj6³áf9Ï™Î^ž–ëœg:›à¿U¾S Á AšÐ…6ô¡hE'ZuXô£!iI'Z˜ô£Ÿ°‹KošÓ>tíiQwš}ös=jU_ºÑ«võ¨+ýjfdZÿÖµV5¨mëA—úÔ‚Jµ®sÝj`Ûб~5­‰ìDãºÓ§`'hÁŒS,š„>Å´eCóº×xúµ²W-lpÛØ®Fö¸ÑÍìM‡aИ¡ƒSpâ‡æt hZ(€‹C¶mên£éÛèö´¸ nër¯úÜ O¶º/­€h3#ÚÓ81íS„!Мà@¿™¡„€a˜¸³«ýoH°aâÌàöÀQj‡sá3wõÂUÝp›ëâ“V@ q%( lÄ Üÿ›íî·tÀnH\<éaPÔAîrÃÜJßy¤kþuQã|Ô:»¬{.é@(àêÿƸÇÍ`0 €{»ÁîSÔ›GƒýwAÛ]Ð/çzš¼~vE‡]ñ›&»¨ÍÞø[˜Ӝ:-ÞÞoN(àÜßÍ v[Ýó:€¿Ïô¦W[ë‡_Sâ%ohÆÇ>Ò÷täißé´oã™§8¼ wZÝG74' ®zŒ~ë®Wìs/èÙG_Ѷï4î©?éÝCZÞÌ8=æ3®`ƒl´Ò³.zì;дøw´Ùu€¯žùÎG<å³/}Gç¿ö–>¶¦ùO÷ðOÒØß­ûD.ßtàã”àòmÐâOÚ^€óØ€ &°Þ*Pú°Íðì¯J /ú¦/ Íúÿ8 ûDPѶ/ú8°Wäs/OHpÓÎî@ ábÑR0÷VSÄiOp/íÜ2A 2¡ tp ­iïP?„0öˆPpÒÎÍ XaÐá 0 0û¨° ñã %/ p % ÅPÐ!í2ál!û¤0öÎ ÛC  ùÏ #íÜ¡ Ä Q ÐLáqõ° ©¯ý°<Qñ1ÿÒÎÍX!E‘ŒÐ<¡ ÜÀp%Ï/q<2ñì61û:ÓPÐlás0Ñl¡ÜÀ J‘úX±ñ\ñ£#m®²ŒÌ² ÛÿÆPÐjqÑÎͪ “0ÑLAÄà‚1ú†QñŠÑŸg. ¼èžýÏÜnQ<Ü€2¡ íï@ùïÏ.ű9ÈÑá€a¸dÒqТQÑÎí¾0çÑÐlA·‘…‘U°ùú:þÑáÌqKб 2Ñ Q Q -óp"c/R722áRK² ÕQÖŽ~!Ía'w²sOÅN%W7Z2á6²#=rîá«@M'wR}’ö€òë„r(W£( . cR&eP)sîáÍÄM žÐ)Ò-R+wƒ+ n 2)ÿiòá å0­ªÒÐNAÏôìÎ3ÏxáÒ²R.Eƒ.Ç­ €ô,Ã2/­üò M*yÒ3Ñ ¤,Ê. F³É@ 3.“(ß²ñ áà Ö < dò#­&o’ø²Ð8³'?Ñ€ÅTsÒ³5?Ã1‡f ¨¬(œAš 1ŸQ7­áÜÀ)¡rÑá7‰Ó8 9W“9±Ã9u­ ( ”B$3;ŲìÈò;™A3 ÍÄ  ø³?­839%m9Ñ32Ô³Öbs6ÙÂ6qsµÓкð7wÒÐæpÐörÑ´<4Ò´@ã@] :ÿ¥*ªó:cðA Íï@!- ­Ô²N2Ñ2tPÌS9YÓCCDU=Ýs*às2µp>!)?•Ña?Åà1”Ž,ZÛ`[âfrš‡¦ÀagW¤îGâfŸ–Æ  LèÖÏæ&öÜ‘öò2Uc7Õ*ZFmW“ç]ÞÅl¶ª\.ê”fJp‘k*èVÑìönµ"oû Q€T7n2Êcºˆ€hš L&wN ¯.È!&`ïv®rõ2O'•B‘ÔIÿ³s«¢v\À”Vj¢ÐIw›i]]k¦v÷d±âu-ve+hwU[õ]ž'p7 ‹'wC×(¦*qÑi`¶ yµ–#õ,-ÂU?ÇõÐÂv*væF„)tÉ6\Hw©â|UW¥ÄË*ÌÑÐ7}­¢f•`ÿªžçkŽ®Î¦‹Êç|‚—‡ÎæbhŸÚŠ â&À:çÔàœ—Ð2'Ý MWûòW¯‚©Ô¶°~*…6nŽ Œ„K*•èæ–^VJc6^9-ÚQ Ì(¶üjsLë· h2+f8«(>§+f °H˧6>.‡Íy؇ í$Rs…Ø*þªˆj©¶6f€Ì¸fä6\PG³tÈP7+2øÐ6øŠ§âJÙ×U…Ãwj†AqøP/%tO­;ÑW«w-°H]yH‘<£‘’ADiB¸9¬ç(´Ü䘌ÁvØsÐlÁ&!-%Kˆ†UªDC• í‘ÿY*ÔÓvc?UÙnùPñÜ€$_t$ñ€ M˜ë™ M™—Ù)œs’‰¼BV“í–1 7÷,EÑ¢WSÕSÇY2èò•cùUWéz¢œ^I Ð)t [‹™(jY×n¹OƒXÑÄ€› Í›ÿ ½B·ÎâŒÚõ)Ày׬øžÕ·YÍ™¯biš§âœ¢¤°õ‚ßXHsí–Çt “ðL ¢#ÚzÓ‰¥¥"£½‚]ÿJ£©¸n;Ú£;¤ Íœíwh}æfV'^hGdfe–J—I ˆŠ(H¼e«jG¦¸‚u)–àÆ`&zqh‡È—€0Yá4™ ™Ò®ÿ Oû“€qú²Læw¦šn2†ª'úb¼§vHávƺ^LievÆ({_VF†a• ´hXfu§«•b£ë¨ãõÙZj¦hç´gaüfe7§e\@‡Jùoö…a¦eÈW¥±e\šJ¦Ža­©Ó†kí–AqW-lG¶¯áb–êb°åêÅsÎöî!Üw[ÜL¸ pp‡Š²{«¸»+.)uQ µ«Êur¦‰Â³[´çÕ¨é.QŸY)úG“J ŸÎèqXÛ`2*iÎh¶ï%t¾§‹TšyÈg¢Ï¦)¢ùæÞú ÉR›«`\MAñ´I-l¹ŠŸâˆc€æ‚ÿø^>ü™®[nBväö±Ç£**˜¥ð骂½ÅÙ½y ´ô(Ü|˵JŠcöÛœ(‡eü‚j‰ÀÏhqÜf²¥“âÀK¤|ʧ¼,óаyÐîÑZ\]t”aVlp„mÝIt±:ŠG½S¼qØêuT¼]}Z|¯æF:;¨aw¨i<*Q¤“‚}Lû¿SGÐ÷û^Èpº*uÅÜ‚E+É Ü¢þæ§bÁs÷èzÐÄ€0ÓBýMÑù‰Ís¦ª²…dGÝ¢î÷y§^ÜüѹE©VÜ¢žXaXv)d\Ï÷ü)D–I»fBF†Ã§–ˆÀ^HjØJnÿj nÜ…©7I‰;ö°®I¡çÀɬ‘"¡£Ïï8£W2V¯‡Ù›ip^JØœ¤,*–è]¤}hçj Ù[â}}ìw»g]aôû±n=× £%‘š‚Æi\ÇÎïÉàC'tþ•€ ‰¼;¢’')Àº©Èiä§„œ­»”ÿ¸Ðî OùÓ“o:)R|èÄ)yÀ&yvq [ägây³vˆ i>tî¸o$ç#¾H!ã‹¢ßý]0ŠÒÏÿü¯xZ8(=ÿ:ž\qÚN„~è±¾m´“¢cë9´ããZ"mIµ9mš$ZM¢^êÇ¢œY•’ñCwÐq$ÿšÐŠ[ÅÌ£TM×4¡ïý^Pšïÿ¾ïð ¿(ð ßïK öàö`ò)ÿñ#¿ò)òUÚÀð¾2>)–þ#máké~E~äWƒçãì™ì@%FÁlÿö¡V¢öqßöuŸö{ß÷w?øsøƒÿ÷ç÷{ù•÷™Ÿø¿3ÃXïE :Û…ûás™ÐëçÂÇ^ÐÊþÏAF³½"£a\)®¨õ=eŸ>à9ìƒä…H§7)tJ Æ›¾Û: Ñ)BL•_Ì <ÈìŽ)„ û1¢Ä‰¹øwÏE%ˆë&‚“¸î#Åuÿÿ ôO¤Ç’EZ 3¦- kä*¦Î<{úü 4¨Ð¡D‹=ª—yL›:} 5ªÔ©T«Z½ú´›‰âX¸ÆÅ… "ÿpYK–È5ˆ/¯‰u ÜÛJ,!ÑÅ1Š(è± 8°àÁ„?ÙeЫŬ :$ØáP‹Okácœ·(ÃŽxù³Egÿùúïmœ¤ÎZà€Ù¡3 ĉ4·îݼ{ûþ}T)ÖáÄ‹'®•+^R\ r!åb­ÛÔkÿ½tÑq‹A«1ž”6¦3 MxÙ>>½ÍÃÌzÿ1†ÄØH0°d¡”3’ºQƒhWÙ Ìÿ9‡D•4÷•p‘^Ö• v¸Î=/UÛy¸bˆ"ŽH"ˆÂU9Ĭˆ"TåÒ"r[E´áe²m·átѱŽ]²YÐZ{}ÝM´t¢^“NžÇž{w¸_ó!¤c„íÔ Ô…Ò1—Y0È‚ÚxJE&8D~÷•§U2uhÛ‡%îÉgŸ~–xbŒMåÁ 'D0I‹=31'ŠU74pµfD×äxÑŽÖõè‘E'©Ù Jõõד¦žºbÒXA‚dR“ nØÂ ­‘=ÄßE4Yæl–%›nª ç¥,™Iã4y˜ÓŸÎ> m´>ÿ i6A)LM’(SÝÒm7“ÌâT9'L²â ÝäMS“À©SݨPƒ7vþƒlJ¨A—.ÿójÿ\³WYn €Wª?Ì {«Bæj# r‡'b0#ÈBúáÚ¥®ú8HqQ&ƒ)E„¬ƒDºðÑWDlôOHÖ¬¡Â´-›g³Òþ tÐ{R+¨µîöPNh A9Ñœ=tAÔ=45‹ÒyALw3×FÇëí ‰\‡>þ³™X•´6ÖEf¹ÀE[oÑý8ëØµ‘›)É$Ä‚›*qA÷ÙWÓ)þÞ­“Õiš]Û±†Jmk$Qhd r– Ýÿ¡Ìœ“Îf…gaz Ízë®EÙóŒÝ(Ôh0…F=;Ï ŽFå{íL-‘‡!·Ïƒ¼ñvs3À”±@,M4GHJ$*E¤Îý“…dËb6™r3¬ÞëǺe Í+ÄRÍ,­]3ö¹¥NØê¯ïÏÿÅN6Ú9ê¼³V×zЃ<-KhWS‚÷»ÙYë<òâ… ƒÐõÒIõŒÂ0óto„é‰R|às¥ƒ¢ ,¬‚Ã%ÞxFdC Ëé|ƒ¿ÁèÏ<ìaÐ/Úo ðÊÃ"àÀ¦Dƒv½cTó`Ä Ên<ÈÙÒö%IK"¡ÑcÂÿ)U)…NŠánÖqêjü ÕPQÈQ·0È-æˆÇ[àiìã5XÂG?þ1"ô# ™ÆC"R‘‚Td=|ɱZ¾#ÆUŠ”Ã\¥@öU rE)=€ÑóI°ÍB[²«âAž·€Tôf{_¬ea Ç*ƒ¼Š>‡»ÅlbÆH ¥s°‡=PÑ$8a ÌœÂ(ÌÍQ4sš£@F6ŽÙ…lj³ ¨0&6·™Ín™àä¦7É Nq~3ç,§9ÇÙ( A˜ôÜ ÑbdCYpP†ÊS&¸„Yô kŒR"£ñÉyF¥èî¦èJ„Ðb-°RBhËŒÿ—ãØ/’%Æ,†Œ f=}²Lq¥,½JrN S¢Ü³¥4•ó‰Àá‘Dábà4 ÔT¤—¨2iLu’Òš*µ¦/=ªS{2Ó¥JÕ87L( K¡Ð2¨\eÈ÷j%¾¢‚ì©;IêJ•ž  Sô§U&q5«4•¬tHT§ŠW—6o0­èO0ÚÕÀ¤põé¥>ª£Ö•#*]iðž‚(bLQ²‹ÀU4éÒ-v³wÍ«g¥RUÂät§eœ`OkÂ…T¤$eÆ/X‘Çm&f¥ÊÏ¥P©)mÄ;T¢|×4å)»Ö®Iê“ôçBxI òÿäm¡´µ„RÑxX)*fËÙ¥DÅP„b9 hˆób­¼å{gAÞâQŽM‰o·ÚûÏr Š eï‹Ð ¶©„¶0Wͪöü‚ÚGLUÌXmclU_Ü¡ ÷©ÂZ{Å.¶¶SqÚ<¨6»©Qm'¸]ÖšhD¦X–¸$F´%Pƒ •šä¤µ& Þån–EÞ'¹Ö ÎÂ\½Ê>À»Ø¨R°¼óPn4ŒË÷*wP¬IÜ#ö8*åÝ’/ÉãÜ­•ÇE棖lÞ%3­[QpaújQˆVÁ§%l/mq[eB é3H}¥³‚¿úÚÄaØžŒ éÚj¼•€Æå¯ËhFíN]¸V±£V”.Vö®€P£õÖvìi^?vÔV9r©é:ÉU£Ü©fwÿYÉ3»õÓP™Ä@<ëW³øÖVq¤çÍ¢]#Õò ¶zÊ€€”ÊØ þÞ"A  !hÇ?ò‹|ä$/y JŽò”§|VéA·,kmïÖÁSîµ mˆ«5mP Ýñ¨ìÏSò8Ò¬Ìv¤ÿMï¾ÞR9”¡®ö;U·øŸ“6W–K,•‡°wY³Ö°^ð¡sÉ ·vT"ªž°ât&lù^¨^Â69$îŽ÷¼ë}ï|ï»ß!1:ü}ð„ç»´«2YÝÁj ;Ö×ýr}ÆU¹QkÚZ™–´¥5-æK`š?{Ðù¬ñj½tf—NÖxóÚ)Q·7«¯uðÉ*…:Ô'—üòÜñ.ìºFµÂw,´§Gu`û±ì†Æ¼MŒHÅ€aÓ"/Ðè8®ßFùœE½+1˜D؃{öÖ&`n1e“õ²~Ũoñ.‰$Ž”fQSÕGÕ­‡ÊëWíÿ\°çpµ"¥`Y ×mÞ–kû€ëä÷‡Äg|Ç`‡°n` (‡€XW?åE¼Æav÷†ÐsŸ•&W÷‡õtj¨@\ƒ_*H(íµkKЂ¤Äf2‡j¼Ge†`fc—fY¶fT!çAXg F> Ág5±ZUh|Ó'‚ÕWK·€Æ1 ¼Ãéèç‚S‘ïGs5ƒôU† †çUDŒÅ(UÇè„ɨŒ@U8™ÐQ‡Ðg~F hÆf w7ipwª_x°†t°¦}T‘.M³× ‰è-M1j¾8JŽÂ4Žä¨TæhŒ˜ŽEXf‰XÍ81ØQÚ(\c(8A”e€O×dú„$ætµc(Ø¥OaÃ’£WA‡‚PÔ55út;^ƒ€Uán9ŒâUn†i6ùdˆ" õ/BJýÿ)§y‘¶¤Z"ÅdÔw@¿ óÈv!9’ü8äIwø(¤.×âoÀãDm 6AWLA ,8<ä55óð~èFJð‚DXGCI”=‘õO §}ÕtLÙ(,„…Ph–¶ ¾Pä(ÝpI… =æ(†p@Òõ¯‰— t@¥<.÷OY†” T5b÷€‘–OI†y˜<¤/È’KÀ“Ð5p%PÑ@zhà[¼å@.W(Á¥\ÁiƒUÓ HÓdÉ#ÖÉx]Ós¸%W™‰Œ›‰‘ˆ1“èZwð›Yš¶t}y-XfJ¸yÿ›z™–°éŸMÁ›@Ø›Öf™ˆæifAŽy™œ=´œO¡c¶˜*¶Œr€&v€¢voEJb¢a3 ždrAÞ'€“5MX‘èèž^$1{F%ïᣣÌpŸµ”Ÿiy-D4œ™ÄcÚ’O¯y‡ u™,¦\Ý–—q•— EDüe› ÇcúUJ*ö4•}UŽº?Ú”œ&vª*htC<>EYfi™Æ¦‡¢-Pôšf8JRƒÁ·ˆ0š£Ýó=Ì÷­²§±£_Ô£%Y{WC(uËõ(67f ê.‡*“†Â[5©VˆêVåjÖÙ“†ò“Ŧ\Œ^ú:`ÊkÄÿ˜ˆ&vhºhßfpÁcAআ±º"ú…yˆWJ3JhÕ¢çÑ Ú¬ÁÚ£¬ÁÚ 1_•£ÐP¬Å «Ð¬ÁÊ=&˜šøa‰ØPJÄO™ßê-ÉÛöÖf£Jª¬CŒB×cdúª:sêsM¡†QC¯$–bæå€ÜX.ZÚðЀ¬£¬1ú CÁ=$üÚ”úä‹yÀf¨hI ˜®û3Ž—œ ‡¢g€eºd^3;%6P!Ë.k¥;¾G"^Nq`æÂ]ÎdÎvfŽæsþjnllæV£pNqrNç®vŽZv & ùØæÈ|nl~è^‚~ZpؘèV=枎Žé’~Zpºxÿéƒá=®éÊÈéžÎê;ê‚E陸‰¥î拞ꭸ꭮ëñê‚%ê@ê´^zNg¹¾ëÉÞëë³NëÄnŸ·þã>“ìÕÎËXìÂ^ë-lì †ìÖÎê¯ Z`îçŽîé®îëÎîí®3Pî.ïóNïúXО•›îâÞ鯾màOðoðð ¯ð Ïð ïð~@<…ø®ŒuYÙïþþè?Vm ï§îžöõ ` ›Níïòÿ!?ñ$‘Ã&×A@ ¸Þò.ïï0Ï'ñ#-2?ò} g1 ñLÞó>oÿí@O"ÚìsC#BôÆGñgò;ò*ŸåMïôÊ.íêS"~“ £7÷Â'WÏvY¯`6ï8¯óqöa¯ëP?".,"q²±ö"õ4ÏvG/I¿ôÇ^÷v?îcïl"f13'S!)Ü'lOqn/X[O]¿òà¾øŒÿïŽL"ë@'‰,'qâ'˜olšÏUpr¿ó¨µñ¢ÿäx¿'‚”rù‚ßö„Z†¿I_¶ú¸èº"îã 3Ã9óû3Ÿ•œßõ@ú_tûÊäÌ"^! :¥ó{âúm'ü]%ûÀá -0µTÝïý þ!Âÿ>BøÔ߈Ä?"©Ê0#XÐàA„ &äêßCˆ%N¤XÑâEŒ5näØÑãG!EŽ$ɱ¤… +ÙÒ¥ÇP„QÆËHìð㏠Q¢Ü"ìj@S¬0é»Ç…8:fÛþ9†”ÔÖ©ÄEÏîùg³'A#åCФ¤²K+%Jl '¼ðL4Ót*Cš64Ïć>ü'Äq´SE‰â¨¤.^tÆÓý³Äˆn44 ò( Eè7Š®Q1Ÿàb;]àâ¾c,„‹ò¶Ó”ˆ8±—ÿû™ÒSPÿ!/<Šˆ3J73Õ´õV\Mš:–$RO½òä¤3´§#‚ˆ>- åR+raJ%ÅÌ…A¤±Z%=}RLíR‹ï±¯u ÖùY£€ÛÒ»oàƒëo•zˆD+%œÇ œ>òŽºòÈÝ0Z§ÁÙÈ{ˆX¯ïúœÞ¿é¹`|sÎÁö\eÂXÖH|$ocׂwÿi¾O.¦“wÏœáOOÿ˜ÿüW©äq$h`ùðøÀ5íJCÆ“Ji쓵o!aÓÍØú†7®4‚#$áHˆ—7=Å‚zÉ ÂA¿€Î½;ŠKxCfäÿ„I![èƒ<Á¦ bxD$&‰«ˆ_ è–¡åPŠStŽÛDÁþˆáüøE0†QŒcã6€®cVdL©øF8R…IÃbH’—À‡Tâ3Ñ«ˆíÈ-nÑQlX@~^2¢u…€ƒ U“ZR5dÀ5tc-)Ť‡‘“á ¢GONgÁSI)ÈEñ¢!p†K\°¾Ü q W)G ¤!„•¼d/I˜Iƒlò"Ú! ÀÑ©R¥jJÇ8ÆžH3³ü13÷8Ö \‡¨}òbfk¤HN‰ÊEYÂ`@cH:¥*ýåOa‚5›å™‰³q%ÿ¹F‚ 0¤ØÐ—û,0 "L‹0s8âêSY‡pž:†Û`ׯ8в ×à‚æ¬£kÄÈ›^'çiÈ<z\ hŸÀµ TžáaÐCÍÖ´@R’aÑ'?mš+ ©eÃô5J‘èl@¥옅™-Šd®‚%G¾ÙÑT®ò‚¡ŠÖsRó(é•$åvð“\ö¥¦7%kšrÊŒR™¦ò)WÔ?gŒ¼:¥S³8¹T+P¤%2 †rRÕi%Â*}®e¯QÚ²#õ¼gÞxYVÈâtŽ€«£FÐV³Nºu^ú"Å¥ÞZT'Á¯àzeHžÊWG¥ÅHÿUïZØ?%uNªFd:ÉÀŒ5²»]ÎYÓ*J"ô´j)ÂÅ’>+)fZàIêæ¸D-ÌñÑUS¨FMËQÔ¶AAm+BŸªYªRê#J…Ÿ-=Ôz`Õ%­XË[øVÈ·•Õ#—”³Aܪ’æ:ïQ‰‰Q‰|¸Ð£þ¬™Nc~gg‹ƒ#÷š]Tú°q)ù@Ê:zÍ©>ùaWŠ›³ì…ΞøZ|MŒ¦ùJñ´—jß{˜ÛH·'¦±\RœÃ³ØQÛínrpÙ^¿¸ÆC®Ëq˜c;JÂ¥ cI\&!YÊp1ò ‘œäÔ®V/1^ÔŒ§üe¦T¹bãႃ#ÿÅ=ÐÏyãy(’W9O#WƲʸëݨü¸\^sŸ["ætaFG åb¯ÑÌȇA&…ÓUi)ŒÐ¹Îáü+“¡âä“ñÙÏ›  'b5m¥.¥×‹O븃È>±h:ÿºT|ø‘Q‚š;?»ª^çŒÝI ÒÅSár¦£Ìi`—ÄÓEºÙ‡W©whSÚRÝÍ>»«öI¶°¦-}X×0Ìs”‘t®íL¤§è¹}šv¹12ìË\LGi{»¥53jÕ‹;Kжmk”7z´vÕ£ñ‘n{{Q2 ¦5Hns'|"辚têåOÙëÝŸÊ 8¶”±«šèÞÕ&`ƒøM­ÿ <»,I¯þk…§üÜ“-¡$¥N_2ÿÐŽ¨I³Œ×ìÙø…¸ôø÷ÐN¹ÊÖÜÆµÈQ¹2S†UW¹ÂΞïÀYûÇÔ•«-P} mž*¯½‘X÷Œ+•²\ÕŸ¯R$àFwÁ=b𥣼ésÈÓƒ#²f6)ïA”@•”Ó$Ï4;¯l´‡"RTÂ~´¹5Û“LrÛF·àd:݃mwà­Ýñ;n✕ÕÊ[žÓ˜ï›æ7ßv²X:4#ÎnèEïgÒóÍô§wäbr¾ºþõ`ŽýÞfO{øû!âf±îw?åÞí÷Àxêá^|¹ßé,OÈBÐìgÿ_ûÛç~÷½ÿý \ÿûã'ù±"0?×exÀLël|éù¬ª€Dýíüç_ÿûç?$L „þ @@^P¿\+‚NÈ5ø‹?;+ Ò:0@ 4Z€PÀècÀË£>¨‚À üÀÀ(€|¿ ÔÀÑãÀŽò@lÁ®¨À¼@DÁãs@bAÌÁÁ$Á¤Á׳A ÂA,B! €L²ÂÝÂö!B#œÂƒàÁ$,AkB'„,(ä)¤B0,ˆPAÊ;Á-D>2D¥/ C0C ,?ÿüà D,ËÃAô¥B—CDÄTD&4ÃF<±Gt”H”ĤÄ,´ÄKŒ¯L\”MäD ôDè ńŠ)EST?T„0FTE8bEqÅW¾Xl=P¤ÅȲÅÁÅ\<½]D­YôÅ)FÆat¼b̽^DF²RÆaÆf4ºg½h”Æ=LCA²Æk¸lì¨c䯢FãÇp̵q,Cs„=oÜ"u\Ç:kGT*Çw!tìy¤Ç$³Ç¸ËGÞ‹ÇŒ@œ@€Ü"|HÚGÝèǃ„°„¢…dÈàqÈŀȈD­‰t¡Š´È¾ÁÈÀÐÈ„ªŽ<9$2‘ô ’,Ip:ÉqÿÛÆ”¤¢•ì‹–tIA‚IÎùÈ™ì'‚¼AƒÄIbüI”ìIL$Ê( J¡tF¤ÜI™4JªÉ¶¸É¥Ô üž„J„iÊ9Tʪ¹«ô5­E®ìC¯üJo Ë={ʱÔDz4ijDËISKqÉʶ´© ª”Ër¡KG±Ë»4«·„ĸäËÌ¿dËÀž¼‹½4ÌEñË.SÌÅžÆ<Š@Ð-˜ÐÌD€ÌzDÌɬ̲ºLž„$A,M“Ì LÒ”/ÑŒ HÂ%dÍÖœMÍØlÓ<Í+ÄÍÃ|ÃÞä§ßä‰ÚTBáN<¤Ìâ$šãÜ ÔôÁåÌMâ|Î^ŠÎÿ˜€Û¬NŽÔÍáM씌³ÊLÍ6š äòxœŸX|Õ«üAÕÔI€%ŽRø°IÛaÕÚñ×Qº¶Ó©eˆ8ã_qÕ‘(%FÂzL® M¦ˆ´yœ‡ë”ÓIn&­IªÜ¯9~–q¦‚:Gn`=ÆU>ne¬¸1D®ÿÝŒèY{‰3{á»å‰Ùæ;>bYfÁŸÁ¹Ž-¦=¹0ê€}^æÕ%îR E‘Šh´Ú”ˆ¸m«æ„PºfŠèKadï—íHiÿâ»ò²hžIY˜ râ}¦Óv®Vx†Î­µ²ˆf†‰Ö¸æÕ”ØõêxµÀ…é8óðŽSÙØ—¢ŽÔ 3`ùFˆPDÀåYž%%º0bîé€Z5afÓ˜¶RõdÌŠ’‡é—çÔqÝyˆÎ’^'ùè”耼ï֫°N±Þév}g³†ØŸÎ"Àû“óÐ`$õða±˜˜±`«êášÙŽëˆÖòJžm[…þKο†À½²FìĦÙL–¢>€®žmÚ®íÙÆ„‘™“èA)DYÅâìC‘cÏ–®q湇Û¦íHÍ’î›Õní­Lc‰HZ¸ÿEᦠ7‹ˆfÂ4ýžêîø—¶n– »‘‘kóâ&‡©%‘§½Þç­>¿ÁˆÀ Ùî–¸n‰ØÑ∾“®ŠˆnéFÑÅ;Špf_Á^‰Ýéî‹l€ jñVc¡}Kêñx§ŽR´û:ÿÖÝ©ŽÉŸù6¿ž€@ø',RpüµdépÙ€ã…5ì†eíŠa3ªý"‚âZÔ{ÀÆ‘¶þÃk…¾dq0 Ëà“^CÂ&š™¥Šª¦ì6c ¯˜‰hkíÉhŒÎ™}N 3û‡/ˆ"Xñ`ê•‘êwibƒ–‰!oÅË/º:& ?Kq‘ÿ:°c(ÅsÜ8ÿ÷ 9õqèÑ+ê…&C‚ž€þÏq5¶õ0R¨è6e©,ö–¶¦¥N±¸©è¦®º†ˆð2)YÝû˜5Ä©¨YR‘(ðÞ &›ñ˜ÓŽPµ+¯ˆ2§,hûñkp—^ç +¶J‘a÷X¢ô™ÑŒSqjÎðØ“ý#A’†v–€A¨h’ʦ®kï”×}¥Ë}ˆFwt;ðÎþ,9i¨*5앸ëÛ—iÑhÌÒ8F>*çŠ(°KZˆïÐA[‘xŽÈõ–+•äÅ…yWuOê)91øÕ %}Iw÷™-Á¬dz4½wr¿HÇø~‰S—R™ÕK‘9ÿ¾g«R˜3‘¦mSVÝ÷‹ då xb‰šï–âÕ8}Y«œ0nš‰‘’Oz‘'™cõ,Êõø—MêV*¢¢øu7xy*ɹ‰cÒJæ…á}–ð~gëÐëšKïAþ}Qᜃøz‘xÁz†¯{Ñ+8¾ˆ©Ÿzß4÷¬"ªªQgb/8ñöŠ(Ê~©Œ!)Q')ñ¢à‰ù:èê,‹aõƒzõ0¼ŠNÙ/ù¸8Š*©¢²tjÏ™àb«ª±\`vº_*Ógzž­TeÄ¥¿|¡­zï¯s6!§uF=Y´)0æá‘­(‰hrý!Ÿ‡Šf{Öùeÿ½r¿…ª¼pgr’éÿV& ~A»Rǯ{Àsõ ÿˆPÛ‹@W+é¯}W[i:w “Ü×ý§|§ ŒÂã (€¨ôo Á‚ ŃÆBŒ(q"ÅŠ/2\@!ÇŽ?‚ )’£-ò5r%Ë–._ÂŒ)s&Íš6[¶€t2ãÆ›×¹pÁ&8¡3îLªt)Ó†}B:°dÒ”R¯bͪu+×®s&}êu¬G¤MÏ¢MË“,[„TwZm+w.ݺv?‚Ý)ö®W³jÿ¾¸—/×·'ãN¬x1c—yOnÕoàÊ–öäzO B"c cD,y4éÒwcÿŒlš&åË®ÿªÆzÍÇkŸMÂU¹z7ïÞRQ Îì;fëׯ›ÆnIÄ‚‹c¸\X Ž  ž—¡Ôó?Ï•â,3;¸îLj”— ú¢èáîßÃïÜbòø ‹ϯWøK"[`q\cÁ1ÿ¸@ÊløOƒücÁ?ƒ¸°Î:¬C.ÿœ!¶Í´žEíÙW¢‰#ÕsŠ×d–âŠ+¶ø"Œ¹(cŒ*¦ ‡(¢ÀÒ/;¹cÌ, ㌹xbB é×dXüµt!A¤pWà‚rå?•T¡„ƒ@ˆ``"¡„mcdzÿÜc¤M4L@®§(3d¹âšmªIÿŸ2îiä5ö9П/ ¨Ÿ‚&Ѝ’»}E“Rb¥ÃLš)¥–Úƒ©¦›^ú)¨fjSLÁˆ9«Ž‚ª«¨ªjN/¹ˆÚE¥¡Æ¢‰ø9ÙkDõ‰¤å âýc%mX^éB–Fˆå@.Ìöb³9ヨ€pZ¨H¼±ª9üê* Þ‚kDšbk©¶×f[kºö¬ûé»ñ¢Û.»êºk¯¼ú¢ûèj>t3À\°Á#œ°Â 3x|g¯ž_뤽^ºñó,Æ<“œîh žG4=D0ú<=Ì2zˆ£MéORJøK̾úù£‘>1ˆsî}'ðž!D€†ˆÆ–>ÅîÍ[ÿ_ú'°h„ï“à^)–¼ô9Oa¾^ðAã-Á|³˜éˆ1ÎEcyë†!6øÂytt[aÀ\h Îcy0a7&ѸÏu#›sÞ$"‡CC”z³Ç£¨W=ã\o4ÙKXìö¿öåOˆøëFì6¾yD` .´ ìn‡C%rÏ{itáÀ" 8 ÎÃ=¢ÀÚØƒn$Qˆ äíˆÆip']½× –ƒsIœÇ ØWŽ”"ˆ{dØI¸áïv=@Ãð2™¾Ø/)Ä`DGÉ÷9q€]$ùL×ÀØÍB~hXBn7 ñÎ…£ìâ/U)ÅQqgª»âÄÿ²(™-"¬‹ûß-óÐK8¾±Ž“œ¡5•èÆIlÒh4˜I9ÿá°›ÄpãËy–9Í잤+¢£a¾i~xˆ¤‹NƒhÆÕ‹ÛÝ ÉØ εÉóDƒ˜wG:.s®« ,Ø,çÂ29eÞ0]掕˜¬éCCò¦ÇX‚å˜àÀ¸ ¦¯ÁDŸòÚY>È­O`ìh)ÈK‡wÈšÞ4§Ò I/Ô®=(îFJòrt®ËåBaÉý¸Ó²ž5y ñQqÓµáòàÄÜ©zÕsiõñ^í¸XÓ:ÙÊî™­qíìgONØv!6´aéec;ÛÇi¶äBXío+,ØÒf µÁÍ5dk;ÝêV ··¶IÄ5Pa=Èòu‘7OÛ•ÚÿeÆ.ØœÇ=–ËZk\f˜·Ïy3t¯;á ?I»µæÂIœ¸à‹.”S¶»}·Œ/ÃøÀúíï®\ŽâYÓ¸ÂvÚZ˜™cá*_yE^0F·9¡#^&ÿ—¾KR„'f4ç>zçQæƒ9ä–¶“æÜ‹ 1зA›ï¼‚ªDŸ÷fÎõuc”þ 3,Ðÿ;¯¨l`4b¸å|Gc—œE§ck–â’½lùX\ÃF÷Ï×xßít¸@÷Žò‚¼Ìçü ç…L†Oÿ¶3vî<þöÆyù$þ3¶íü¨)~~׎tý@ ¢ñØ¿úÜ;‰œ!O¥ßkÕžÁÜîaE‡QÏy_èTÝŽ™ÎVûhÎô)I•vÉÏ÷àOu™]ß÷‰_ &\‘™ßU±ÓíÒM}–û%•ìÈÎM=ØöÌá ŸvÅ ’uUÿ©ÒMõœ ÎÁäöù:qœÀ, J…F—ì´ÏFíVEWì` µ×í,On}àÿ^íÞù4Î1O ùÁ œ º!­±`ÁðV/Ù–"aUOí` ¢ÑE)_UnGÑ!Få`UÉ“m—uÒÑGi”ié¡e™~jÒ‘÷¥QEµS^]+u¡é(Rs‰aû`FéR¾±áµ½á+ÊZƒ•Øÿ’ìxBYžZXÿÔúÐ ®-ºQƒ‘™,Ù  "÷ô/5XìÔâü‰Sž­–]Þ8QÂD¡%ú„홹RÒŒüŸüŸFaàô±1@Ü&Q)äZPZ¡‘ÁEÍÖÀ´!,ú#}ZÂ(Ù˜‰™ÀðÐ4­™ ¡Ù ÿ7•]’aŽyÛ@r™˜¤ó´ÐÉÐ9­ÙBœó0ã–I¤Á9_¸y#Èåäô„˜Š©]µ]Y!€Ž!¸*šO9DŽ®Õâ¯9™m™ßÙ)ÏEÍC?þcRJÖâ É™ÛS2Œ)ÆÌIrE¹•!T‚ÓÉ- R*eW®S ¯AåX*ŒÄŒ¸QeTX%µ¤¹¡Õ›Âp¥WÒ¥¯€%Yâ¥Ö eZúÄZæ¥ËÌe] f~ÜåÁäUà ß_Be7ò¥Lø¥b®L`æd^Fa’bñÞÁÈÒ¼ÌðÌÏþ` ¤•œ=¶•³1fcÂÄåè¤ÊÐä eMÀµŒh øQfmæÿ­5Ìñ]JMä4Iev.Y…Ð$~©©˜Áô•Ÿ!Î Œ·çËœ&jº„jþÚÂФÉ݌ȱŒSÒ¦m‚geâ&vÆ%ù ê¥ô8ÐGÍ[g-XþÐN%Uø@ñ õ!üÐyº5!bIPí¤×-‚fÐk!Ž)í'XQ'TèÞ–)Îò]ÁXS…–CÞUè|é$8•áIÔ<5ÚØ\H]ÕbótT&ygxÊèe_ÈØÀ„ *è(<ÉwyžiЉ9ŸV]‰“nNÜlå¨Rã(•MÕ’•”Vy_gÝ£ÊLg„®„¢ÿâÌÂ8æÏò˜ì°£òÝ“A_„©‘qŸRõè™j™®é´Ññå]‘+~çŒ*ZÈ"ÂܨŸ˜!} RP§o¾GÁÖ1å(8EÌVž•<¡úQíX*¦¾à?!U¢MØL—z©H€ié×ÄÅ’æôßM!b`¹Ðê™ ƒÅê)¾ÑJºÑ65¦ê° jÃОj­ê•¢>¢ûmÏÔUÔ¤NªFI‘"L°j*¢:iY«l½©¦Ÿ`¡jÇUâªÊD«> Q)ÒÝ`íÒS)ª^±—/µëE—`õúñ•SJ&±lD ªa*i4D‘ŸÍ[)ÚSÿàýR£F µ¤ü4’•¡¢–÷4iÂú&Yà‰kNý¤hɹP¹Bá¹¢+L€ãÆæëÁxлòê¼®+JZ0ñjgù*‚++þkÀú,3dÃô•˜(êmR!mg¢ÍÓü€PèÏáç}^UJ!Ž0&‘òmÓMS½Y“‚ £]PÓRƒ6§ÉÎÃ^¦luæU˜¾jDuŸ"C<²i ñôÓíè£(ÅmË®$&åÔ>ö++:AhÁá"nâ*îâ2nã:îãBnäJîäRnåZîåbnæjnå¬ %çÊ”VY†nÅ)g˜%ÂÄÉ9%½ŒÚ®-KXgéPÿ¾édRkö¤¾åjÒ®L¦SQÞnîÖn͂ﮯáMŠ¥À øAôJïôRoõZïõboöjïöro÷zï÷‚oøŠïø’ï÷rÁxvÎÐr"dŽúa ìÆîH<&û6 êÄïýv4IŽæ&ý\Dê%þÆÄüÒïÂØ¯#ð@èo30„&ðJpÌ?0þ.°Ö¤.^’Î"ç®åSkÊVpGD°L20_ðkfðX6\aa4åwr’§ðA”° «Ô ðûç¬BÒÑç´YÀpNbºf4Ñ’ýP ­Y¡ÝIèQÿÆÙ -1„9Q ½Y;©‘ÿÁ=QEÅÜ »#‹¤×ñ0HL¨« §qìÆÔó PÕRÓ©Ò¥ÓÂÒÝàž9T11í.YÓê¦PàURÇ:ÁŸè’Ö5Î0ê€!Ô.–+¹R4’¦‚‰ŽðUX[¦ª ¿ñ?øC>ä €À)£2 )—r*£ò*“²)»²*³²,»2,·ò,ã²-§ò.Ï2¼B(ß/=<êá4õb™æ+\ÉS!£?a•ÁœUaaomì5ëÑïñ™ëµ˜à®aû®+÷}3 ó9£³}óÁ`c fÝ{ŽjzUn¡aÓல«’­GµåýPÙ¶¤ •2¡©ÂÖ‰‘œÿË Œ<¾:ý4Ž‘ý(ŽŽë8ÑŠ)QÖÍð­÷¸^×ÐôX“5]\ð&AeÝíQì¼O&ù•ú¼ð‰Aš%üàóAsÏ”1šµÿ4ò|Í¥±ÏZkUóˆæÑÂ[9DØý/=mH' ü–ue[¶M¬pÃ$t«®TfvâZ‰" e_vi›6KdöLåg.ŒÒðgÇ¥¨1ôÿdŸvmÛöK¤6K°ªÞvo›vnë6ó¶owY·l6 FÚ Ä©˜'ÛL ßLóp-¿Åtq[·ewë*ÌÂÌl_3΀öÖämžìu›÷mDZAÎd90N›‘܇6š ‰â]˜ÞŽSé$|_çQ£"í@­ ¥]I‚“P=q(*FΕ±h÷Q›qT›1©O¾æpŸw† ³DwaÙd¾ÅkG—ÂO‰ó¹£ì¤™åñÄôýR>SªióLÂRµO05üÑV);Êx¼ñø}U`NåRé¡Òû4‘>·Ó¯a¸†Cù søüjmu_…ÕÎ#Ñ83ΪÿæT,Z m$jÕ¼xú¡VQÜŠõR3öWW…uS‹)…m#pUX¾=y”ëyO9jA••sª|µ’>£S¼’*™»o ûæúZ!“|5b/µ9¼Žùþµ’îÞ»qù›“,žW÷žƒúÛ4rî¬8ËS‰H»yk}à‡q™¢ÕU`ÊmF!ÕªÛùUG)wStMB¾‘v¨» _MV17AUsIß!óÔŽŒÓ­Œƒ¢·/™PƒµOéÅÄ™cŽ““Ÿ" ÑðÕ­sQX!ÑžµØ#zÿ= §m±ÓûoÑI1¯5ïÿ¬a7ÈxäôÝîBÜ[Þæìdç>j•‚÷ ½ä€“˜µO8õîf³Ÿ‘–á·ŽùY›e<ý.%̰×{ɯ*p+§gsMNõ¯n_ÝÀ¼ÉË|c¢|9:÷Ø0wpw-%Î|ÏÇoÍë¼bæ¹Ï½°}ÐçåÐýÒ‡Uö C1@}ÔƒA ÌÓK=ÔSýáþá~âþâC¾ã3þßSþäK~â_¾æg~ãw>9;¾è{¾âþÄ}à«~µÕƒ8ðÃëË8Èþì{:¼>?Ä>í˾íþîïþíç¾îó>îû~íñðÓ~ò#ÿñû>ó?¿ó ¿ô“C@;÷ƒôWÿô_ôo?÷c¿öo÷gÿ÷[ø›?ù‹õ«ú£ÿ÷·?ü¿ÿøÏ¿9;sitemesh-2.4.1+dfsg.orig/docs/history.html0000644000175000017500000001120111157162710020466 0ustar twernertwerner SiteMesh History and Crew

History

SiteMesh was originally written about 6 years ago, after Joe Walnes downloaded the first sun servlet engine and wrote it using servlet chains (before filters).

He had been using it internally for about 2 years and by the time it was open sourced it was quite mature. Over the years, the basic design remained the same; content was intercepted, parsed, a decorator mapper was used to find a decorator and they were merged together.

The original version used a bunch of regular expressions to extract the necessary chunks of text from the document. This was easy to get running, but very error prone as the matches had no context about where they were in a document. For example, a <title> element in a <head> block is very important to SiteMesh, however sometimes they appear elsewhere, such as in a comment, <script> or <xml> block.

This was dumped, in favour of a DOM based parser, which initially used JTidy to convert HTML to XHTML so it could be traversed as a standard DOM tree. Much nicer, but very, very sloow. Too slow, so sitemesh was switched to use OpenXML, an XML parser that was tolerant to nasty HTML, giving a slight boost to performance.

By this time, SiteMesh had been open-sourced, and along came Victor Salaman, who was the third user to discover it (after Mike Cannon-Brookes and Joseph Ottinger). He saw the potential but hated the parser. About three hours later, he'd produced his own version that used low-level string manipulation. It wasn't pretty, but it was very, very fast - twelve times faster than the OpenXML one, with the bonus feature of not rewriting great chunks of the document. This brought SiteMesh into the mainstream as it was now ready for use on high-traffic sites. 1.0 was released.

There were 2 main leaps that helped make it successful - the rewrite from servlet-chain to servlet-filter when the first draft of the Servlet 2.3 API came out and Victor Salaman rewriting the parser to make it about 12 times faster. In December 2003, Chris Miller and Hani Suleiman improved the parser to make it again 6 times faster and further minimize memory usage.

The SiteMesh Crew

  • Joe Walnes <joe at truemesh dot com>
  • Mathias Bogaert <pathos at pandora dot be>
  • Scott Farquhar <scott at atlassian dot com>
  • Mike Cannon-Brookes <mike at atlassian dot com>
  • Victor Salaman <salaman at teknos dot com>
  • Joseph Ottinger <joeo at adjacency dot org>
  • Hani Suleiman <fate at users dot sourceforge dot net>
  • Chris Miller <chris_overseas at hotmail dot com>
For any inquiries involving SiteMesh, please send an email to users@sitemesh.dev.java.net.

Who's using SiteMesh? What sites are using Sitemesh?

The following companies use (develop J2EE applications using) SiteMesh:

The following sites use SiteMesh:

Are you using Sitemesh? Please let us know, so that we can include you in this list!

sitemesh-2.4.1+dfsg.orig/docs/testsuite.html0000644000175000017500000000670111157162710021027 0ustar twernertwerner SiteMesh TestSuite

The idea behind the SiteMesh testsuite is that a full unit test can be performed on SiteMesh for all servers in one step. Whenever any changes are made, the full test-suite should be re-run. When new features are added, the test-suite should be modified and then SiteMesh modified until the tests pass again.

It consists of:

  • A web application that demonstrates all aspects of SiteMesh.
  • A set of unit tests built on top of JUnit and HttpUnit that check the correct output is being generated from the web-app.
  • A configurable deployment system that shall automate deployment of the web-app to lots of different app-servers/servlet-engines.
  • A configurable test-runner that shall run the unit tests against the web-apps deployed on the various servers.

What are the standalone tests?

The standalone tests consist at this moment mostly out of tests that try to break the HTMLPageParser by throwing a whole lot of very badly written HTML pages at it. Take a look at the testsuite/parser-tests directory for the testcases. Make sure you read the readme.txt file in that directory before you start writing your own tests. Here is a small overview of what we currenly test for:
  • not using html or body tags, see test5.txt, test6.txt and test15.txt
  • upper/lower case tag combinations, see test8.txt
  • not enclosing the attribute with double quotes (")
  • specifying a title more than once (the first one is used), see test11.txt
  • empty tags (<> and < >), see test10.txt
  • javascripts (containing > and <), see test16.txt and test25.txt
  • xmp tags, see test17.txt

If you would like to ignore certain tests (because they would break (fail) the nightly build), put the file name in the ignore.txt file.

Each time a modification is made to SiteMesh or the test-suite run 'ant test-standalone' (it will recompile and use the modified SiteMesh sources).

How do I test on multiple containers?

First, install all the app-servers/servlet-engines you wish to test with. The servers don't need to be on the same machine - so long as you can access the directory the web-apps are to be deployed to, they can be on other machines on the network.

Build the web-app with 'ant webapp-build'. Deploy the resulting .war file in the dist directory to each server. Fire up all the servers (and leave them running). Make sure they are not all trying to listen on the same port :)

Edit tests.xml. For each server, an entry should be made saying where the web-app is deployed to on the filesystem (the app can be a .war, .ear or unpacked directory) and what the URL to access it is.

Each time a modification is made to SiteMesh or the test-suite a two step process must be performed:

  1. Run 'ant deploy' to rebuild the web-app and redeploy it to each server.
  2. Run 'ant test' to run the testsuite against the new server.

It is important that the deployment process has completed on all servers before running the second step - this takes longer on some servers.

sitemesh-2.4.1+dfsg.orig/docs/freemarker-decorators.html0000644000175000017500000001077411157162710023271 0ustar twernertwerner Freemarker Decorators As of SiteMesh 2.0.2 Freemarker (.ftl) decorators are supported.

Here is an example of how such a decorator might look like:

<#include "/includes/decorators/header.dec">
    <h2>${title}</h2>
    ${head}
    <img src="${base}/images/logo.gif" border="0">
    <td valign="top" class="body">
        <div class="header">
            <span class="pagetitle">${title}</span>
        </div>
        ${body}
    </td>
<#include "/includes/decorators/footer.dec">

Installation

  • Download Freemarker 2.3 (recommended) and copy it into [web-app]/WEB-INF/lib. The SiteMesh distribution comes with freemarker.jar v2.3rc3

  • Add the following to [web-app]/WEB-INF/web.xml within the <web-app> tag:
<servlet>
    <servlet-name>sitemesh-freemarker</servlet-name>
    <servlet-class>com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet</servlet-class>
	<init-param>
		<param-name>TemplatePath</param-name>
		<param-value>/</param-value>
	</init-param>
	<init-param>
		<param-name>default_encoding</param-name>
		<param-value>ISO-8859-1</param-value>
	</init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>sitemesh-freemarker</servlet-name>
    <url-pattern>*.dec</url-pattern>
</servlet-mapping>
  • Modify decorators.xml to reference a .dec file.
<#include "/includes/decorators/header.dec">
    <h2>${title}</h2>
    ${head}
    <img src="${base}/images/logo.gif" border="0">
    <td valign="top" class="body">
        <div class="header">
            <span class="pagetitle">${title}</span>
        </div>
        ${body}
    </td>
<#include "/includes/decorators/footer.dec">

Context

FreemarkerDecoratorServlet puts some things into the context object that you should be aware of:

Basic context attributes

  • It makes all request, request parameters, session, and servlet context attributes available to templates through Request, RequestParameters, Session, and Application variables. For example :
    ${Session["user"]}
  • The scope variables are also available via automatic scope discovery. That is, writing Application.attrName, Session.attrName, Request.attrName is not mandatory; it's enough to write attrName, and if no such variable was created in the template, it will search the variable in Request, and then in Session, and finally in Application.
  • <#assign ww=JspTaglibs["/WEB-INF/webwork.tld"]>
  • It creates a variable with name JspTaglibs, that can be used to load JSP taglibs. For example:
    <#assign ww=JspTaglibs["/WEB-INF/webwork.tld"]>
    ...
    <@ww.property value="myVar"/>	
  • Sitemesh context attributes

    base request.getContextPath()
    title Parsed page title (<title>...<title>)
    head Parsed page head
    body Parsed page body
    page SiteMesh's internal Page object
    sitemesh-2.4.1+dfsg.orig/docs/dm.html0000644000175000017500000002515111157162710017376 0ustar twernertwerner SiteMesh DecoratorMappers

    When a page has been parsed, it then has to be mapped to a decorator. This mapping is performed by a chain of DecoratorMappers (referred to as mappers from here on).

    For each request, the first mapper in the chain is asked which decorator should be used. It is passed across a reference to the Page object and HttpServletRequest. It returns either a Decorator object, if it knows which decorator to be used, or null. If null is returned, the next mapper in the chain is queried. This whole process is repeated until there are no more mappers in the chain, or one of the mappers returns a valid decorator. If no mappers return a decorator, the page is not decorated at all and served in its original state.

    This way the mappers are chained together and queried is known as the Chain of Responsibility design pattern.

    Examples of mappers:

    • Determine decorator based on path of requested page.
    • Use different decorators based on time, locale or browser.
    • Use simplified decorators for search-engine robots.
    • Switch decorators based on a URL parameter, request attribute or meta-tag.
    • Use custom decorators based on user's saved settings...

    The main implementation of DecoratorMapper is ConfigDecoratorMapper which reads the decorators and mappings from /WEB-INF/decorators.xml. The appropriate decorator is then applied depending on the URL pattern.

    DecoratorMappers are simple to write and the distribution includes some samples that demonstrate how to write them and how flexible they can be. These are:
    AgentDecoratorMapper Can determine the user-agent (i.e. web-browser) requesting a page, and map to a suitable Decorator.
    ConfigDecoratorMapper Default implementation of DecoratorMapper. Reads decorators and mappings from the config property (default '/WEB- INF/decorators.xml').
    CookieDecoratorMapper Will map a suitable decorator based on a cookie value.
    EnvEntryDecoratorMapper Allows the reference to a web-app environment entry for the decorator name, and falls back to ConfigDecoratorMapper's behavior if no matching environment entry is found.
    FileDecoratorMapper Will treat the name of the decorator as a file-name to use (in the context of the web-app).
    FrameSetDecoratorMapper Will use the specified decorator when the Page is an instance of HTMLPage and isFrameSet() returns true. The name of this decorator should be supplied in the decorator property - if no decorator property is supplied, no decorator is applied to frame based pages.
    InlineDecoratorMapper Used to determine the correct Decorator when using inline decorators.
    LanguageDecoratorMapper Can determine the preferred language set in the browser requesting a page, and map to a suitable Decorator (using the "Accept-Language" HTTP header).
    PageDecoratorMapper The actual Page determines the Decorator to be used.

    The 'meta.decorator' and 'decorator' properties of the page are accessed and if any of them contain the name of a valid Decorator, that Decorator shall be applied.

    ParameterDecoratorMapper Will choose the decorator based on request parameters.

    The ParameterDecoratorMapper is configured via three properties.

    decorator.parameter - the parameter which contains the name of the decorator which will be mapped. The default is "decorator".

    For example if decorator.parameter is "foobar" then myurl.jsp?foobar=mydecorator will map to the decorator named "mydecorator".

    You can also supply an optional 'confirmation parameter'. The decorator will only be mapped if the parameter named parameter.name is in the request URI and the value of that parameter is equal to the parameter.value property.

    For example assuming parameter.name=confirm and parameter.value=true the URI myurl.jsp?decorator=mydecorator&confirm=true will map the decorator mydecorator. where as the URIs myurl.jsp?decorator=mydecorator and myurl.jsp?decorator=mydecorator&confirm=false will not return any decorator.

    SessionDecoratorMapper

    Will look at a session attribute to find the name of an appropriate decorator to use. If the session attribute is present, the mapper will not do anything and allow the next mapper in the chain to select a decorator.

    By default, it will look at the 'decorator' session attribute, however this can be overriden by configuring the mapper with a 'decorator.parameter' property.

    PrintableDecoratorMapper Will check to see whether 'printable=true' is supplied as a request parameter and if so, use the specified decorator instead. The name of this decorator should be supplied in the decorator property.
    RobotDecoratorMapper Will use the specified decorator when the requester is identified as a robot (also known as spider, crawler, ferret) of a search engine. The name of this decorator should be supplied in the decorator property.

    An example of a custom DecoratorMapper could be one that displays different Decorators based on time (e.g. morning, afternoon, Christmas, etc).

    Custom mapper configuration

    To be able to specify which mappers will be applied to a request, create the file [web-app]/WEB-INF/sitemesh.xml that contains the following:

    <sitemesh>
        <property name="decorators-file" value="/WEB-INF/decorators.xml" />
        <excludes file="${decorators-file}" />
    
        <page-parsers>
            <parser content-type="text/html"
                class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
            <parser content-type="text/html;charset=ISO-8859-1"
                class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
        </page-parsers>
    
        <decorator-mappers>
            <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
                <param name="config" value="${decorators-file}" />
            </mapper>
        </decorator-mappers>
    </sitemesh>
    

    In this example, the only mapper that will be applied is the ConfigDecoratorMapper, and that will only be applied to responses of type text/html or text/html;charset=ISO-8859-1. Responses of any other content type (eg image/gif) will be ignored by Sitemesh. Additionally, any files that match a pattern specified in the excludes file (in this case '/WEB-INF/decorators.xml') will not be touched by Sitemesh.

    The excludes file points to an XML file that contains an <excludes /> block similar to the following:

    <decorators>
        <excludes>
            <pattern>/plainPage.jsp</pattern>
            <pattern>/plain/*.jsp</pattern>
        </excludes>
    </decorators>
    

    The above example would prevent /plainPage.jsp and any JSP pages in the /plain directory from being decorated. (Note that the pattern matching follows exactly the same rules as the decorator mappings used by the ConfigDecoratorMapper.)

    Typically the <excludes /> block is just added at the start of the decorators.xml file, however this is not a requirement and any other XML file can be specified instead by changing the excludes file specified in sitemesh.xml. This might be useful if for example the ConfigDecoratorMapper is not being used in your deployment.

    Note that preventing pages from being decorated by adding them to the excludes list superceeds, and is a better approach than, the old method of mapping the pages to a non-existent decorator. This is because when pages were mapped to a non-existent decorator they were still buffered internally by Sitemesh. By using the exclude list Sitemesh will not let the request pass straight through to the servlet container without any buffering.

    Default mapper configuration

    If sitemesh.xml is not found in the WEB-INF dir, the default mapper configuration will be used. The default mapper configuration is defined in sitemesh-default.xml (packaged inside the jar) and consists of the following mappers:

    • PageDecoratorMapper
    • FrameSetDecoratorMapper
    • PrintableDecoratorMapper
    • FileDecoratorMapper
    • ConfigDecoratorMapper
    By default only content of type text/html will be decorated by Sitemesh. sitemesh-2.4.1+dfsg.orig/docs/meta.xml0000644000175000017500000001563011157162710017561 0ustar twernertwerner SiteMesh 10000 SIM SIM 3 7 8 Requirements requirements.html Feature List features.html Installation and Configuration install.html index.html true Flow Diagram flow.html Character Sets charsets.html Building Decorators decorators.html Velocity Decorators velocity-decorators.html Freemarker Decorators freemarker-decorators.html Decorator Mappers dm.html Test Suite testsuite.html FAQ faq.html Tag Reference tags.html Joe Walnes joe at truemesh dot com Creator and maintainer Mathias Bogaert m.bogaert at memenco dot com Scott Farquhar scott at atlassian dot com Mike Cannon-Brookes mike at atlassian dot com Victor Salaman salaman at teknos dot com Joseph Ottinger joeo at adjacency dot org Hani Suleiman fate at users dot sourceforge dot net Chris Miller chris_overseas at hotmail dot com 2.4 1/22/2009 21683 JAR https://sitemesh.dev.java.net/files/documents/887/124378/sitemesh-2.4.jar Full https://sitemesh.dev.java.net/files/documents/887/124379/sitemesh-2.4.zip Blank app https://sitemesh.dev.java.net/files/documents/887/124380/sitemesh-blank.war Example app https://sitemesh.dev.java.net/files/documents/887/124381/sitemesh-example.war 2.3 10/22/2006 21480 JAR https://sitemesh.dev.java.net/files/documents/887/43017/sitemesh-2.3.jar Full https://sitemesh.dev.java.net/files/documents/887/43018/sitemesh-2.3.zip Blank app https://sitemesh.dev.java.net/files/documents/887/43019/sitemesh-blank.war Example app https://sitemesh.dev.java.net/files/documents/887/43020/sitemesh-example.war 2.2.1 10/08/2004 21380 JAR https://sitemesh.dev.java.net/files/documents/887/7635/sitemesh-2.2.1.jar Full https://sitemesh.dev.java.net/files/documents/887/7636/sitemesh-2.2.1.zip Blank app https://sitemesh.dev.java.net/files/documents/887/7637/sitemesh-blank.war Example app https://sitemesh.dev.java.net/files/documents/887/7638/sitemesh-example.war 2.2 7/22/2004 21280 JAR https://sitemesh.dev.java.net/files/documents/887/7112/sitemesh-2.2.jar Full https://sitemesh.dev.java.net/files/documents/887/7115/sitemesh-2.2.zip Blank app https://sitemesh.dev.java.net/files/documents/887/7113/sitemesh-blank.war Example app https://sitemesh.dev.java.net/files/documents/887/7114/sitemesh-example.war sitemesh-2.4.1+dfsg.orig/docs/install.html0000644000175000017500000000444711157162712020453 0ustar twernertwerner SiteMesh Installation and Configuration

    Once SiteMesh has been downloaded (or built), configuration is simple.

    • Setup a web-app as usual (or skip all this by using the pre-configured sitemesh-blank.war).
    • Copy sitemesh-2.4.1.jar into [web-app]/WEB-INF/lib.
    • Create the file [web-app]/WEB-INF/decorators.xml that contains the following:

      <decorators>
      </decorators>
    • (Optional) Create the file [web-app]/WEB-INF/sitemesh.xml that contains the following:
      <sitemesh>
          <property name="decorators-file" value="/WEB-INF/decorators.xml" />
          <excludes file="${decorators-file}" />
      
          <page-parsers>
              <parser content-type="text/html"
                  class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
              <parser content-type="text/html;charset=ISO-8859-1"
                  class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
          </page-parsers>
      
          <decorator-mappers>
              <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
                  <param name="config" value="${decorators-file}" />
              </mapper>
          </decorator-mappers>
      </sitemesh>
      
    • Add the following to [web-app]/WEB-INF/web.xml within the <web-app> tag:

      <filter>
          <filter-name>sitemesh</filter-name>
          <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
      </filter>
      
      <filter-mapping>
          <filter-name>sitemesh</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      

    That's it! Your web-app is now setup to use SiteMesh, you can now start building decorators.

    sitemesh-2.4.1+dfsg.orig/docs/download.html0000644000175000017500000001531211157162710020603 0ustar twernertwerner Download SiteMesh

    Released Versions

    The following versions of SiteMesh are currently available.

    Please see Installation and Configuration for installation instructions.

    CVS Access

    The SiteMesh project is hosted at http://sitemesh.dev.java.net. You can browse the CVS tree here. Instructions for checking the code out of CVS are available here.

    Building

    To build SiteMesh from the sources, you must have the Java SDK version 1.4 or above, and Jakarta Ant version 1.5 or above.

    To build the SiteMesh binaries, change to the sitemesh directory, and type:

    ant

    If there are any errors, try clearing your classpath and retry.

    Upon completion, a directory called dist should have been created which contains sitemesh-{version}.jar (the actual library) and 2 .tld files (tag-library descriptors).

    Other build targets include:

    ant blank
    Builds the blank web-app (dist/sitemesh-blank.war).
    ant example
    Builds the sample web-app (dist/sitemesh-example.war).
    ant docs
    Builds the API JavaDoc and copies the documentation (dist/docs/).
    ant changelog
    Generates a changelog for the last 80 days (dist/docs/changelog.html).
    sitemesh-2.4.1+dfsg.orig/docs/charsets.html0000644000175000017500000000620211157162710020606 0ustar twernertwerner SiteMesh and Charsets

    Platform Defaults

    The default character set for SiteMesh is iso-8859-1. SiteMesh currently assumes that the underlying platform encoding is also iso-8859-1.

    This can cause some fairly insidious problems if there is a mismatch between the two! Specifically, on platforms which have a different file encoding, this should be overridden. The two known platforms which do not have iso-8859-1 encoding by default are IBM AS/400 JDK's and OSX. The work around in these cases is to specify a -Dfile.encoding=iso-8859-1 parameter as JVM argument when starting the application server.

    Using Other Encodings

    The iso-8859-1 encoding is sufficient for most European and Western character sets, so nothing will need to be done in this case. However, for other languages that require the full range of the UTF-8 character set, this has to be explicitly specified at a number of places, some SiteMesh specific, some app server specific/jsp specific.

    Note that the examples below all refer to UTF-8. The same approach applies to any encoding other than iso-8859-1, and is not limited to UTF-8.

    1. If possible, the web application should be configured to use UTF-8 as the default encoding. Orion allows this to be specific in orion-web.xml, as the default-charset attribute. Weblogic requires a context parameter named weblogic.httpd.inputCharset. See your application server documentation for more details. If the application server of choice does not allow to set the default charset for all web-apps, then every page (including the decorators) will need to specify the content-type. This is done by specifying a page header tag like this:

    <%@ page contentType="text/html; charset=utf-8"%>
    

    Note that some older versions of Orion do not respect the contentType page directive in included pages, so to be on the safe side, this directive should be specified in ALL pages, not just the top level one (one could use an include).

    2. The next step is to inform the browser that the page contents are of a specific character set. This is done by specifying a meta tag in the HEAD element of the html page, like this:

    <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8">
    

    3. The final step is informing SiteMesh's decorator mechanism that it should use a specific encoding other than the default. This is done by specifying an encoding attribute to the applyDecorator tag with the name of the encoding to use.

    <page:applyDecorator name="form" encoding="utf-8">
        ...
    </page:applyDecorator>
    
    sitemesh-2.4.1+dfsg.orig/docs/cache.jsp.txt0000644000175000017500000000013311157162710020500 0ustar twernertwerner<% response.setHeader("Cache-Control", "public"); response.setHeader("Pragma", "cache"); %>sitemesh-2.4.1+dfsg.orig/build.properties0000644000175000017500000000142611157162206020374 0ustar twernertwerner# Directs the compiler to try to generate faster code by inlining static, final and private methods. # This option may slow down compilation, make larger class files, and/or make it difficult to debug. # This option informs the compiler that all generated class files are guaranteed to be delivered and # upgraded as a unit, enabling optimizations that may otherwise break binary compatibility. # Use this option with discretion. compile.optimize = off # Starts the compiler in debugging mode. compile.debug = on # Indicates whether source should be compiled with deprecation information. compile.deprecation = on # Indicates whether -nowarn switch should be passed to the compiler. compile.nowarn = off # NAMING PROPERTIES Name = OpenSymphony SiteMesh name = sitemesh version = 2.4.1 sitemesh-2.4.1+dfsg.orig/src/0000755000175000017500000000000011157132034015737 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/0000755000175000017500000000000011157130046016717 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/0000755000175000017500000000000011157130046017475 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/0000755000175000017500000000000011157130046022245 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/0000755000175000017500000000000011157130046023532 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/0000755000175000017500000000000011157130046025353 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/multipass/0000755000175000017500000000000011157130046027374 5ustar twernertwerner././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/multipass/DivExtractingPageParserTest.javasitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/multipass/DivExtractingPageParser0000644000175000017500000000277310276421212034054 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.multipass; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.multipass.DivExtractingPageParser; import junit.framework.TestCase; import java.io.IOException; /** * @author Joe Walnes */ public class DivExtractingPageParserTest extends TestCase { public void testReplacesTopLevelDivsWithPlaceHolders() throws IOException { String input = "" + "\n" + " Title\n" + " \n" + "
    Hello
    \n" + " Blah\n" + "
    World
    Great
    \n" + "
    Bye
    \n" + " \n" + ""; PageParser parser = new DivExtractingPageParser(); Page page = parser.parse(input.toCharArray()); String expectedBody = "" + " \n" + " Blah\n" + " \n" + "
    Bye
    \n"; assertEquals("Title", page.getTitle()); assertEquals(expectedBody.trim(), page.getBody().trim()); assertEquals("
    Hello
    ", page.getProperty("div.one")); assertEquals("
    World
    Great
    ", page.getProperty("div.two")); } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/0000755000175000017500000000000011157130046026317 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/tokenizer/0000755000175000017500000000000011157130046030331 5ustar twernertwerner././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/tokenizer/MockTokenHandler.javasitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/tokenizer/MockTokenHandler.j0000644000175000017500000000370110162456004033675 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.tokenizer; import com.opensymphony.module.sitemesh.html.Tag; import com.opensymphony.module.sitemesh.html.Text; import junit.framework.Assert; class MockTokenHandler implements TokenHandler { private StringBuffer expected = new StringBuffer(); private StringBuffer actual = new StringBuffer(); public void expectText(String tag) { expected.append(tag); } public void expectTag(int type, String tag) { expectTag(type, tag, new String[0]); } public void expectTag(int type, String tag, String[] attributes) { expected.append("{{TAG : ").append(tag); for (int i = 0; i < attributes.length; i+=2) { expected.append(' ').append(attributes[i]).append("=\"").append(attributes[i + 1]).append('"'); } expected.append(' ').append(typeAsString(type)).append("}}"); } public boolean shouldProcessTag(String name) { Assert.assertNotNull("Name should not be null", name); return true; } public void tag(Tag tag) { actual.append("{{TAG : ").append(tag.getName()); for (int i = 0; i < tag.getAttributeCount(); i++) { actual.append(' ').append(tag.getAttributeName(i)).append("=\"").append(tag.getAttributeValue(i)).append('"'); } actual.append(' ').append(typeAsString(tag.getType())).append("}}"); } public void text(Text text) { actual.append(text.getContents()); } public void warning(String message, int line, int column) { Assert.fail("Encountered error: " + message); } public void verify() { Assert.assertEquals(expected.toString(), actual.toString()); } private String typeAsString(int type) { switch (type) { case Tag.OPEN: return "*open*"; case Tag.CLOSE: return "*close*"; case Tag.EMPTY: return "*empty*"; default: return "*unknown*"; } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/tokenizer/TagTokenizerTest.javasitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/tokenizer/TagTokenizerTest.j0000644000175000017500000003000410162456006033751 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.tokenizer; import com.opensymphony.module.sitemesh.html.Tag; import com.opensymphony.module.sitemesh.html.Text; import junit.framework.TestCase; public class TagTokenizerTest extends TestCase { private MockTokenHandler handler; protected void setUp() throws Exception { super.setUp(); handler = new MockTokenHandler(); } public void testSplitsTagsFromText() { // expectations handler.expectTag(Tag.OPEN, "hello"); handler.expectText("cruel"); handler.expectTag(Tag.OPEN, "world"); handler.expectTag(Tag.OPEN, "and"); handler.expectText("some stuff"); // execute TagTokenizer tokenizer = new TagTokenizer("cruelsome stuff"); tokenizer.start(handler); // verify handler.verify(); } public void testDistinguishesBetweenOpenCloseAndEmptyTags() { // expectations handler.expectTag(Tag.OPEN, "open"); handler.expectTag(Tag.CLOSE, "close"); handler.expectTag(Tag.EMPTY, "empty"); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testTreatsCommentsAsText() { // expectations handler.expectText("hello world "); handler.expectText(""); handler.expectText(""); handler.expectText(""); handler.expectText("good\n bye."); handler.expectTag(Tag.OPEN, "br"); // execute TagTokenizer tokenizer = new TagTokenizer("hello world good\n bye.
    "); tokenizer.start(handler); // verify handler.verify(); } public void testExtractsUnquotedAttributesFromTag() { // expectations handler.expectTag(Tag.OPEN, "hello", new String[]{"name", "world", "foo", "boo"}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testExtractsQuotedAttributesFromTag() { // expectations handler.expectTag(Tag.OPEN, "hello", new String[]{"name", "the world", "foo", "boo"}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testHandlesMixedQuoteTypesInAttributes() { // expectations handler.expectTag(Tag.OPEN, "hello", new String[]{"name", "it's good", "foo", "say \"boo\""}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testHandlesHtmlStyleEmptyAttributes() { // expectations handler.expectTag(Tag.OPEN, "hello", new String[]{"isgood", null, "and", null, "stuff", null}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testSupportsWhitespaceInElements() { // expectations handler.expectTag(Tag.OPEN, "hello", new String[]{"somestuff", "good", "foo", null, "x", "long\n string"}); handler.expectTag(Tag.EMPTY, "empty"); handler.expectTag(Tag.OPEN, "HTML", new String[]{"notonnewline", "yo", "newline", "hello", "anotherline", "bye"}); // execute TagTokenizer tokenizer = new TagTokenizer("" + "" + "" + ""); tokenizer.start(handler); // verify handler.verify(); } public void testExposesOriginalTagToHandler() { // Should really use a mock library for this expectation, but I'd rather not // add a new dependency for the sake of a single test. final String originalTag = ""; TagTokenizer tokenizer = new TagTokenizer("some text" + originalTag + "more text"); final boolean[] called = {false}; // has to be final array so anonymous inner class can change the value. tokenizer.start(new TokenHandler() { public boolean shouldProcessTag(String name) { return true; } public void tag(Tag tag) { assertEquals(originalTag, tag.getContents()); called[0] = true; } public void text(Text text) { // ignoring text for this test } public void warning(String message, int line, int column) { fail("Encountered error " + message); } }); assertTrue("tag() never called", called[0]); } public void testAllowsSlashInUnquotedAttribute() { // expectations handler.expectTag(Tag.OPEN, "something", new String[]{"type", "text/html"}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testAllowsTrailingQuoteOnAttribute() { // expectations handler.expectTag(Tag.OPEN, "something", new String[]{"type", "bl'ah\""}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } public void testAllowsAwkwardCharsInElementAndAttribute() { // expectations handler.expectTag(Tag.OPEN, "name:space", new String[]{"foo:bar", "x:y%"}); handler.expectTag(Tag.EMPTY, "a_b-c$d", new String[]{"b_b-c$d", "c_b=c$d"}); handler.expectTag(Tag.OPEN, "a", new String[]{"href", "/exec/obidos/flex-sign-in/ref=pd_nfy_gw_si/026-2634699-7306802?opt=a&page=misc/login/flex-sign-in-secure.html&response=tg/new-for-you/new-for-you/-/main"}); // execute TagTokenizer tokenizer = new TagTokenizer("" + "" + "" + ""); tokenizer.start(handler); // verify handler.verify(); } public void testTreatsXmpCdataScriptAndProcessingInstructionsAsText() { // expectations handler.expectText(""); handler.expectText("<evil \n<stuff<"); handler.expectText(""); handler.expectText("> <\n ]]>"); handler.expectText(""); handler.expectText(""); // execute TagTokenizer tokenizer = new TagTokenizer("" + "" + "<evil \n<stuff<" + "" + "> <\n ]]>" + "" + ""); tokenizer.start(handler); // verify handler.verify(); } public void testTreatsUnterminatedTagAtEofAsText() { // expectations handler.expectText("hello"); handler.expectText("< ><>"); tokenizer.start(handler); // verify handler.verify(); } public void testDoesNotTryToParseTagsUnlessTheHandlerCares() { // setup handler = new MockTokenHandler() { public boolean shouldProcessTag(String name) { return name.equals("good"); } }; // expectations handler.expectTag(Tag.OPEN, "good"); handler.expectText(""); handler.expectTag(Tag.CLOSE, "good"); handler.expectText(""); handler.expectText(""); tokenizer.start(handler); // verify handler.verify(); } public void testToleratesExtraQuoteClosingAttributeValue() { // expectations handler = new MockTokenHandler() { public void warning(String message, int line, int column) { // warning ok! } }; handler.expectTag(Tag.OPEN, "a", new String[] {"href", "something-with-a-naughty-quote"}); // execute TagTokenizer tokenizer = new TagTokenizer(""); tokenizer.start(handler); // verify handler.verify(); } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/HTMLProcessorTest.java0000644000175000017500000001071210456125670032477 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.html.rules.TagReplaceRule; import junit.framework.TestCase; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.io.StringWriter; import java.io.IOException; public class HTMLProcessorTest extends TestCase { public void testCreatesStateTransitionEvent() throws IOException { char[] input = "".toCharArray(); HTMLProcessor htmlProcessor = new HTMLProcessor(input, new CharArray(128)); State defaultState = htmlProcessor.defaultState(); final StringBuffer stateLog = new StringBuffer(); defaultState.addListener(new StateChangeListener() { public void stateFinished() { stateLog.append("finished"); } }); htmlProcessor.process(); assertEquals("finished", stateLog.toString()); } public void testSupportsConventionalReaderAndWriter() throws IOException { Reader in = new StringReader("world"); Writer out = new StringWriter(); HTMLProcessor processor = new HTMLProcessor(in, out); processor.addRule(new TagReplaceRule("b", "strong")); processor.process(); assertEquals("world", out.toString()); } public void testAllowsRulesToModifyAttributes() throws IOException { Reader in = new StringReader("world"); Writer out = new StringWriter(); HTMLProcessor processor = new HTMLProcessor(in, out); processor.addRule(new BasicRule("a") { public void process(Tag tag) { CustomTag customTag = new CustomTag(tag); String href = customTag.getAttributeValue("href", false); if (href != null) { href = href.toUpperCase(); customTag.setAttributeValue("href", true, href); } customTag.writeTo(currentBuffer()); } }); processor.process(); assertEquals("world", out.toString()); } public void testSupportsChainedFilteringOfTextContent() throws IOException { Reader in = new StringReader("world"); Writer out = new StringWriter(); HTMLProcessor processor = new HTMLProcessor(in, out); processor.addTextFilter(new TextFilter() { public String filter(String text) { return text.toUpperCase(); } }); processor.addTextFilter(new TextFilter() { public String filter(String text) { return text.replaceAll("O", "o"); } }); processor.process(); assertEquals("WoRLD", out.toString()); } public void testSupportsTextFiltersForSpecificStates() throws IOException { Reader in = new StringReader("la la
    la la laaaa
    laaaa
    la la"); Writer out = new StringWriter(); HTMLProcessor processor = new HTMLProcessor(in, out); State capsState = new State(); processor.addRule(new StateTransitionRule("capitalism", capsState, true)); capsState.addTextFilter(new TextFilter() { public String filter(String text) { return text.toUpperCase(); } }); processor.process(); assertEquals("la la
    la la LAAAA
    LAAAA
    la la", out.toString()); } public void testCanAddAttributesToCustomTag() throws IOException { CharArray buffer = new CharArray(64); String html = "

    Headline

    "; HTMLProcessor htmlProcessor = new HTMLProcessor(html.toCharArray(), buffer); htmlProcessor.addRule(new BasicRule() { public boolean shouldProcess(String tag) { return tag.equalsIgnoreCase("h1"); } public void process(Tag tag) { if (tag.getType() == Tag.OPEN) { CustomTag ctag = new CustomTag(tag); ctag.addAttribute("class", "y"); assertEquals(1, ctag.getAttributeCount()); tag = ctag; } tag.writeTo(currentBuffer()); } }); htmlProcessor.process(); assertEquals("

    Headline

    ", buffer.toString()); } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/rules/0000755000175000017500000000000011157130046027451 5ustar twernertwerner././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/rules/RegexReplacementTextFilterTest.javasitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/rules/RegexReplacementTextFi0000644000175000017500000000274510274764456034003 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import junit.framework.TestCase; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.io.StringWriter; import java.io.IOException; import com.opensymphony.module.sitemesh.html.HTMLProcessor; public class RegexReplacementTextFilterTest extends TestCase { public void testReplacesTextContentMatchedByRegularExpression() throws IOException { Reader in = new StringReader("Today is DATE so hi"); Writer out = new StringWriter(); HTMLProcessor processor = new HTMLProcessor(in, out); processor.addTextFilter(new RegexReplacementTextFilter("DATE", "1-jan-2009")); processor.process(); assertEquals("Today is 1-jan-2009 so hi", out.toString()); } public void testAllowsMatchedGroupToBeUsedInSubsitution() throws IOException { Reader in = new StringReader("I think JIRA:SIM-1234 is the way forward"); Writer out = new StringWriter(); HTMLProcessor processor = new HTMLProcessor(in, out); processor.addTextFilter(new RegexReplacementTextFilter( "JIRA:([A-Z]+\\-[0-9]+)", "$1")); processor.process(); assertEquals( "I think SIM-1234 is the way forward", out.toString()); } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/CustomTagTest.java0000644000175000017500000000271410272467170031744 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import junit.framework.TestCase; public class CustomTagTest extends TestCase { public void testWritesOutUserDefinedTag() { assertEquals("", new CustomTag("hello", Tag.EMPTY).getContents()); assertEquals("", new CustomTag("hello", Tag.OPEN).getContents()); assertEquals("", new CustomTag("hello", Tag.CLOSE).getContents()); } public void testWritesAttributes() { CustomTag tag = new CustomTag("hello", Tag.EMPTY); tag.addAttribute("color", "green"); tag.addAttribute("stuff", null); assertEquals("", tag.getContents()); } public void testAllowsAttributesToBeManipulated() { CustomTag tag = new CustomTag("hello", Tag.OPEN); assertEquals("", tag.getContents()); tag.addAttribute("a", "aaa"); tag.addAttribute("b", "bbb"); assertEquals("", tag.getContents()); tag.removeAttribute("b", false); assertEquals("", tag.getContents()); tag.setAttributeValue("a", false, "zzz"); assertEquals("", tag.getContents()); tag.addAttribute("c", "ccc"); int index = tag.getAttributeIndex("c", true); assertEquals(1, index); assertEquals("ccc", tag.getAttributeValue(index)); assertEquals("c", tag.getAttributeName(index)); } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/html/StateTest.java0000644000175000017500000000337410227016756031121 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import junit.framework.TestCase; public class StateTest extends TestCase { class DummyRule extends BasicRule { public DummyRule(String acceptableTagName) { super(acceptableTagName); } public void process(Tag tag) { throw new UnsupportedOperationException(); } } public void testMapsTagNameToRule() { TagRule mouseRule = new DummyRule("mouse"); TagRule donkeyRule = new DummyRule("donkey"); TagRule lemonRule = new DummyRule("lemon"); State state = new State(); state.addRule(mouseRule); state.addRule(donkeyRule); state.addRule(lemonRule); assertSame(donkeyRule, state.getRule("donkey")); assertSame(lemonRule, state.getRule("lemon")); assertSame(mouseRule, state.getRule("mouse")); } public void testExposesWhetherItShouldProcessATagBasedOnAvailableRules() { TagRule mouseRule = new DummyRule("mouse"); TagRule donkeyRule = new DummyRule("donkey"); TagRule lemonRule = new DummyRule("lemon"); State state = new State(); state.addRule(mouseRule); state.addRule(donkeyRule); state.addRule(lemonRule); assertTrue(state.shouldProcessTag("donkey")); assertTrue(state.shouldProcessTag("lemon")); assertFalse(state.shouldProcessTag("yeeeehaa")); } public void testReturnsMostRecentlyAddedRuleIfMultipleMatchesFound() { TagRule oldRule = new DummyRule("something"); TagRule newRule = new DummyRule("something"); State state = new State(); state.addRule(oldRule); state.addRule(newRule); assertSame(newRule, state.getRule("something")); } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/parser/0000755000175000017500000000000011157130046026647 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/parser/tokenizer/0000755000175000017500000000000011157130046030661 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/parser/HTMLPageParserTest.java0000644000175000017500000001526110174661270033103 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.PageParser; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.io.LineNumberReader; import java.io.Reader; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import junit.framework.TestCase; import junit.framework.TestSuite; import junit.framework.Test; /** * Test case for HTMLPageParser implementations. See parser-tests/readme.txt. * * @author Joe Walnes */ public class HTMLPageParserTest extends TestCase { /** * This test case builds a custom suite, containing a collection of smaller suites (one for each file in src/parser-tests). */ public static Test suite() throws IOException { TestSuite result = new TestSuite(HTMLPageParserTest.class.getName()); File[] files = listParserTests(new File("src/parser-tests")); PageParser[] parsers = new PageParser[] { /*new FastPageParser(),*/ new HTMLPageParser() }; for (int i = 0; i < parsers.length; i++) { PageParser parser = parsers[i]; String name = parser.getClass().getName(); TestSuite suiteForParser = new TestSuite(name); for (int j = 0; j < files.length; j++) { File file = files[j]; TestSuite suiteForFile = new TestSuite(file.getName().replace('.', '_')); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testTitle")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testBody")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testHead")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testFullPage")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testProperties")); suiteForParser.addTest(suiteForFile); } result.addTest(suiteForParser); } return result; } private HTMLPage page; private Map blocks; private String encoding; private final PageParser parser; private File file; public HTMLPageParserTest(PageParser parser, File inputFile, String test) { super(test); this.parser = parser; file = inputFile; encoding = "UTF8"; } protected void setUp() throws Exception { super.setUp(); // read blocks from input file. this.blocks = readBlocks(new FileReader(file)); // create PageParser and parse input block into HTMLPage object. String input = (String) blocks.get("INPUT"); this.page = (HTMLPage) parser.parse(input.toCharArray()); } public void testTitle() throws Exception { assertBlock("TITLE", page.getTitle()); } public void testBody() throws Exception { StringWriter body = new StringWriter(); page.writeBody(body); body.flush(); assertBlock("BODY", body.toString()); } public void testHead() throws Exception { StringWriter head = new StringWriter(); page.writeHead(head); head.flush(); assertBlock("HEAD", head.toString()); } public void testFullPage() throws Exception { StringWriter fullPage = new StringWriter(); page.writePage(fullPage); fullPage.flush(); assertBlock("INPUT", fullPage.toString()); } public void testProperties() throws Exception { Properties props = new Properties(); String propsString = (String) blocks.get("PROPERTIES"); ByteArrayInputStream input = new ByteArrayInputStream(propsString.trim().getBytes(encoding)); props.load(input); String[] pageKeys = page.getPropertyKeys(); assertEquals(file.getName() + " : Unexpected number of page properties [" + join(pageKeys) + "]", props.size(), pageKeys.length); for (int i = 0; i < pageKeys.length; i++) { String pageKey = pageKeys[i]; String blockValue = props.getProperty(pageKey); String pageValue = page.getProperty(pageKey); assertEquals(file.getName(), blockValue == null ? null : blockValue.trim(), pageValue == null ? null : pageValue.trim()); } } private String join(String[] values) { StringBuffer result = new StringBuffer(); for (int i = 0; i < values.length; i++) { if (i > 0) { result.append(','); } result.append(values[i]); } return result.toString(); } //------------------------------------------------- private static File[] listParserTests(File dir) throws IOException { // get list of files to ignore LineNumberReader ignoreReader = new LineNumberReader(new FileReader(new File(dir, "ignore.txt"))); final List ignoreFileNames = new ArrayList(); String line; while ((line = ignoreReader.readLine()) != null) { ignoreFileNames.add(line); } return dir.listFiles(new FilenameFilter() { public boolean accept(File currentDir, String name) { return name.startsWith("test") && !ignoreFileNames.contains(name); } }); } private void assertBlock(String blockName, String result) throws Exception { String expected = (String) blocks.get(blockName); assertEquals(file.getName() + " : Block did not match", expected.trim(), result.trim()); } /** * Read input to test and break down into blocks. See parser-tests/readme.txt */ private Map readBlocks(Reader input) throws IOException { Map blocks = new HashMap(); LineNumberReader reader = new LineNumberReader(input); String line; String blockName = null; StringBuffer blockContents = null; while ((line = reader.readLine()) != null) { if (line.startsWith("~~~ ") && line.endsWith(" ~~~")) { if (blockName != null) { blocks.put(blockName, blockContents.toString()); } blockName = line.substring(4, line.length() - 4); blockContents = new StringBuffer(); } else { if (blockName != null) { blockContents.append(line); blockContents.append('\n'); } } } if (blockName != null) { blocks.put(blockName, blockContents.toString()); } return blocks; } } sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/parser/testdata/0000755000175000017500000000000011157130046030460 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/parser/html/0000755000175000017500000000000011157130046027613 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/mapper/0000755000175000017500000000000011157130046026637 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/mapper/PathMapperTest.java0000644000175000017500000000640610057642602032415 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.mapper; import junit.framework.TestCase; public class PathMapperTest extends TestCase { private PathMapper pathMapper; protected void setUp() throws Exception { super.setUp(); pathMapper = new PathMapper(); // exact matches come first pathMapper.put("exact1", "/myexactfile.html"); pathMapper.put("exact2", "/mydir/myexactfile.html"); pathMapper.put("exact3", "/mydir/myexactfile.jsp"); pathMapper.put("exact4", "/mydir/dodo"); // then the complex matches pathMapper.put("complex1", "/mydir/*"); pathMapper.put("complex2", "/mydir/otherdir/*.jsp"); pathMapper.put("complex3", "/otherdir/*.??p"); pathMapper.put("complex4", "*.xml"); pathMapper.put("complex5", "/*/admin/*.??ml"); pathMapper.put("complex6", "/*/complexx/a*b.x?tml"); // if all the rest fails, use the default matches pathMapper.put("default", "*"); } public void testHardening() throws Exception { PathMapper bad = new PathMapper(); bad.put(null, null); assertNull(bad.get(null)); assertNull(bad.get("")); assertNull(bad.get("/somenonexistingpath")); } public void testFindExactKey() throws Exception { assertEquals("exact1", pathMapper.get("/myexactfile.html")); assertEquals("exact2", pathMapper.get("/mydir/myexactfile.html")); assertEquals("exact3", pathMapper.get("/mydir/myexactfile.jsp")); assertEquals("exact4", pathMapper.get("/mydir/dodo")); } public void testFindComplexKey() throws Exception { assertEquals("complex1", pathMapper.get("/mydir/")); assertEquals("complex1", pathMapper.get("/mydir/test1.xml")); assertEquals("complex1", pathMapper.get("/mydir/test321.jsp")); assertEquals("complex1", pathMapper.get("/mydir/otherdir")); assertEquals("complex2", pathMapper.get("/mydir/otherdir/test321.jsp")); assertEquals("complex3", pathMapper.get("/otherdir/test2.jsp")); assertEquals("complex3", pathMapper.get("/otherdir/test2.bpp")); assertEquals("complex4", pathMapper.get("/somedir/one/two/some/deep/file/test.xml")); assertEquals("complex4", pathMapper.get("/somedir/321.jsp.xml")); assertEquals("complex5", pathMapper.get("/mydir/otherdir/admin/myfile.html")); assertEquals("complex5", pathMapper.get("/mydir/somedir/admin/text.html")); assertEquals("complex6", pathMapper.get("/mydir/complexx/a-some-test-b.xctml")); assertEquals("complex6", pathMapper.get("/mydir/complexx/a b.xhtml")); assertEquals("complex6", pathMapper.get("/mydir/complexx/a___b.xhtml")); } public void testFindDefaultKey() throws Exception { assertEquals("default", pathMapper.get(null)); assertEquals("default", pathMapper.get("/")); assertEquals("default", pathMapper.get("/*")); assertEquals("default", pathMapper.get("*")); assertEquals("default", pathMapper.get("blah.txt")); assertEquals("default", pathMapper.get("somefilewithoutextension")); assertEquals("default", pathMapper.get("/file_with_underscores-and-dashes.test")); assertEquals("default", pathMapper.get("/tuuuu*/file.with.dots.test.txt")); } }sitemesh-2.4.1+dfsg.orig/src/test/com/opensymphony/module/sitemesh/mapper/ConfigLoaderTest.java0000644000175000017500000001243610127531774032715 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.mapper; import junit.framework.TestCase; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; public class ConfigLoaderTest extends TestCase { private ConfigLoader configLoader; private File tempConfigFile; protected void setUp() throws Exception { super.setUp(); // create temp file tempConfigFile = File.createTempFile("decorators-test", ".xml"); tempConfigFile.deleteOnExit(); // write to temp file BufferedWriter out = new BufferedWriter(new FileWriter(tempConfigFile)); out.write(""); // new format test decorators out.write(" "); out.write(" /info/*"); out.write(" "); out.write(" /test/*"); out.write(" "); out.write(" "); out.write(" "); out.write(" "); out.write(" "); out.write(" /other/*"); out.write(" "); out.write(" "); out.write(" /uri/*"); out.write(" "); out.write(" "); out.write(" /rolebased/*"); out.write(" "); // old format test decorator out.write(" "); out.write(" old"); out.write(" /decorators/old.jsp"); out.write(" "); out.write(" "); out.write(" old"); out.write(" /old/*"); out.write(" "); out.write(" "); out.write(" old2"); out.write(" "); out.write(" "); out.write(""); out.close(); configLoader = new ConfigLoader(tempConfigFile); } protected void tearDown() throws Exception { if (tempConfigFile != null) tempConfigFile.delete(); configLoader = null; } public void testMappedNames() throws Exception { assertEquals(configLoader.getMappedName("/info/somepage.html"), "default"); assertEquals(configLoader.getMappedName("/test/somepage.html"), "default"); assertEquals(configLoader.getMappedName("/other/someotherpage.html"), "other"); assertEquals(configLoader.getMappedName("/uri/somepage.html"), "uri"); assertEquals(configLoader.getMappedName("/rolebased/someotherpage.html"), "rolebaseddeveloper"); assertEquals(configLoader.getMappedName("/old/someoldpage.html"), "old"); } public void testDecoratorPresence() throws Exception { assertNotNull(configLoader.getDecoratorByName("default")); assertNotNull(configLoader.getDecoratorByName("other")); assertNotNull(configLoader.getDecoratorByName("uri")); assertNotNull(configLoader.getDecoratorByName("rolebaseddeveloper")); assertNotNull(configLoader.getDecoratorByName("old")); } public void testDecorators() throws Exception { assertEquals(configLoader.getDecoratorByName("default").getName(), "default"); assertEquals(configLoader.getDecoratorByName("default").getPage(), "/decorators/default.jsp"); assertNull(configLoader.getDecoratorByName("default").getURIPath()); assertNull(configLoader.getDecoratorByName("default").getRole()); assertEquals(configLoader.getDecoratorByName("other").getName(), "other"); assertEquals(configLoader.getDecoratorByName("other").getPage(), "/other.jsp"); // absolute path assertNull(configLoader.getDecoratorByName("other").getURIPath()); assertNull(configLoader.getDecoratorByName("other").getRole()); assertEquals(configLoader.getDecoratorByName("uri").getName(), "uri"); assertEquals(configLoader.getDecoratorByName("uri").getPage(), "/decorators/uri.jsp"); assertEquals(configLoader.getDecoratorByName("uri").getURIPath(), "/someapp"); assertNull(configLoader.getDecoratorByName("uri").getRole()); assertEquals(configLoader.getDecoratorByName("rolebaseddeveloper").getName(), "rolebased"); assertEquals(configLoader.getDecoratorByName("rolebaseddeveloper").getPage(), "/decorators/rolebased.jsp"); assertNull(configLoader.getDecoratorByName("rolebaseddeveloper").getURIPath()); assertEquals(configLoader.getDecoratorByName("rolebaseddeveloper").getRole(), "developer"); assertEquals(configLoader.getDecoratorByName("old").getName(), "old"); assertEquals(configLoader.getDecoratorByName("old").getPage(), "/decorators/old.jsp"); assertNull(configLoader.getDecoratorByName("old").getURIPath()); assertNull(configLoader.getDecoratorByName("old").getRole()); } }sitemesh-2.4.1+dfsg.orig/src/Sitemesh.iml0000644000175000017500000003233711157132034020233 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/etc/0000755000175000017500000000000011157130032016506 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/tld/0000755000175000017500000000000011157130032017271 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/tld/jsp1.2/0000755000175000017500000000000011157130032020306 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/tld/jsp1.2/sitemesh-page.tld0000644000175000017500000000570510051427522023562 0ustar twernertwerner 1.0 1.2 sitemesh-page http://www.opensymphony.com/sitemesh/page SiteMesh Page Tags applyDecorator com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag JSP name false true page false true title false true id false true contentType false true encoding false true apply-decorator com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag JSP name false true page false true title false true id false true contentType false true encoding false true param com.opensymphony.module.sitemesh.taglib.page.ParamTag JSP name false true sitemesh-2.4.1+dfsg.orig/src/etc/tld/jsp1.2/sitemesh-decorator.tld0000644000175000017500000000642510276421204024630 0ustar twernertwerner 1.0 1.2 sitemesh-decorator http://www.opensymphony.com/sitemesh/decorator SiteMesh Decorator Tags head com.opensymphony.module.sitemesh.taglib.decorator.HeadTag JSP body com.opensymphony.module.sitemesh.taglib.decorator.BodyTag JSP title com.opensymphony.module.sitemesh.taglib.decorator.TitleTag JSP default false true getProperty com.opensymphony.module.sitemesh.taglib.decorator.PropertyTag JSP property true true default false true writeEntireProperty false true extractProperty com.opensymphony.module.sitemesh.multipass.ExtractPropertyTag JSP property true true default false true writeEntireProperty false true usePage com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag com.opensymphony.module.sitemesh.taglib.decorator.UsePageTEI JSP id true false useHtmlPage com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag com.opensymphony.module.sitemesh.taglib.decorator.UseHTMLPageTEI JSP id true false sitemesh-2.4.1+dfsg.orig/src/etc/tld/sitemesh-page.tld0000644000175000017500000000460211017476420022544 0ustar twernertwerner 1.0 1.1 sitemesh-page-tags http://www.opensymphony.com/sitemesh/page applyDecorator com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag JSP name false true page false true title false true id false true contentType false true encoding false true apply-decorator com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag JSP name false true page false true title false true id false true contentType false true encoding false true param com.opensymphony.module.sitemesh.taglib.page.ParamTag JSP name false true sitemesh-2.4.1+dfsg.orig/src/etc/tld/sitemesh-decorator.tld0000644000175000017500000000523611017476420023616 0ustar twernertwerner 1.0 1.1 sitemesh-decorator-tags http://www.opensymphony.com/sitemesh/decorator head com.opensymphony.module.sitemesh.taglib.decorator.HeadTag JSP body com.opensymphony.module.sitemesh.taglib.decorator.BodyTag JSP title com.opensymphony.module.sitemesh.taglib.decorator.TitleTag JSP default false true getProperty com.opensymphony.module.sitemesh.taglib.decorator.PropertyTag JSP property true true default false true writeEntireProperty false true extractProperty com.opensymphony.module.sitemesh.multipass.ExtractPropertyTag JSP property true true default false true writeEntireProperty false true usePage com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag com.opensymphony.module.sitemesh.taglib.decorator.UsePageTEI JSP id true false useHtmlPage com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag com.opensymphony.module.sitemesh.taglib.decorator.UseHTMLPageTEI JSP id true false sitemesh-2.4.1+dfsg.orig/src/etc/dtd/0000755000175000017500000000000011157130032017261 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/dtd/sitemesh_1_5_decorators.dtd0000644000175000017500000000223010111307322024462 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/etc/dtd/sitemesh_1_0_decorators.dtd0000644000175000017500000000256207757210412024504 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/etc/blank/0000755000175000017500000000000011157130032017575 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/blank/WEB-INF/0000755000175000017500000000000011157130032020624 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/blank/WEB-INF/decorators.xml0000644000175000017500000000044210036472054023523 0ustar twernertwerner /* sitemesh-2.4.1+dfsg.orig/src/etc/blank/WEB-INF/web.xml0000644000175000017500000000151010550354754022137 0ustar twernertwerner sitemesh com.opensymphony.sitemesh.webapp.SiteMeshFilter sitemesh /* sitemesh-page /WEB-INF/lib/sitemesh-page.tld sitemesh-decorator /WEB-INF/lib/sitemesh-decorator.tld sitemesh-2.4.1+dfsg.orig/src/etc/blank/decorators/0000755000175000017500000000000011157130032021742 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/etc/blank/decorators/printable.jsp0000644000175000017500000000061310051427522024445 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Welcome!" /> Printed on <%=new java.util.Date()%>.


    sitemesh-2.4.1+dfsg.orig/src/etc/blank/decorators/main.jsp0000644000175000017500000000054210051427522023412 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> My Site - <decorator:title default="Welcome!" />

    (printable version)

    sitemesh-2.4.1+dfsg.orig/src/etc/blank/decorators/panel.jsp0000644000175000017500000000051110051427522023561 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>

    sitemesh-2.4.1+dfsg.orig/src/etc/blank/index.jsp0000644000175000017500000000017707751471036021450 0ustar twernertwerner Hello world!

    Hello world!

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/0000755000175000017500000000000011157130046020374 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/parser-tests/test32.txt0000644000175000017500000000076610124214746022275 0ustar twernertwerner~~~ INPUT ~~~ "); window.document.writeln (""); } ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ "); window.document.writeln (""); } ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/readme.txt0000644000175000017500000000214710057642564022411 0ustar twernertwernerThe files in this directory are used to test the HTMLPageParser. The layout of the files is like this: ~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    Each block is identified by ~~~ BLAH ~~~ and lasts until either the next block starts or the end of the file. The INPUT block is fed into the parser, and then TITLE, PROPERTIES, HEAD and BODY blocks are compared to the results of the parser. Blocks will have leading and trailing whitespace ignored during the comparison. The PROPERTIES block takes the syntax of a standard java properties file. To add a new test, just place a new file called 'test??.txt' in this directory. File names listed in ignore.txt will be skipped.sitemesh-2.4.1+dfsg.orig/src/parser-tests/ignore.txt0000644000175000017500000000000110057642564022422 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/parser-tests/test17.txt0000644000175000017500000000156310057642572022303 0ustar twernertwerner~~~ INPUT ~~~ Some page

    Here's some src code:

    
         <html>
           <head>
             <title>XXX</title>
           </head>
           <body>
             This is something.
           </body>
         </html>
       

    Bye.

    ignore this! ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    Here's some src code:

    
         <html>
           <head>
             <title>XXX</title>
           </head>
           <body>
             This is something.
           </body>
         </html>
       

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test18.txt0000644000175000017500000000153610057642574022306 0ustar twernertwerner~~~ INPUT ~~~ Some page

    Here's some src code:

    XXX This is something.

    Bye.

    ignore this! ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    Here's some src code:

    XXX This is something.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test14.txt0000644000175000017500000006250610057642572022304 0ustar twernertwerner~~~ INPUT ~~~ OpenSymphony - Welcome To OpenSymphony
      Home | News | Guidelines | Contribute | The Team | Contact  SourceForge Project:  Homepage Bugs @ Sourceforge Mailing Lists @ Sourceforge Task Manager @ Sourceforge CVS @ Sourceforge
    Modules
    Production Quality
     » OSCache
     » SiteMesh
     » FormTags
     » TransformTags
     » OSCore

    Beta / Developing
     » OSUser
     » WebCompass
     » RichTags
     » OSAccess
     » OSWorkflow

    Attic (Old components that are no longer actively developed)
     » OSContent
     » Clickstream
     » OSContact

    Project Documentation
     » What Is OpenSymphony?
     » Architectural Overview
     » The Components

    Mirrors/Sponsor Companies
    These companies have contributed a lot to OpenSymphony and we thank them.


    Want to keep informed?
    Why not subscribe to our mailing lists?

    Keep up to date with the latest announcements, ask questions and discuss future directions of the project.

     
    { Welcome To OpenSymphony }
    The Open Source J2EE component project

    OpenSymphony is an Open Source project dedicated to providing enterprise class J2EE applications and components. Our components aim to be specification compliant, and should work in any J2EE compliant application server. (Although some components only require a servlet container rather than a full J2EE app server).

    See What Is OpenSymphony? and the OpenSymphony Architectural Overview for more detail.

    Components

    Production Quality

    • OSCache - A JSP tag library and set of classes to perform fine grained dynamic caching of JSP content. It also has persistent on disk caches, and can allow your site to have graceful error tolerance (eg if an error occurs like your db goes down, you can serve the cached content so people can still surf the site almost without knowing). [requires Servlet 2.2 / JSP 1.1]
    • SiteMesh - This is a servlet filter + tag library component that uses decorators to allow for excellent site layout and web app integration (ie you can integrate legacy web apps that are perl or CF based with your current J2EE apps - very cool) [requires Servlet 2.3 / JSP 1.1]
    • FormTags - A JSP taglib designed to make integration of HTML forms and Javabeans relatively orthogonal and convenient.
    • Transformtags - A JSP taglib designed to provide tags to transform source content from one form to another. For example, it contains a tag to apply XSL to XML content, as well as a tag to escape HTML text and search/replace content.
    • OSCore - Core components that are useful in any J2EE application. The most used component here is the PropertySet EJB, an EJB properties object that's very flexible and can be constrained by a PropertySetSchema.

    Beta (Developing Components)

    • OSUser - A set of user management EJB components that will work on any EJB server. At the moment every server has its own user management API. This project is an attempt to unite them to make your applications truly portable between app servers. [requires EJB 1.1 / OSCore components]
    • RichTags - A JSP taglib designed to allow rich GUI user-interface and data-entry widgets to be used in HTML based web-applications.
    • WebCompass - A combination of an EJB package and a tag library to provide site navigation and organization.
    • OSWorkflow - A very flexible workflow system that can be plugged in to almost any need or existing application. Uses can range from document management to order processing to project management. [requires EJB 1.1 / OSCore & OSUser components]

    Latest News

    OSCore 1.1 Released - 2002/04/30

    New OSCache Release - 2002/01/08

    Project Refactoring, OSCache Class Diagrams - 2001/12/14

    TransformTags updated - 2001/11/19

    Radical new OSCache release! - 2001/11/07

    TransformTags released! - 2001/10/25

    Website Updates - 2001/10/04

    OSUser Docs online - 2001/09/28

    TransformTags 1.0 RC1 available! - 2001/09/24

    WebCompass, TransformTags docs moved - 2001/09/24

    SiteMesh 1.3 released - 2001/09/23

    OSCache 1.6.1 released - 2001/09/17


      Home | News | Guidelines | Contribute | The Team | Contact Project managed at: SourceForge Logo
    Copyright 2000-2001 - The Team - Contact Us & Mailing Lists

    ~~~ TITLE ~~~ OpenSymphony - Welcome To OpenSymphony ~~~ PROPERTIES ~~~ title=OpenSymphony - Welcome To OpenSymphony body.bgcolor=#FFFFFF body.leftmargin=0 body.topmargin=0 body.marginwidth=0 body.marginheight=0 ~~~ HEAD ~~~ ~~~ BODY ~~~
      Home | News | Guidelines | Contribute | The Team | Contact  SourceForge Project:  Homepage Bugs @ Sourceforge Mailing Lists @ Sourceforge Task Manager @ Sourceforge CVS @ Sourceforge
    Modules
    Production Quality
     » OSCache
     » SiteMesh
     » FormTags
     » TransformTags
     » OSCore

    Beta / Developing
     » OSUser
     » WebCompass
     » RichTags
     » OSAccess
     » OSWorkflow

    Attic (Old components that are no longer actively developed)
     » OSContent
     » Clickstream
     » OSContact

    Project Documentation
     » What Is OpenSymphony?
     » Architectural Overview
     » The Components

    Mirrors/Sponsor Companies
    These companies have contributed a lot to OpenSymphony and we thank them.


    Want to keep informed?
    Why not subscribe to our mailing lists?

    Keep up to date with the latest announcements, ask questions and discuss future directions of the project.

     
    { Welcome To OpenSymphony }
    The Open Source J2EE component project

    OpenSymphony is an Open Source project dedicated to providing enterprise class J2EE applications and components. Our components aim to be specification compliant, and should work in any J2EE compliant application server. (Although some components only require a servlet container rather than a full J2EE app server).

    See What Is OpenSymphony? and the OpenSymphony Architectural Overview for more detail.

    Components

    Production Quality

    • OSCache - A JSP tag library and set of classes to perform fine grained dynamic caching of JSP content. It also has persistent on disk caches, and can allow your site to have graceful error tolerance (eg if an error occurs like your db goes down, you can serve the cached content so people can still surf the site almost without knowing). [requires Servlet 2.2 / JSP 1.1]
    • SiteMesh - This is a servlet filter + tag library component that uses decorators to allow for excellent site layout and web app integration (ie you can integrate legacy web apps that are perl or CF based with your current J2EE apps - very cool) [requires Servlet 2.3 / JSP 1.1]
    • FormTags - A JSP taglib designed to make integration of HTML forms and Javabeans relatively orthogonal and convenient.
    • Transformtags - A JSP taglib designed to provide tags to transform source content from one form to another. For example, it contains a tag to apply XSL to XML content, as well as a tag to escape HTML text and search/replace content.
    • OSCore - Core components that are useful in any J2EE application. The most used component here is the PropertySet EJB, an EJB properties object that's very flexible and can be constrained by a PropertySetSchema.

    Beta (Developing Components)

    • OSUser - A set of user management EJB components that will work on any EJB server. At the moment every server has its own user management API. This project is an attempt to unite them to make your applications truly portable between app servers. [requires EJB 1.1 / OSCore components]
    • RichTags - A JSP taglib designed to allow rich GUI user-interface and data-entry widgets to be used in HTML based web-applications.
    • WebCompass - A combination of an EJB package and a tag library to provide site navigation and organization.
    • OSWorkflow - A very flexible workflow system that can be plugged in to almost any need or existing application. Uses can range from document management to order processing to project management. [requires EJB 1.1 / OSCore & OSUser components]

    Latest News

    OSCore 1.1 Released - 2002/04/30

    New OSCache Release - 2002/01/08

    Project Refactoring, OSCache Class Diagrams - 2001/12/14

    TransformTags updated - 2001/11/19

    Radical new OSCache release! - 2001/11/07

    TransformTags released! - 2001/10/25

    Website Updates - 2001/10/04

    OSUser Docs online - 2001/09/28

    TransformTags 1.0 RC1 available! - 2001/09/24

    WebCompass, TransformTags docs moved - 2001/09/24

    SiteMesh 1.3 released - 2001/09/23

    OSCache 1.6.1 released - 2001/09/17


      Home | News | Guidelines | Contribute | The Team | Contact Project managed at: SourceForge Logo

    Copyright 2000-2001 - The Team - Contact Us & Mailing Lists

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test19.txt0000644000175000017500000000152610057642574022306 0ustar twernertwerner~~~ INPUT ~~~ Some page

    Here's some src code:

    Bye.

    ignore this! ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    Here's some src code:

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test31.txt0000644000175000017500000000023110057642600022256 0ustar twernertwerner~~~ INPUT ~~~ ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test21.txt0000644000175000017500000000154010057642574022273 0ustar twernertwerner~~~ INPUT ~~~ Some page

    Here's some src code:

    XXX This is something. ]]>

    Bye.

    ignore this! ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    Here's some src code:

    XXX This is something. ]]>

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test15.txt0000644000175000017500000000047110057642572022276 0ustar twernertwerner~~~ INPUT ~~~

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= meta.blah=cheese ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test27.txt0000644000175000017500000000042610057642576022305 0ustar twernertwerner~~~ INPUT ~~~ Here's some title ~~~ TITLE ~~~ Here's some title ~~~ PROPERTIES ~~~ title=Here's some title meta.author=Joe ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test29.txt0000644000175000017500000000070610057642600022274 0ustar twernertwerner~~~ INPUT ~~~ ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test37.txt0000644000175000017500000001164710127513262022300 0ustar twernertwerner~~~ INPUT ~~~ Google
    Google

    Web     Images    Groups    News     more »
     
      Advanced Search
      Preferences
      Language Tools
    Search:



    Advertising Programmes - About Google - Go to Google.com

    ©2004 Google - Searching 4,285,199,774 web pages

    ~~~ TITLE ~~~ Google ~~~ PROPERTIES ~~~ title=Google meta.http-equiv.content-type=text/html; charset=UTF-8 body.bgcolor=#ffffff body.text=#000000 body.link=#0000cc body.vlink=#551a8b body.alink=#ff0000 body.onLoad=sf() ~~~ HEAD ~~~ ~~~ BODY ~~~
    Google

    Web     Images    Groups    News     more »
     
      Advanced Search
      Preferences
      Language Tools
    Search:



    Advertising Programmes - About Google - Go to Google.com

    ©2004 Google - Searching 4,285,199,774 web pages

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test39.txt0000644000175000017500000000107410550421526022274 0ustar twernertwernerThis test proves that http://jira.opensymphony.com/browse/SIM-206 isn't a problem anymore. ~~~ INPUT ~~~ Some page

    This is a pretty simple page with an XML processing instruction header.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page with an XML processing instruction header.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test09.txt0000644000175000017500000000041010057642570022270 0ustar twernertwerner~~~ INPUT ~~~
    Bye
    ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~
    Bye
    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test41.txt0000644000175000017500000000043110550416146022263 0ustar twernertwernerThis test illustrates http://jira.opensymphony.com/browse/SIM-216. If tags are not matched, Sitemesh used to throw a NoSuchElementException. Handle unmatched tags ~~~ INPUT ~~~ Tongor ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ Tongor sitemesh-2.4.1+dfsg.orig/src/parser-tests/test13.txt0000644000175000017500000000075510057642572022301 0ustar twernertwerner~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    Bye.

    This should be here ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    This should be here sitemesh-2.4.1+dfsg.orig/src/parser-tests/test26.txt0000644000175000017500000000030110057642576022274 0ustar twernertwerner~~~ INPUT ~~~ blahblah ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ blahblahsitemesh-2.4.1+dfsg.orig/src/parser-tests/test01.txt0000644000175000017500000000102610057642566022271 0ustar twernertwerner~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test23.txt0000644000175000017500000000164510126462134022270 0ustar twernertwerner~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    xy xy x This is some more content.... Woo.xxxy

    Bye.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black page.icon=thing.gif page.category=news page.somecontent=\n This is some more content.... \n Woo. page.more=xxx ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    xy xy xy

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test05.txt0000644000175000017500000000030710057642566022276 0ustar twernertwerner~~~ INPUT ~~~ Simple page2

    Hello world 2

    ~~~ TITLE ~~~ Simple page2 ~~~ PROPERTIES ~~~ title=Simple page2 ~~~ HEAD ~~~ ~~~ BODY ~~~

    Hello world 2

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test02.txt0000644000175000017500000000045510057642566022277 0ustar twernertwerner~~~ INPUT ~~~ Hi.
    Bye
    ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ Hi.
    Bye
    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test22.txt0000644000175000017500000000114710057642574022277 0ustar twernertwerner~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black decorator=something language=en ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test35.txt0000644000175000017500000000040210105461206022255 0ustar twernertwerner~~~ INPUT ~~~ my title hi ~~~ TITLE ~~~ my title ~~~ PROPERTIES ~~~ title=my title notonnewline=yo newline=hello anotherline=bye ~~~ HEAD ~~~ ~~~ BODY ~~~ hisitemesh-2.4.1+dfsg.orig/src/parser-tests/test12.txt0000644000175000017500000000056210057642570022272 0ustar twernertwerner~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    Bye.

    This should be ignored!! ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test28.txt0000644000175000017500000000120010057642576022275 0ustar twernertwerner~~~ INPUT ~~~ Application Test

    Application Test

    ~~~ TITLE ~~~ Application Test ~~~ PROPERTIES ~~~ title=Application Test ~~~ HEAD ~~~ ~~~ BODY ~~~

    Application Test

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test03.txt0000644000175000017500000000050210057642566022271 0ustar twernertwerner~~~ INPUT ~~~ SiteMesh test suite

    SiteMesh test suite!

    Now

    ~~~ TITLE ~~~ SiteMesh test suite ~~~ PROPERTIES ~~~ title=SiteMesh test suite ~~~ HEAD ~~~ ~~~ BODY ~~~

    SiteMesh test suite!

    Now

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test33.txt0000644000175000017500000000053410057642600022266 0ustar twernertwerner~~~ INPUT ~~~ Here's some title ~~~ TITLE ~~~ Here's some title ~~~ PROPERTIES ~~~ xmlns\:prefix=www.opensymphony.com title=Here's some title meta.author=Joe ~~~ HEAD ~~~ ~~~ BODY ~~~sitemesh-2.4.1+dfsg.orig/src/parser-tests/test24.txt0000644000175000017500000000126510057642576022304 0ustar twernertwerner~~~ INPUT ~~~ Some page

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black meta.http-equiv.content-type=text/html ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test43.txt0000644000175000017500000000137610550417256022301 0ustar twernertwernerThis test illustrates http://jira.opensymphony.com/browse/SIM-172 Unclosed quotes cause parsing problem (note unclosed quote after the first 'area' tag) ~~~ INPUT ~~~ ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test10.txt0000644000175000017500000000044510057642570022270 0ustar twernertwerner~~~ INPUT ~~~ < > page title second title - THIS IS WRONG < ><> < ><>

    PAGE BODY

    ~~~ TITLE ~~~ page title ~~~ PROPERTIES ~~~ title=page title ~~~ HEAD ~~~ ~~~ BODY ~~~

    PAGE BODY

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test30.txt0000644000175000017500000000072610057642600022266 0ustar twernertwerner~~~ INPUT ~~~ ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test34.txt0000644000175000017500000000040410057642602022265 0ustar twernertwerner~~~ INPUT ~~~ Hello World! HTML

    Hello World! HTML

    ~~~ TITLE ~~~ Hello World! HTML ~~~ PROPERTIES ~~~ title=Hello World! HTML ~~~ HEAD ~~~ ~~~ BODY ~~~

    Hello World! HTML

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test08.txt0000644000175000017500000000063410057642570022277 0ustar twernertwerner~~~ INPUT ~~~ Here's some title
    Bye
    ~~~ TITLE ~~~ Here's some title ~~~ PROPERTIES ~~~ title=Here's some title meta.author=Joe ~~~ HEAD ~~~ ~~~ BODY ~~~
    Bye
    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test42.txt0000644000175000017500000000071710550416742022275 0ustar twernertwernerThis test illustrates http://jira.opensymphony.com/browse/SIM-180. Header content after a tag gets treated as part of the body ~~~ INPUT ~~~ Blah Etc. Blah blah blah ~~~ TITLE ~~~ Blah ~~~ PROPERTIES ~~~ title=Blah page.contentblah=Etc. ~~~ HEAD ~~~ ~~~ BODY ~~~ Blah blah blah sitemesh-2.4.1+dfsg.orig/src/parser-tests/test44.txt0000644000175000017500000000042310675577512022304 0ustar twernertwernerThis test illustrates http://jira.opensymphony.com/browse/SIM-241 Closing the HEAD tag without a corresponding opening tag throws and ArrayOutOfBoundsException ~~~ INPUT ~~~ ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test20.txt0000644000175000017500000000161010057642574022270 0ustar twernertwerner~~~ INPUT ~~~ Some page

    Here's some src code:

    Bye.

    ignore this! ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page meta.author=Someone body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    Here's some src code:

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test38.txt0000644000175000017500000002040710127513262022273 0ustar twernertwerner~~~ INPUT ~~~ Title of the page

    hello

     

    this is a document generated by Microsoft Word XP

    ~~~ TITLE ~~~ Title of the page ~~~ PROPERTIES ~~~ xmlns\:o=urn\:schemas-microsoft-com\:office\:office xmlns\:w=urn\:schemas-microsoft-com\:office\:word xmlns=http\://www.w3.org/TR/REC-html40 body.lang=EN-US body.style=tab-interval\:.5in meta.http-equiv.Content-Type=text/html\; charset=windows-1252 meta.ProgId=Word.Document meta.Generator=Microsoft Word 10 meta.Originator=Microsoft Word 10 title=Title of the page office.DocumentProperties.Author=Joe Walnes office.DocumentProperties.LastAuthor=Joe Walnes office.DocumentProperties.Revision=1 office.DocumentProperties.TotalTime=0 office.DocumentProperties.Created=2004-09-30T07\:40\:00Z office.DocumentProperties.LastSaved=2004-09-30T07\:40\:00Z office.DocumentProperties.Pages=1 office.DocumentProperties.Words=8 office.DocumentProperties.Characters=49 office.DocumentProperties.Company=ThoughtWorks Inc. office.DocumentProperties.Lines=1 office.DocumentProperties.Paragraphs=1 office.DocumentProperties.CharactersWithSpaces=56 office.DocumentProperties.Version=10.4219 ~~~ HEAD ~~~ ~~~ BODY ~~~

    hello

     

    this is a document generated by Microsoft Word XP

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test11.txt0000644000175000017500000000056510057642570022274 0ustar twernertwerner~~~ INPUT ~~~ Some page WRONG TITLE

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ Some page ~~~ PROPERTIES ~~~ title=Some page body.bgcolor=black ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test06.txt0000644000175000017500000000016110057642566022275 0ustar twernertwerner~~~ INPUT ~~~ Hello world 3 ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ Hello world 3sitemesh-2.4.1+dfsg.orig/src/parser-tests/test25.txt0000644000175000017500000000134210057642576022301 0ustar twernertwerner~~~ INPUT ~~~ ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= ~~~ HEAD ~~~ ~~~ BODY ~~~ sitemesh-2.4.1+dfsg.orig/src/parser-tests/test04.txt0000644000175000017500000000037610057642566022303 0ustar twernertwerner~~~ INPUT ~~~ Simple page1

    Hello world 1

    ~~~ TITLE ~~~ Simple page1 ~~~ PROPERTIES ~~~ title=Simple page1 ~~~ HEAD ~~~ ~~~ BODY ~~~

    Hello world 1

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test07.txt0000644000175000017500000000031610057642570022273 0ustar twernertwerner~~~ INPUT ~~~ panel 1 The first panel ~~~ TITLE ~~~ panel 1 ~~~ PROPERTIES ~~~ title=panel 1 ~~~ HEAD ~~~ ~~~ BODY ~~~ The first panelsitemesh-2.4.1+dfsg.orig/src/parser-tests/test40.txt0000644000175000017500000000104510166306700022261 0ustar twernertwerner~~~ INPUT ~~~ Support

    Empty at the moment. See contact.

    ~~~ TITLE ~~~ Support ~~~ PROPERTIES ~~~ title=Support mce_editor_0_formatSelect=

    mce_editor_0_styleSelect= meshcmsmodules=gallery_pooh_1999 ~~~ HEAD ~~~ ~~~ BODY ~~~

    Empty at the moment. See contact.

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test36.txt0000644000175000017500000032312510127513262022274 0ustar twernertwerner~~~ INPUT ~~~ Amazon.co.uk: Welcome International How to order Sell Your Stuff Harry Potter Shop Disney View the contents of your Shopping Basket Create or view a list of products you'd love to receive as gifts View or change the status of your recent orders or update your account details Need help? Your questions answered here
    Amazon.co.uk
    Search our Shops       

    Star Choice
    Lord It Up
    Order The Lord of the Rings: The Two Towers four-disc set and get at least 30% off DVDs in our Christmas shop.
    Our Price: £23.99

    Browse
  • Books
  • DVD
  • Electronics & Photo
  • Gifts
  • Kitchen & Home
  • Music
  • PC & Video Games
  • Software
  • Toys & Kids!
  • Travel
  • Video  

  • Used
  • Auctions
  • zShops

  • Alliance
  • Expedia.co.uk
  • Make Money

    Marketplace
    Find out how to make money at Amazon.co.uk

    Associates
    Join now and start earning money from your website.

    Advantage
    The easy way for independent publishers and authors to enhance their sales.

    Web Services
    Build websites, applications or tools using Amazon Web Services.

    See all services

    Explore
    Wish List
    Make it easy to find that perfect gift--create or find a Wish List.

    Gift Certificates
    Send an Amazon.co.uk gift certificate to friends and family or colleagues.

    Refer-a-Friend
    Spread the Amazon word and earn up to £60 in gift certificates.

    Currency Converter
    Display our prices in another currency.

    Amazon.co.uk Anywhere
    Browse and buy from your WAP mobile phone.

    Top-5-Questions
    1. How do I order?
    2. Our Security Guarantee
    3. How much will postage and packing cost?
    4. Using a gift certificate
    5. Making changes to my order

     

    Hello! Already a customer? Sign in to get Instant Recommendations.



    First-time visitors--find out how to order and visit our Help Desk for the answers to your questions.

    DVD Delight
    Avoid the queues and festive mayhem--buy the well-specified, great-looking Toshiba SD330E multi-region DVD player. Find more low prices on 1000s of products and see our Christmas shop. Our Price: £79.99 Used & New from £79.99
    More in Electronics & Photo


    New & Future Releases
    Dude, Where's My Country?
    Amazon.co.uk Review
    Plenty of liberal scholars, entertainers and pundits have railed against the hoodwinking of the American people, but Michael Moore's Dude, Where's My Country? stands out for its thoroughly positive perspective. He says America has been tricked by Republican lawmakers and their wealthy corporate... Read more

    Our Price: £8.99 Used & New from £8.99 More New & Future Releases

    At Least 30% off DVDs
    Shop early this Christmas at Amazon.co.uk--get every feisty episode of the acclaimed Sex and the City, Series 5. Find more DVDs with at least 30% off in our Christmas shop. Our Price: £19.99 Used & New from £17.99
    More in DVD


    Your Books Store
    French Leave: Over 100 Irresistible Recipes
    Amazon.co.uk Review
    The life of a Michelin-starred chef is undeniably a stressful one, and no doubt many pause from time to time in the frenzy of the kitchen or the worry of the office to ask themselves if it's really all worth it. John Burton Race, who had clocked up two stars, had such a moment. He saw the business... Read more

    Our Price: £10.00 Used & New from £10.00
    In Used
    Sony MZ-N710 Blue Net MiniDisc Walkman
    Amazon.co.uk Review
    The Sony MZ-N710 Net MiniDisc Walkman offers great looks, a compact design, up to 85 hours battery life and the ability to store over five hours of music on one 80-minute MiniDisc.

    MiniDisc technology has come on leaps and bounds these past few years. As the units have become smaller, the battery... Read more

    Used Price: £110.00 (Our Price:£119.90)

    More In Used

     
    Leap into Learning

    Learning is fun with Finding Nemo, the interactive LeapPad book from LeapFrog.
    Our Price: £11.99
    Visit our Christmas shop
    Prepare for Christmas
    Gift Ideas: Best of 2003
    Gift Services
    Last-order Dates

    New at Amazon.co.uk
    Already a customer?
    Sign in to see what's New for You.

    Your Shopping Basket
    Your Shopping Basket You have 0 items in your Shopping Basket.
    New Releases
    Books How to Do Everything with Your Digital Camera (How to Do Everything)
    More Categories
    Books Computers & Internet
    Dvd DVD Children & Family
    Music Compilations
    Music Pop
    Books Business, Finance & Law
    More New Releases


    Amazon.co.uk
    Hot 100 Books
    Updated Hourly
    1. Schott's Food and Drink Miscellany ~ Ben Schott 50% off
    2. Dude, Where's My Country? ~ Michael Moore 50% off
    3. Olivia Joules and the Overactive Imagination ~ Helen Fielding 50% off
    arrow See full list

    Amazon.co.uk
    Hot 100 Music
    Updated Hourly
    1. Life for Rent ~ Dido £8.49
    2. Now That's What I Call Music Vol 56 ~ Various £12.99
    3. In Time: The Best of REM 1988 - 2003 ~ REM £8.49
    arrow See full list

    Where's My Stuff?
    • track your recent orders
    • view or change your orders in Your Account
    Delivery and Returns
    delivery rates and policies
    return an item (see our Returns Policy)
    Need Help?
    • forgot your password? Click here
    redeem or buy a gift certificate
    • Still have questions? Visit our Help Pages
    Search our shops    for     
    Make £££ from your purchases
    Learn more about selling at Amazon.co.uk today.
    Text Only Top of Page


    International Sites:  United States  | Germany  |  France  |  Japan   |  Canada

    Join Associates  |   Join Our Staff  |   About Amazon.co.uk  |   Help pages      

    Our Privacy NoticeUpdated Conditions of Use & Sale
    © 1996-2003, Amazon.com, Inc. and its affiliates

    ~~~ TITLE ~~~ Amazon.co.uk: Welcome ~~~ PROPERTIES ~~~ title=Amazon.co.uk:\nWelcome meta.description=Find, shop for and buy welcome at Amazon.co.uk meta.keywords=Amazon.co.uk, Welcome body.bgcolor=#FFFFFF body.link=#003399 body.alink=#FF9933 body.vlink=#996633 body.text=#000000 body.onload=popWinC() ~~~ HEAD ~~~ ~~~ BODY ~~~ International How to order Sell Your Stuff Harry Potter Shop Disney View the contents of your Shopping Basket Create or view a list of products you'd love to receive as gifts View or change the status of your recent orders or update your account details Need help? Your questions answered here
    Amazon.co.uk
    Search our Shops       

    Star Choice
    Lord It Up
    Order The Lord of the Rings: The Two Towers four-disc set and get at least 30% off DVDs in our Christmas shop.
    Our Price: £23.99

    Browse
  • Books
  • DVD
  • Electronics & Photo
  • Gifts
  • Kitchen & Home
  • Music
  • PC & Video Games
  • Software
  • Toys & Kids!
  • Travel
  • Video  

  • Used
  • Auctions
  • zShops

  • Alliance
  • Expedia.co.uk
  • Make Money

    Marketplace
    Find out how to make money at Amazon.co.uk

    Associates
    Join now and start earning money from your website.

    Advantage
    The easy way for independent publishers and authors to enhance their sales.

    Web Services
    Build websites, applications or tools using Amazon Web Services.

    See all services

    Explore
    Wish List
    Make it easy to find that perfect gift--create or find a Wish List.

    Gift Certificates
    Send an Amazon.co.uk gift certificate to friends and family or colleagues.

    Refer-a-Friend
    Spread the Amazon word and earn up to £60 in gift certificates.

    Currency Converter
    Display our prices in another currency.

    Amazon.co.uk Anywhere
    Browse and buy from your WAP mobile phone.

    Top-5-Questions
    1. How do I order?
    2. Our Security Guarantee
    3. How much will postage and packing cost?
    4. Using a gift certificate
    5. Making changes to my order

     

    Hello! Already a customer? Sign in to get Instant Recommendations.



    First-time visitors--find out how to order and visit our Help Desk for the answers to your questions.

    DVD Delight
    Avoid the queues and festive mayhem--buy the well-specified, great-looking Toshiba SD330E multi-region DVD player. Find more low prices on 1000s of products and see our Christmas shop. Our Price: £79.99 Used & New from £79.99
    More in Electronics & Photo


    New & Future Releases
    Dude, Where's My Country?
    Amazon.co.uk Review
    Plenty of liberal scholars, entertainers and pundits have railed against the hoodwinking of the American people, but Michael Moore's Dude, Where's My Country? stands out for its thoroughly positive perspective. He says America has been tricked by Republican lawmakers and their wealthy corporate... Read more

    Our Price: £8.99 Used & New from £8.99 More New & Future Releases

    At Least 30% off DVDs
    Shop early this Christmas at Amazon.co.uk--get every feisty episode of the acclaimed Sex and the City, Series 5. Find more DVDs with at least 30% off in our Christmas shop. Our Price: £19.99 Used & New from £17.99
    More in DVD


    Your Books Store
    French Leave: Over 100 Irresistible Recipes
    Amazon.co.uk Review
    The life of a Michelin-starred chef is undeniably a stressful one, and no doubt many pause from time to time in the frenzy of the kitchen or the worry of the office to ask themselves if it's really all worth it. John Burton Race, who had clocked up two stars, had such a moment. He saw the business... Read more

    Our Price: £10.00 Used & New from £10.00
    In Used
    Sony MZ-N710 Blue Net MiniDisc Walkman
    Amazon.co.uk Review
    The Sony MZ-N710 Net MiniDisc Walkman offers great looks, a compact design, up to 85 hours battery life and the ability to store over five hours of music on one 80-minute MiniDisc.

    MiniDisc technology has come on leaps and bounds these past few years. As the units have become smaller, the battery... Read more

    Used Price: £110.00 (Our Price:£119.90)

    More In Used

     
    Leap into Learning

    Learning is fun with Finding Nemo, the interactive LeapPad book from LeapFrog.
    Our Price: £11.99
    Visit our Christmas shop
    Prepare for Christmas
    Gift Ideas: Best of 2003
    Gift Services
    Last-order Dates

    New at Amazon.co.uk
    Already a customer?
    Sign in to see what's New for You.

    Your Shopping Basket
    Your Shopping Basket You have 0 items in your Shopping Basket.
    New Releases
    Books How to Do Everything with Your Digital Camera (How to Do Everything)
    More Categories
    Books Computers & Internet
    Dvd DVD Children & Family
    Music Compilations
    Music Pop
    Books Business, Finance & Law
    More New Releases


    Amazon.co.uk
    Hot 100 Books
    Updated Hourly
    1. Schott's Food and Drink Miscellany ~ Ben Schott 50% off
    2. Dude, Where's My Country? ~ Michael Moore 50% off
    3. Olivia Joules and the Overactive Imagination ~ Helen Fielding 50% off
    arrow See full list

    Amazon.co.uk
    Hot 100 Music
    Updated Hourly
    1. Life for Rent ~ Dido £8.49
    2. Now That's What I Call Music Vol 56 ~ Various £12.99
    3. In Time: The Best of REM 1988 - 2003 ~ REM £8.49
    arrow See full list

    Where's My Stuff?
    • track your recent orders
    • view or change your orders in Your Account
    Delivery and Returns
    delivery rates and policies
    return an item (see our Returns Policy)
    Need Help?
    • forgot your password? Click here
    redeem or buy a gift certificate
    • Still have questions? Visit our Help Pages
    Search our shops    for     
    Make £££ from your purchases
    Learn more about selling at Amazon.co.uk today.
    Text Only Top of Page


    International Sites:  United States  | Germany  |  France  |  Japan   |  Canada

    Join Associates  |   Join Our Staff  |   About Amazon.co.uk  |   Help pages      

    Our Privacy NoticeUpdated Conditions of Use & Sale
    © 1996-2003, Amazon.com, Inc. and its affiliates

    sitemesh-2.4.1+dfsg.orig/src/parser-tests/test16.txt0000644000175000017500000000065010057642572022276 0ustar twernertwerner~~~ INPUT ~~~

    This is a pretty simple page.

    Bye.

    ~~~ TITLE ~~~ ~~~ PROPERTIES ~~~ title= meta.blah=cheese ~~~ HEAD ~~~ ~~~ BODY ~~~

    This is a pretty simple page.

    Bye.

    sitemesh-2.4.1+dfsg.orig/src/java/0000755000175000017500000000000011157130032016654 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/0000755000175000017500000000000011157130032017432 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/0000755000175000017500000000000011157130040022201 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/0000755000175000017500000000000011157130042024024 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/Decorator.java0000644000175000017500000000026110277153004026615 0ustar twernertwernerpackage com.opensymphony.sitemesh; /** * @author Joe Walnes * @since SiteMesh 3 */ public interface Decorator { void render(Content content, SiteMeshContext context); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/ContentProcessor.java0000644000175000017500000000047710277153004030216 0ustar twernertwernerpackage com.opensymphony.sitemesh; import java.io.IOException; /** * @author Joe Walnes * @since SiteMesh 3 */ public interface ContentProcessor { boolean handles(SiteMeshContext context); boolean handles(String contentType); Content build(char[] data, SiteMeshContext context) throws IOException; } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/0000755000175000017500000000000011157130042026665 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/package.html0000644000175000017500000000013710277153002031152 0ustar twernertwernerCompatability classes to enable easy migration of SiteMesh 1 and 2 applications to SiteMesh 3. sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/HTMLPage2Content.java0000644000175000017500000000226610277153002032517 0ustar twernertwernerpackage com.opensymphony.sitemesh.compatability; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.sitemesh.Content; import java.io.IOException; import java.io.Writer; /** * Adapts a SiteMesh 2 {@link HTMLPage} to a SiteMesh 3 {@link Content}. * * @author Joe Walnes * @since SiteMesh 3 */ public class HTMLPage2Content implements Content { private final HTMLPage page; public HTMLPage2Content(HTMLPage page) { this.page = page; } public void writeOriginal(Writer out) throws IOException { page.writePage(out); } public int originalLength() { return page.getContentLength(); } public void writeBody(Writer out) throws IOException { page.writeBody(out); } public void writeHead(Writer out) throws IOException { page.writeHead(out); } public String getTitle() { return page.getTitle(); } public String getProperty(String name) { return page.getProperty(name); } public String[] getPropertyKeys() { return page.getPropertyKeys(); } public void addProperty(String name, String value) { page.addProperty(name, value); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/PageParser2ContentProcessor.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/PageParser2ContentProcesso0000644000175000017500000000375310277153002034007 0ustar twernertwernerpackage com.opensymphony.sitemesh.compatability; import com.opensymphony.module.sitemesh.Factory; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.filter.HttpContentType; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.SiteMeshContext; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import com.opensymphony.sitemesh.ContentProcessor; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * Adapts a SiteMesh 2 {@link PageParser} to a SiteMesh 3 {@link ContentProcessor}. * * @author Joe Walnes * @since SiteMesh 3 */ public class PageParser2ContentProcessor implements ContentProcessor { private final Factory factory; public PageParser2ContentProcessor(Factory factory) { this.factory = factory; } public boolean handles(SiteMeshContext context) { SiteMeshWebAppContext webAppContext = (SiteMeshWebAppContext) context; return !factory.isPathExcluded(extractRequestPath(webAppContext.getRequest())); } private String extractRequestPath(HttpServletRequest request) { String servletPath = request.getServletPath(); String pathInfo = request.getPathInfo(); String query = request.getQueryString(); return (servletPath == null ? "" : servletPath) + (pathInfo == null ? "" : pathInfo) + (query == null ? "" : ("?" + query)); } public boolean handles(String contentType) { return factory.shouldParsePage(contentType); } public Content build(char[] data, SiteMeshContext context) throws IOException { HttpContentType httpContentType = new HttpContentType(context.getContentType()); PageParser pageParser = factory.getPageParser(httpContentType.getType()); Page page = pageParser.parse(data); return new HTMLPage2Content((HTMLPage) page); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/Content2HTMLPage.java0000644000175000017500000001032411157157170032521 0ustar twernertwernerpackage com.opensymphony.sitemesh.compatability; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.sitemesh.Content; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Map; import java.util.HashMap; /** * Adapts a SiteMesh 3 {@link Content} to a SiteMesh 2 {@link HTMLPage}. * * @author Joe Walnes * @since SiteMesh 3 */ public class Content2HTMLPage implements HTMLPage { private final Content content; private HttpServletRequest request; public Content2HTMLPage(Content content, HttpServletRequest request) { this.content = content; this.request = request; } public void writePage(Writer out) throws IOException { content.writeOriginal(out); } public String getPage() { try { StringWriter writer = new StringWriter(); writePage(writer); return writer.toString(); } catch (IOException e) { throw new IllegalStateException("Could not get page " + e.getMessage()); } } public void writeBody(Writer out) throws IOException { content.writeBody(out); } public String getBody() { try { StringWriter writer = new StringWriter(); writeBody(writer); return writer.toString(); } catch (IOException e) { throw new IllegalStateException("Could not get body " + e.getMessage()); } } public void writeHead(Writer out) throws IOException { content.writeHead(out); } public String getHead() { try { StringWriter writer = new StringWriter(); writeHead(writer); return writer.toString(); } catch (IOException e) { throw new IllegalStateException("Could not get head " + e.getMessage()); } } public String getTitle() { return content.getTitle(); } public int getContentLength() { return content.originalLength(); } public String getProperty(String name) { return content.getProperty(name); } public int getIntProperty(String name) { try { return Integer.parseInt(noNull(getProperty(name))); } catch (NumberFormatException e) { return 0; } } public long getLongProperty(String name) { try { return Long.parseLong(noNull(getProperty(name))); } catch (NumberFormatException e) { return 0; } } private String noNull(String property) { return property == null ? "" : property; } public boolean getBooleanProperty(String name) { String property = getProperty(name); if (property == null || property.trim().length() == 0) return false; switch (property.charAt(0)) { case '1': case 't': case 'T': case 'y': case 'Y': return true; default: return false; } } public boolean isPropertySet(String name) { return getProperty(name) != null; } public String[] getPropertyKeys() { return content.getPropertyKeys(); } public Map getProperties() { Map result = new HashMap(); String[] keys = content.getPropertyKeys(); for (int i = 0; i < keys.length; i++) { result.put(keys[i], content.getProperty(keys[i])); } return result; } public boolean isFrameSet() { return isPropertySet("frameset") && getProperty("frameset").equalsIgnoreCase("true"); } public void setFrameSet(boolean frameset) { addProperty("frameset", frameset ? "true" : "false"); } /** * @see com.opensymphony.module.sitemesh.Page#getRequest() */ public HttpServletRequest getRequest() { return request; } /** * Create snapshot of Request. * * @see com.opensymphony.module.sitemesh.Page#getRequest() */ public void setRequest(HttpServletRequest request) { this.request = request; } public void addProperty(String name, String value) { content.addProperty(name, value); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/DecoratorMapper2DecoratorSelector.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/DecoratorMapper2DecoratorS0000644000175000017500000000266411157135340033765 0ustar twernertwernerpackage com.opensymphony.sitemesh.compatability; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.Decorator; import com.opensymphony.sitemesh.DecoratorSelector; import com.opensymphony.sitemesh.SiteMeshContext; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import com.opensymphony.sitemesh.webapp.decorator.NoDecorator; import javax.servlet.http.HttpServletRequest; /** * Adapts a SiteMesh 2 {@link DecoratorMapper} to a SiteMesh 2 {@link DecoratorSelector}. * * @author Joe Walnes * @since SiteMesh 3 */ public class DecoratorMapper2DecoratorSelector implements DecoratorSelector { private final DecoratorMapper decoratorMapper; public DecoratorMapper2DecoratorSelector(DecoratorMapper decoratorMapper) { this.decoratorMapper = decoratorMapper; } public Decorator selectDecorator(Content content, SiteMeshContext context) { SiteMeshWebAppContext webAppContext = (SiteMeshWebAppContext) context; HttpServletRequest request = webAppContext.getRequest(); com.opensymphony.module.sitemesh.Decorator decorator = decoratorMapper.getDecorator(request, new Content2HTMLPage(content, request)); if (decorator == null || decorator.getPage() == null) { return new NoDecorator(); } else { return new OldDecorator2NewDecorator(decorator); } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/OldDecorator2NewDecorator.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/compatability/OldDecorator2NewDecorator.0000644000175000017500000000373211157135340033661 0ustar twernertwernerpackage com.opensymphony.sitemesh.compatability; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import com.opensymphony.sitemesh.webapp.decorator.BaseWebAppDecorator; import com.opensymphony.module.sitemesh.RequestConstants; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Adapts a SiteMesh 2 {@link com.opensymphony.module.sitemesh.Decorator} to a * SiteMesh 3 {@link com.opensymphony.sitemesh.Decorator}. * * @author Joe Walnes * @since SiteMesh 3 */ public class OldDecorator2NewDecorator extends BaseWebAppDecorator implements RequestConstants { private final com.opensymphony.module.sitemesh.Decorator oldDecorator; public OldDecorator2NewDecorator(com.opensymphony.module.sitemesh.Decorator oldDecorator) { this.oldDecorator = oldDecorator; } protected void render(Content content, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, SiteMeshWebAppContext webAppContext) throws IOException, ServletException { request.setAttribute(PAGE, new Content2HTMLPage(content, request)); // see if the URI path (webapp) is set if (oldDecorator.getURIPath() != null) { // in a security conscious environment, the servlet container // may return null for a given URL if (servletContext.getContext(oldDecorator.getURIPath()) != null) { servletContext = servletContext.getContext(oldDecorator.getURIPath()); } } // get the dispatcher for the decorator RequestDispatcher dispatcher = servletContext.getRequestDispatcher(oldDecorator.getPage()); dispatcher.include(request, response); request.removeAttribute(PAGE); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/0000755000175000017500000000000011157130042025302 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/package.html0000644000175000017500000000010310276712106027565 0ustar twernertwerner

    Provides integration of SiteMesh with Java web-applications.

    sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/ContentBufferingResponse.java0000644000175000017500000000435510277153002033140 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp; import com.opensymphony.module.sitemesh.filter.PageResponseWrapper; import com.opensymphony.module.sitemesh.PageParserSelector; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.sitemesh.ContentProcessor; import com.opensymphony.sitemesh.Content; import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author Joe Walnes * @since SiteMesh 3 */ public class ContentBufferingResponse extends HttpServletResponseWrapper { // TODO: Temporary SM3 migration implementation! Wraps SM2 PageResponseWrapper. This class is an evil stopgap. // Eventually PageResponseWrapper will go away and the functionality will be rolled into this class. private final PageResponseWrapper pageResponseWrapper; private final ContentProcessor contentProcessor; private final SiteMeshWebAppContext webAppContext; public ContentBufferingResponse(HttpServletResponse response, final ContentProcessor contentProcessor, final SiteMeshWebAppContext webAppContext) { super(new PageResponseWrapper(response, new PageParserSelector() { public boolean shouldParsePage(String contentType) { return contentProcessor.handles(contentType); } public PageParser getPageParser(String contentType) { // Migration: Not actually needed by PageResponseWrapper, so long as getPage() isn't called. return null; } }){ public void setContentType(String contentType) { webAppContext.setContentType(contentType); super.setContentType(contentType); } }); this.contentProcessor = contentProcessor; this.webAppContext = webAppContext; pageResponseWrapper = (PageResponseWrapper) getResponse(); } public boolean isUsingStream() { return pageResponseWrapper.isUsingStream(); } public Content getContent() throws IOException { char[] data = pageResponseWrapper.getContents(); if (data != null) { return contentProcessor.build(data, webAppContext); } else { return null; } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/0000755000175000017500000000000011157130042027264 5ustar twernertwerner././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/DispatchedDecorator.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/DispatchedDecorator.jav0000644000175000017500000000422210276712102033705 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp.decorator; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Decorator that dispatches to another path in the Servlet Container (such as a JSP or path mapped to a Servlet). *

    * The Content and SiteMeshContext objects are passed to the decorator using the HttpServletRequest attributes * {@link #CONTENT_KEY} and {@link #CONTEXT_KEY}. *

    * To dispatch to a decorator in another web-app on the same server, use {@link ExternalDispatchedDecorator}. * * @author Joe Walnes * @since SiteMesh 3.0 */ public class DispatchedDecorator extends BaseWebAppDecorator { public static final String CONTENT_KEY = "com.opensymphony.sitemesh.CONTENT"; public static final String CONTEXT_KEY = "com.opensymphony.sitemesh.CONTEXT"; private final String path; public DispatchedDecorator(String path) { this.path = path; } protected void render(Content content, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, SiteMeshWebAppContext webAppContext) throws IOException, ServletException { Object oldContent = request.getAttribute(CONTENT_KEY); Object oldWebAppContext = request.getAttribute(CONTEXT_KEY); request.setAttribute(CONTENT_KEY, content); request.setAttribute(CONTEXT_KEY, webAppContext); try { RequestDispatcher dispatcher = servletContext.getRequestDispatcher(path); dispatcher.include(request, response); } finally { request.setAttribute(CONTENT_KEY, oldContent); request.setAttribute(CONTEXT_KEY, oldWebAppContext); } } protected ServletContext locateWebApp(ServletContext context) { // Overriden by ExternalDispatchedDecorator, which finds the context of another web-app. return context; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/BaseWebAppDecorator.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/BaseWebAppDecorator.jav0000644000175000017500000000325111157157260033616 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp.decorator; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.Decorator; import com.opensymphony.sitemesh.SiteMeshContext; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Convenient base class for all Java web-app based decorators that make use of the Servlet API. * * @author Joe Walnes * @since SiteMesh 3.0 */ public abstract class BaseWebAppDecorator implements Decorator { /** * More convenient version of {@link #render(com.opensymphony.sitemesh.Content, com.opensymphony.sitemesh.SiteMeshContext)} * suited for Servlet API calls. */ protected abstract void render(Content content, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, SiteMeshWebAppContext webAppContext) throws IOException, ServletException; public void render(Content content, SiteMeshContext context) { SiteMeshWebAppContext webAppContext = (SiteMeshWebAppContext) context; try { render(content, webAppContext.getRequest(), webAppContext.getResponse(), webAppContext.getServletContext(), webAppContext); } catch (IOException e) { // TODO: Decent exception handling throw new RuntimeException(e.toString()); } catch (ServletException e) { // TODO: Decent exception handling throw new RuntimeException(e.toString()); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/NoDecorator.java0000644000175000017500000000253110276712104032355 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp.decorator; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * If no decorator is to be applied to a page, this will ensure the original content gets written out. * * @author Joe Walnes * @since SiteMesh 3.0 */ public class NoDecorator extends BaseWebAppDecorator { protected void render(Content content, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, SiteMeshWebAppContext webAppContext) throws IOException, ServletException { response.setContentLength(content.originalLength()); if (webAppContext.isUsingStream()) { PrintWriter writer = new PrintWriter(response.getOutputStream()); content.writeOriginal(writer); writer.flush(); //flush writer to underlying outputStream response.getOutputStream().flush(); } else { PrintWriter writer = response.getWriter(); content.writeOriginal(writer); response.getWriter().flush(); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/ExternalDispatchedDecorator.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/decorator/ExternalDispatchedDecor0000644000175000017500000000234110276712102033743 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp.decorator; import javax.servlet.ServletContext; /** * Decorator that dispatches to another path in A DIFFERENT WEB-APP in the same Servlet Container (such as a JSP or path mapped to a Servlet). *

    * The Content and SiteMeshContext objects are passed to the decorator using the HttpServletRequest attributes * {@link #CONTENT_KEY} and {@link #CONTEXT_KEY}. *

    * To dispatch to a decorator in the same web-app, use {@link DispatchedDecorator}. * * @author Joe Walnes * @since SiteMesh 3.0 */ public class ExternalDispatchedDecorator extends DispatchedDecorator { private final String webApp; public ExternalDispatchedDecorator(String path, String webApp) { super(path); this.webApp = webApp; } protected ServletContext locateWebApp(ServletContext context) { ServletContext externalContext = context.getContext(webApp); if (externalContext != null) { return externalContext; } else { // in a security conscious environment, the servlet container // may return null for a given URL throw new SecurityException("Cannot obtain ServletContext for web-app : " + webApp); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/SiteMeshWebAppContext.java0000644000175000017500000000304110277153002032333 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp; import com.opensymphony.sitemesh.SiteMeshContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletContext; /** * @author Joe Walnes * @since SiteMesh 3 */ public class SiteMeshWebAppContext implements SiteMeshContext { private static final String IS_USING_STRING_KEY = "com.opensymphony.sitemesh.USINGSTREAM"; private final HttpServletRequest request; private final HttpServletResponse response; private final ServletContext servletContext; private String contentType; public SiteMeshWebAppContext(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) { this.request = request; this.response = response; this.servletContext = servletContext; } public HttpServletRequest getRequest() { return request; } public HttpServletResponse getResponse() { return response; } public ServletContext getServletContext() { return servletContext; } public boolean isUsingStream() { return request.getAttribute(IS_USING_STRING_KEY) == Boolean.TRUE; } public void setUsingStream(boolean isUsingStream) { request.setAttribute(IS_USING_STRING_KEY, isUsingStream ? Boolean.TRUE : Boolean.FALSE); // JDK 1.3 friendly } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/ContainerTweaks.java0000644000175000017500000000155110550355756031271 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp; import com.opensymphony.module.sitemesh.util.Container; /** * Provides details of which tweaks should be used in SiteMesh - necessary because containers behave subtly different. * * @author Joe Walnes * @since SiteMesh 3 */ public class ContainerTweaks { // TODO: Externalize these into a config file (optional of course!), allowing users to change them at runtime if needed. private final int container = Container.get(); public boolean shouldAutoCreateSession() { return false; // return container == Container.TOMCAT; - this is removed due to SIM-151. } public boolean shouldLogUnhandledExceptions() { return container == Container.TOMCAT; } public boolean shouldIgnoreIllegalStateExceptionOnErrorPage() { return container == Container.WEBLOGIC; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/webapp/SiteMeshFilter.java0000644000175000017500000001403710550334430031044 0ustar twernertwernerpackage com.opensymphony.sitemesh.webapp; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Factory; import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.Decorator; import com.opensymphony.sitemesh.DecoratorSelector; import com.opensymphony.sitemesh.ContentProcessor; import com.opensymphony.sitemesh.compatability.DecoratorMapper2DecoratorSelector; import com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Core Filter for integrating SiteMesh into a Java web application. * * @author Joe Walnes * @author Scott Farquhar * @since SiteMesh 3 */ public class SiteMeshFilter implements Filter { private FilterConfig filterConfig; private ContainerTweaks containerTweaks; private static final String ALREADY_APPLIED_KEY = "com.opensymphony.sitemesh.APPLIED_ONCE"; public void init(FilterConfig filterConfig) { this.filterConfig = filterConfig; containerTweaks = new ContainerTweaks(); } public void destroy() { filterConfig = null; containerTweaks = null; } /** * Main method of the Filter. *

    Checks if the Filter has been applied this request. If not, parses the page * and applies {@link com.opensymphony.module.sitemesh.Decorator} (if found). */ public void doFilter(ServletRequest rq, ServletResponse rs, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) rq; HttpServletResponse response = (HttpServletResponse) rs; ServletContext servletContext = filterConfig.getServletContext(); SiteMeshWebAppContext webAppContext = new SiteMeshWebAppContext(request, response, servletContext); ContentProcessor contentProcessor = initContentProcessor(webAppContext); DecoratorSelector decoratorSelector = initDecoratorSelector(webAppContext); if (filterAlreadyAppliedForRequest(request)) { // Prior to Servlet 2.4 spec, it was unspecified whether the filter should be called again upon an include(). chain.doFilter(request, response); return; } if (!contentProcessor.handles(webAppContext)) { // Optimization: If the content doesn't need to be processed, bypass SiteMesh. chain.doFilter(request, response); return; } if (containerTweaks.shouldAutoCreateSession()) { // Some containers (such as Tomcat 4) will not allow sessions to be created in the decorator. // (i.e after the response has been committed). request.getSession(true); } try { Content content = obtainContent(contentProcessor, webAppContext, request, response, chain); if (content == null) { return; } Decorator decorator = decoratorSelector.selectDecorator(content, webAppContext); decorator.render(content, webAppContext); } catch (IllegalStateException e) { // Some containers (such as WebLogic) throw an IllegalStateException when an error page is served. // It may be ok to ignore this. However, for safety it is propegated if possible. if (!containerTweaks.shouldIgnoreIllegalStateExceptionOnErrorPage()) { throw e; } } catch (RuntimeException e) { if (containerTweaks.shouldLogUnhandledExceptions()) { // Some containers (such as Tomcat 4) swallow RuntimeExceptions in filters. servletContext.log("Unhandled exception occurred whilst decorating page", e); } throw e; } catch (ServletException e) { request.setAttribute(ALREADY_APPLIED_KEY, null); throw e; } } protected ContentProcessor initContentProcessor(SiteMeshWebAppContext webAppContext) { // TODO: Remove heavy coupling on horrible SM2 Factory Factory factory = Factory.getInstance(new Config(filterConfig)); factory.refresh(); return new PageParser2ContentProcessor(factory); } protected DecoratorSelector initDecoratorSelector(SiteMeshWebAppContext webAppContext) { // TODO: Remove heavy coupling on horrible SM2 Factory Factory factory = Factory.getInstance(new Config(filterConfig)); factory.refresh(); return new DecoratorMapper2DecoratorSelector(factory.getDecoratorMapper()); } /** * Continue in filter-chain, writing all content to buffer and parsing * into returned {@link com.opensymphony.module.sitemesh.Page} object. If * {@link com.opensymphony.module.sitemesh.Page} is not parseable, null is returned. */ private Content obtainContent(ContentProcessor contentProcessor, SiteMeshWebAppContext webAppContext, HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { ContentBufferingResponse contentBufferingResponse = new ContentBufferingResponse(response, contentProcessor, webAppContext); chain.doFilter(request, contentBufferingResponse); // TODO: check if another servlet or filter put a page object in the request // Content result = request.getAttribute(PAGE); // if (result == null) { // // parse the page // result = pageResponse.getPage(); // } webAppContext.setUsingStream(contentBufferingResponse.isUsingStream()); return contentBufferingResponse.getContent(); } private boolean filterAlreadyAppliedForRequest(HttpServletRequest request) { if (request.getAttribute(ALREADY_APPLIED_KEY) == Boolean.TRUE) { return true; } else { request.setAttribute(ALREADY_APPLIED_KEY, Boolean.TRUE); return false; } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/SiteMeshContext.java0000644000175000017500000000030610277153004027761 0ustar twernertwernerpackage com.opensymphony.sitemesh; /** * @author Joe Walnes * @since SiteMesh 3 */ public interface SiteMeshContext { void setContentType(String contentType); String getContentType(); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/content/0000755000175000017500000000000011157130042025476 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/Content.java0000644000175000017500000000226110277153002026305 0ustar twernertwernerpackage com.opensymphony.sitemesh; import java.io.IOException; import java.io.Writer; /** * @author Joe Walnes * @since SiteMesh 3 */ public interface Content { /** * Write out the original unprocessed content. */ void writeOriginal(Writer writer) throws IOException; /** * Length of the original unprocessed content. */ int originalLength(); /** * Write the contents of the <body> tag. */ void writeBody(Writer out) throws IOException; /** * Write the contents of the <head> tag. */ void writeHead(Writer out) throws IOException; /** * Get the Title of the document */ String getTitle(); /** * Get a property embedded into the Page as a String. * * @param name Name of property * @return Property value */ String getProperty(String name); /** * Get all available property keys for the Page. * * @return Property keys */ String[] getPropertyKeys(); /** * Manually add a property to page. */ void addProperty(String name, String value); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/sitemesh/DecoratorSelector.java0000644000175000017500000000050710277153004030321 0ustar twernertwernerpackage com.opensymphony.sitemesh; /** * Selects an appropriate Decorator for the Content. *

    * Note: Since SiteMesh 3, this replaces the DecoratorMapper. * * @author Joe Walnes * @since SiteMesh 3 */ public interface DecoratorSelector { Decorator selectDecorator(Content content, SiteMeshContext context); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/0000755000175000017500000000000011157130032023467 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/0000755000175000017500000000000011157160460025320 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/Decorator.java0000644000175000017500000000315407751471036030121 0ustar twernertwerner/* * Title: Decorator * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import java.util.Iterator; /** * Representation of a Decorator. * *

    A Decorator is infact a Servlet/JSP, and this is a wrapper to reference it. * An implementation is returned by the {@link com.opensymphony.module.sitemesh.DecoratorMapper}.

    * * @author Joe Walnes * @version $Revision: 1.1 $ */ public interface Decorator { /** * URI of the Servlet/JSP to dispatch the request to (relative to the * web-app context). */ String getPage(); /** Name of the Decorator. For informational purposes only. */ String getName(); /** URI path of the Decorator. Enables support for decorators defined in seperate web-apps. */ String getURIPath(); /** Role the user has to be in to get this decorator applied. */ String getRole(); /** * Returns a String containing the value of the named initialization parameter, * or null if the parameter does not exist. * * @param paramName Key of parameter. * @return Value of the parameter or null if not found. */ String getInitParameter(String paramName); /** * Returns the names of the Decorator's initialization parameters as an Iterator * of String objects, or an empty Iterator if the Decorator has no initialization parameters. */ Iterator getInitParameterNames(); }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/PageParser.java0000644000175000017500000000177210060331354030215 0ustar twernertwerner/* * Title: PageParser * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import java.io.IOException; /** * The PageParser is responsible for parsing the page data into an appropriate * {@link com.opensymphony.module.sitemesh.Page} object. * *

    The implementation of this can be switched to parse different kind of data * (e.g. HTML, WML, FOP, images) or for performance enhancements. An * implementation is obtained through the {@link com.opensymphony.module.sitemesh.Factory} .

    * *

    A single PageParser is reused, therefore the parse() methods need to be thread-safe.

    * * @author Joe Walnes * @version $Revision: 1.2 $ */ public interface PageParser { /** * This builds a Page. */ Page parse(char[] data) throws IOException; } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/0000755000175000017500000000000011157130040026551 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/AbstractTag.java0000644000175000017500000000520110060331360031611 0ustar twernertwerner/* * Title: AbstractTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.RequestConstants; import com.opensymphony.module.sitemesh.util.OutputConverter; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.BodyTagSupport; import java.io.Writer; /** * Convenience implementation of Tag containing generice methods required * by all (or most) taglibs. * * @author Joe Walnes * @version $Revision: 1.4 $ */ public abstract class AbstractTag extends BodyTagSupport implements RequestConstants { protected PageContext pageContext; protected Tag parent; /** To be implemented by all empty tags. */ public abstract int doEndTag() throws JspException; /** Returns SKIP_BODY. */ public int doStartTag() { return SKIP_BODY; } public void release() { } public Tag getParent() { return parent; } public void setParent(Tag parent) { this.parent = parent; } public void setPageContext(PageContext pageContext) { this.pageContext = pageContext; } /** * Return the Page object from the PAGE scope. If this is found in REQUEST scope * instead, it will be moved into PAGE scope - to handle multi-level includes. */ protected Page getPage() { Page p = (Page)pageContext.getAttribute(PAGE, PageContext.PAGE_SCOPE); if (p == null) { p = (Page)pageContext.getAttribute(PAGE, PageContext.REQUEST_SCOPE); if (p == null) { pageContext.removeAttribute(PAGE, PageContext.PAGE_SCOPE); } else { pageContext.setAttribute(PAGE, p, PageContext.PAGE_SCOPE); } pageContext.removeAttribute(PAGE, PageContext.REQUEST_SCOPE); } return p; } /** Log exception generated by taglib. */ protected static void trace(Exception e) { e.printStackTrace(); } /** * Get the outputWriter. This method should be used in preference to * pageContext.getOut(), as some charset conversions may need * to happen in some servers. * @return the writer for use in the tag */ protected Writer getOut() { return OutputConverter.getWriter(pageContext.getOut()); } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/0000755000175000017500000000000011157130040030533 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/HeadTag.java0000644000175000017500000000204010266735736032716 0ustar twernertwerner/* * Title: HeadTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; import java.io.IOException; import javax.servlet.jsp.JspException; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.taglib.AbstractTag; /** * Write original HTMLPage head to out. * * @author Joe Walnes * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.HTMLPage#writeHead(java.io.Writer) */ public class HeadTag extends AbstractTag { public final int doEndTag() throws JspException { HTMLPage htmlPage = (HTMLPage)getPage(); try { htmlPage.writeHead(getOut()); } catch(IOException e) { throw new JspException("Error writing head element: " + e.toString(), e); } return EVAL_PAGE; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/UsePageTEI.java0000644000175000017500000000174007751471036033315 0ustar twernertwerner/* * Title: UsePageTEI * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; import javax.servlet.jsp.tagext.TagData; import javax.servlet.jsp.tagext.TagExtraInfo; import javax.servlet.jsp.tagext.VariableInfo; /** * TagExtraInfo implementation to expose Page object as variable. * * @author Joe Walnes * @version $Revision: 1.1 $ * * @see UsePageTag * @see UseHTMLPageTEI */ public class UsePageTEI extends TagExtraInfo { protected String getType() { return "com.opensymphony.module.sitemesh.Page"; } public VariableInfo[] getVariableInfo(TagData data) { String id = data.getAttributeString("id"); return new VariableInfo[] {new VariableInfo(id, getType(), true, VariableInfo.AT_END)}; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/UsePageTag.java0000644000175000017500000000224307751471036033406 0ustar twernertwerner/* * Title: UsePageTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; import com.opensymphony.module.sitemesh.taglib.AbstractTag; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; /** * Expose the Page as a bean to the page which can then be accessed * from scriptlets. * *

    Depending on the TEI used, the object will be * {@link com.opensymphony.module.sitemesh.Page} or * {@link com.opensymphony.module.sitemesh.HTMLPage}.

    * * @author Joe Walnes * @version $Revision: 1.1 $ * * @see UsePageTEI * @see UseHTMLPageTEI */ public class UsePageTag extends AbstractTag { private String id = null; /** Set name of variable the Page will be set as. */ public void setId(String id) { this.id = id; } public final int doEndTag() throws JspException { pageContext.setAttribute(id, getPage(), PageContext.PAGE_SCOPE); return EVAL_PAGE; } }././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/PropertyTag.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/PropertyTag.java0000644000175000017500000000506610276421210033670 0ustar twernertwerner/* * Title: PropertyTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.taglib.AbstractTag; import java.io.Writer; /** * Write property of Page to out. * * @author Joe Walnes * @version $Revision: 1.4 $ * * @see com.opensymphony.module.sitemesh.Page#getProperty(java.lang.String) */ public class PropertyTag extends AbstractTag { private String propertyName, defaultValue; private boolean writeEntireProperty = false; /** Key of property to write. */ public void setProperty(String propertyName) { this.propertyName = propertyName; } protected String getProperty() { return propertyName; } /** Value to write if no property matching key is found (optional). */ public void setDefault(String defaultValue) { this.defaultValue = defaultValue; } /** When begins with y, t or 1, the full attribute (name + value) is written. */ public final void setWriteEntireProperty(String writeEntireProperty) { if (writeEntireProperty == null || writeEntireProperty.trim().length() == 0) return; switch (writeEntireProperty.charAt(0)) { case '1': case 't': case 'T': case 'y': case 'Y': this.writeEntireProperty = true; break; default: this.writeEntireProperty = false; } } public int doEndTag() { try { Page page = getPage(); String propertyValue = page.getProperty(propertyName); if (propertyValue == null || propertyValue.trim().length() == 0) propertyValue = defaultValue; if (propertyValue != null) { Writer out = getOut(); if (writeEntireProperty) { out.write(" "); out.write(propertyName.substring(propertyName.lastIndexOf('.') + 1)); out.write("=\""); out.write(propertyValue); out.write("\""); } else { out.write(propertyValue); } } } catch (Exception e) { trace(e); } return EVAL_PAGE; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/BodyTag.java0000644000175000017500000000154110007334710032733 0ustar twernertwerner/* * Title: BodyTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; import com.opensymphony.module.sitemesh.taglib.AbstractTag; /** * Write original Page body to out. * * @author Joe Walnes * @author Scott Farquhar * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.HTMLPage#writeBody(java.io.Writer) */ public class BodyTag extends AbstractTag { public final int doEndTag() { try { getPage().writeBody(getOut()); } catch (Exception e) { trace(e); } return EVAL_PAGE; } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/UseHTMLPageTEI.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/UseHTMLPageTEI.j0000644000175000017500000000122107751471036033304 0ustar twernertwerner/* * Title: UseHTMLPageTEI * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; /** * TagExtraInfo implementation to expose HTMLPage object as variable. * * @author Joe Walnes * @version $Revision: 1.1 $ * * @see UsePageTag * @see UsePageTEI */ public class UseHTMLPageTEI extends UsePageTEI { protected String getType() { return "com.opensymphony.module.sitemesh.HTMLPage"; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/decorator/TitleTag.java0000644000175000017500000000220510007336604033121 0ustar twernertwerner/* * Title: TitleTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.decorator; import com.opensymphony.module.sitemesh.taglib.AbstractTag; /** * Write the Page <title> value to out. * * @author Joe Walnes * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.HTMLPage#getTitle() */ public class TitleTag extends AbstractTag { private String defaultTitle = null; /** Value to write if no title is found (optional). */ public void setDefault(String defaultTitle) { this.defaultTitle = defaultTitle; } public final int doEndTag() { try { String title = getPage().getTitle(); if (title == null || title.trim().length() == 0) title = defaultTitle; if (title != null) getOut().write(title); } catch (Exception e) { trace(e); } return EVAL_PAGE; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/page/0000755000175000017500000000000011157130040027465 5ustar twernertwerner././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/page/ApplyDecoratorTag.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/page/ApplyDecoratorTag.jav0000644000175000017500000002627210550422640033572 0ustar twernertwerner/* * Title: ApplyDecoratorTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.page; import com.opensymphony.module.sitemesh.*; import com.opensymphony.module.sitemesh.filter.PageRequestWrapper; import com.opensymphony.module.sitemesh.filter.PageResponseWrapper; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.net.URL; import java.net.URLConnection; import java.net.MalformedURLException; /** * This tag inserts an external resource as a panel into the current Page. * *

    The page attribute should point to the panel resource * which should expose an entire page (e.g. another JSP file producing * HTML). This attribute can be relative to the page it is being called * from or an absolute path from the context-root.

    * *

    OR

    * *

    If the page attribute is not specified, the body content is parsed * into the {@link com.opensymphony.module.sitemesh.Page} object and has * the {@link com.opensymphony.module.sitemesh.Decorator} applied.

    * *

    The (optional) decorator attribute is the name of the * {@link com.opensymphony.module.sitemesh.Decorator} * to apply to the included page. Note that the implementation of * {@link com.opensymphony.module.sitemesh.DecoratorMapper} can overide this.

    * * @author Joe Walnes * @version $Revision: 1.10 $ */ public class ApplyDecoratorTag extends BodyTagSupport implements RequestConstants { private String page = null; private String decorator = null; private String contentType = null; private String encoding = null; private Map params = new HashMap(6); private Config config = null; private DecoratorMapper decoratorMapper = null; private Factory factory; /** * Tag attribute: URI of page to include. * Can be relative to page being called from, or absolute * path from context-root of web-app. */ public void setPage(String page) { this.page = page; } /** * Add a parameter to the page. This has a package level * access modifier so ParamTag can also call it. */ void addParam(String name, String value) { params.put(name, value); } /** * Tag attribute: If set, this value will override the 'title' * property of the page. This is a convenience utility and is * identical to specifing a 'page:param name=title' tag. */ public void setTitle(String title) { addParam("title", title); } /** * Tag attribute: If set, this value will override the 'id' * property of the page. This is a convenience utility and is * identical to specifing a 'page:param name=id' tag. */ public void setId(String id) { addParam("id", id); } /** * Tag attribute: Name of Decorator to apply to Page. * This is passed to DecoratorMapper to retrieve appropriate * Decorator. DecoratorMapper may override if needed. * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public void setName(String decorator) { if (decorator != null) this.decorator = decorator; } /** @deprecated Use setName() instead. */ public void setDecorator(String decorator) { setName(decorator); } public void setContentType(String contentType) { this.contentType = contentType; } public void setEncoding(String encoding) { this.encoding = encoding; } public int doStartTag() { if (config == null) { // set context if not already set config = new Config(pageContext.getServletConfig()); factory = Factory.getInstance(config); decoratorMapper = factory.getDecoratorMapper(); } // return page == null ? EVAL_BODY_BUFFERED : SKIP_BODY; return EVAL_BODY_BUFFERED; } /** Ensure that external page contents are included in bodycontent. */ public int doAfterBody() throws JspException { return SKIP_BODY; } /** Standard taglib method: apply decorator to page. */ public int doEndTag() throws JspException { try { // if composite decorator, remember last page Page oldPage = (Page) pageContext.getRequest().getAttribute(PAGE); // parse bodycontent into Page object PageParser parser = getParserSelector().getPageParser(contentType != null ? contentType : "text/html"); Page pageObj; if (page == null) { // inline content if (bodyContent != null) { pageObj = parser.parse(bodyContent.getString().toCharArray()); } else { pageObj = parser.parse(new char[]{}); } } else if (page.startsWith("http://") || page.startsWith("https://")) { try { URL url = new URL(page); URLConnection urlConn = url.openConnection(); urlConn.setUseCaches(true); BufferedReader in = new BufferedReader( new InputStreamReader(urlConn.getInputStream())); StringBuffer sbuf = new StringBuffer(); char[] buf = new char[1000]; for (; ;) { int moved = in.read(buf); if (moved < 0) break; sbuf.append(buf, 0, moved); } in.close(); pageObj = parser.parse(sbuf.toString().toCharArray()); } catch (MalformedURLException e) { throw new JspException(e); } catch (IOException e) { throw new JspException(e); } } else { // external content String fullPath = page; if (fullPath.length() > 0 && fullPath.charAt(0) != '/') { HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); // find absolute path if relative supplied String thisPath = request.getServletPath(); // check if it did not return null (could occur when the servlet container // does not use a servlet to serve the requested resouce) if (thisPath == null) { String requestURI = request.getRequestURI(); if (request.getPathInfo() != null) { // strip the pathInfo from the requestURI thisPath = requestURI.substring(0, requestURI.indexOf(request.getPathInfo())); } else { thisPath = requestURI; } } fullPath = thisPath.substring(0, thisPath.lastIndexOf('/') + 1) + fullPath; int dotdot; while ((dotdot = fullPath.indexOf("..")) > -1) { int prevSlash = fullPath.lastIndexOf('/', dotdot - 2); fullPath = fullPath.substring(0, prevSlash) + fullPath.substring(dotdot + 2); } } // include page using filter response RequestDispatcher rd = pageContext.getServletContext().getRequestDispatcher(fullPath); PageRequestWrapper pageRequest = new PageRequestWrapper((HttpServletRequest) pageContext.getRequest()); PageResponseWrapper pageResponse = new PageResponseWrapper((HttpServletResponse) pageContext.getResponse(), factory); StringBuffer sb = new StringBuffer(contentType != null ? contentType : "text/html"); if (encoding != null) { sb.append(";charset=").append(encoding); } pageResponse.setContentType(sb.toString()); // if rd == null, then the panel was not found, but this isn't correct, so we need to spit out // something appropriate. What this is, well...I don't know yet. if (rd == null) { throw new ApplyDecoratorException("The specified resource in applyDecorator tag (" + fullPath + ") was not found."); } rd.include(pageRequest, pageResponse); pageObj = pageResponse.getPage(); } // If pageObj == null, then the panel source had some weird error in // it. Stop writing bugs like this. They're ugly and they make you smell funny. if (pageObj == null) { throw new ApplyDecoratorException(page + " did not create a valid page to decorate."); } // add extra params to Page Iterator paramKeys = params.keySet().iterator(); while (paramKeys.hasNext()) { String k = (String) paramKeys.next(); String v = (String) params.get(k); pageObj.addProperty(k, v); } // get decorator if (decorator == null) decorator = ""; pageObj.setRequest((HttpServletRequest) pageContext.getRequest()); pageContext.getRequest().setAttribute(DECORATOR, decorator); Decorator d = decoratorMapper.getDecorator(((HttpServletRequest) pageContext.getRequest()), pageObj); pageContext.getRequest().removeAttribute(DECORATOR); // apply decorator if (d != null && d.getPage() != null) { pageContext.getRequest().setAttribute(PAGE, pageObj); pageContext.include(d.getPage()); } else { throw new JspException("Cannot locate inline Decorator: " + decorator); } // clean up pageContext.getRequest().setAttribute(PAGE, oldPage); params.clear(); // params need to be cleared between invocations - SIM-191 } catch (IOException e) { throw new JspException(e); } catch (ServletException e) { throw new JspException(e); } catch (ApplyDecoratorException e) { try { pageContext.getOut().println(e.getMessage()); } catch (IOException ioe) { System.err.println("IOException thrown in applyDecorator tag: " + e.toString()); } } return EVAL_PAGE; } private PageParserSelector getParserSelector() { return Factory.getInstance(config); } class ApplyDecoratorException extends Exception { public ApplyDecoratorException(String s) { super(s); } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/taglib/page/ParamTag.java0000644000175000017500000000177110307200304032027 0ustar twernertwerner/* * Title: ParamTag * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.taglib.page; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.servlet.jsp.tagext.Tag; /** * Add a parameter to the inline Decorator, as if specified in the Page. * * @author Joe Walnes * @version $Revision: 1.2 $ */ public class ParamTag extends BodyTagSupport { private String name; public void setName(String name) { this.name = name; } public int doAfterBody() { Tag parent = findAncestorWithClass(this, ApplyDecoratorTag.class); if (parent instanceof ApplyDecoratorTag) { ApplyDecoratorTag t = (ApplyDecoratorTag)parent; t.addParam(name, getBodyContent().getString()); } return SKIP_BODY; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/Factory.java0000644000175000017500000001026210566417560027604 0ustar twernertwerner/* * Title: Factory * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import com.opensymphony.module.sitemesh.factory.FactoryException; import com.opensymphony.module.sitemesh.util.ClassLoaderUtil; import com.opensymphony.module.sitemesh.util.Container; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * Factory responsible for creating appropriate instances of implementations. * This is specific to a web context and is obtained through {@link #getInstance(com.opensymphony.module.sitemesh.Config)}. * *

    The actual Factory method used is determined by the enviroment entry sitemesh.factory. * If this doesn't exist, it defaults to {@link com.opensymphony.module.sitemesh.factory.DefaultFactory} .

    * * @author Joe Walnes * @version $Revision: 1.8 $ */ public abstract class Factory implements PageParserSelector { /** Web context lookup key */ private static final String SITEMESH_FACTORY = "sitemesh.factory"; /** * Entry-point for obtaining singleton instance of Factory. The default factory class * that will be instantiated can be overridden with the environment * entry sitemesh.factory. */ public static Factory getInstance(Config config) { Factory instance = (Factory)config.getServletContext().getAttribute(SITEMESH_FACTORY); if (instance == null) { String factoryClass = getEnvEntry("sitemesh.factory", "com.opensymphony.module.sitemesh.factory.DefaultFactory"); try { Class cls = ClassLoaderUtil.loadClass(factoryClass, config.getClass()); Constructor con = cls.getConstructor(new Class[] { Config.class }); instance = (Factory)con.newInstance(new Config[] { config }); config.getServletContext().setAttribute(SITEMESH_FACTORY, instance); } catch (InvocationTargetException e) { throw new FactoryException("Cannot construct Factory : " + factoryClass, e.getTargetException()); } catch (Exception e) { throw new FactoryException("Cannot construct Factory : " + factoryClass, e); } } instance.refresh(); return instance; } public abstract void refresh(); /** Return instance of DecoratorMapper. */ public abstract DecoratorMapper getDecoratorMapper(); /** * Create a PageParser suitable for the given content-type. * *

    For example, if the supplied parameter is text/html * a parser shall be returned that can parse HTML accordingly.

    Never returns null. * * @param contentType The MIME content-type of the data to be parsed * @return Appropriate PageParser for reading data * */ public abstract PageParser getPageParser(String contentType); /** Determine whether a Page of given content-type should be parsed or not. */ public abstract boolean shouldParsePage(String contentType); /** * Determine whether the given path should be excluded from decoration or not. */ public abstract boolean isPathExcluded(String path); /** Find String environment entry, or return default if not found. */ private static String getEnvEntry(String envEntry, String defaultValue) { String result = null; try { if (Container.get() != Container.JRUN) { // TODO: JRun really isn't happy with this InitialContext ctx = new InitialContext(); Object o = ctx.lookup("java:comp/env/" + envEntry); ctx.close(); result = (String)PortableRemoteObject.narrow(o, String.class); // rmi-iiop friendly. } } catch (Exception e) { } // failed - don't moan, just return default. return result == null || result.trim().length() == 0 ? defaultValue : result; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/0000755000175000017500000000000011157130040026264 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/CharArrayWriter.java0000644000175000017500000000754010272511404032212 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.util; import java.io.Writer; import java.io.IOException; /** * Unsynced version of the JDK's CharArrayWriter */ public class CharArrayWriter extends Writer { /** * The buffer where data is stored. */ protected char buf[]; /** * The number of chars in the buffer. */ protected int count; /** * Creates a new CharArrayWriter. */ public CharArrayWriter() { this(32); } /** * Creates a new CharArrayWriter with the specified initial size. * * @param initialSize an int specifying the initial buffer size. * @exception IllegalArgumentException if initialSize is negative */ public CharArrayWriter(int initialSize) { if (initialSize < 0) { throw new IllegalArgumentException("Negative initial size: " + initialSize); } buf = new char[initialSize]; } /** * Writes a character to the buffer. */ public void write(int c) { int newcount = count + 1; if (newcount > buf.length) { char newbuf[] = new char[Math.max(buf.length << 1, newcount)]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } buf[count] = (char)c; count = newcount; } /** * Writes characters to the buffer. * @param c the data to be written * @param off the start offset in the data * @param len the number of chars that are written */ public void write(char c[], int off, int len) { if ((off < 0) || (off > c.length) || (len < 0) || ((off + len) > c.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } int newcount = count + len; if (newcount > buf.length) { char newbuf[] = new char[Math.max(buf.length << 1, newcount)]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } System.arraycopy(c, off, buf, count, len); count = newcount; } /** * Write a portion of a string to the buffer. * @param str String to be written from * @param off Offset from which to start reading characters * @param len Number of characters to be written */ public void write(String str, int off, int len) { int newcount = count + len; if (newcount > buf.length) { char newbuf[] = new char[Math.max(buf.length << 1, newcount)]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } str.getChars(off, off + len, buf, count); count = newcount; } /** * Writes the contents of the buffer to another character stream. * * @param out the output stream to write to * @throws java.io.IOException If an I/O error occurs. */ public void writeTo(Writer out) throws IOException { out.write(buf, 0, count); } /** * Resets the buffer so that you can use it again without * throwing away the already allocated buffer. */ public void reset() { count = 0; } /** * Returns a copy of the input data. * * @return an array of chars copied from the input data. */ public char toCharArray()[] { char newbuf[] = new char[count]; System.arraycopy(buf, 0, newbuf, 0, count); return newbuf; } /** * Returns the current size of the buffer. * * @return an int representing the current size of the buffer. */ public int size() { return count; } /** * Converts input data to a string. * @return the string. */ public String toString() { return new String(buf, 0, count); } /** * Flush the stream. */ public void flush() { } /** * Close the stream. This method does not release the buffer, since its * contents might still be required. */ public void close() { } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/CharArrayReader.java0000644000175000017500000001103607757573360032162 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.util; import java.io.Reader; import java.io.IOException; /** * This class implements a character buffer that can be used as a * character-input stream. * * Modified from the JDK source in that it gets rid of the * ensureOpen() method, so we get unexpected behaviour if the * reader is closed. *

    * The second modification is that since this class is used * internally by FastPageParser in a single thread, we don't * need any locking or synchronization. Using this class * instead of the standard CharArrayReader improves * FastPageParser performance by 15-20%. * * @author Hani Suleiman */ public class CharArrayReader extends Reader { /** The character buffer. */ protected char buf[]; /** The current buffer position. */ protected int pos; /** The position of mark in buffer. */ protected int markedPos = 0; /** * The index of the end of this buffer. There is not valid * data at or beyond this index. */ protected int count; /** * Create an CharArrayReader from the specified array of chars. * * @param buf Input buffer (not copied) */ public CharArrayReader(char buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; } /** * Create an CharArrayReader from the specified array of chars. * * @param buf Input buffer (not copied) * @param offset Offset of the first char to read * @param length Number of chars to read */ public CharArrayReader(char buf[], int offset, int length) { if((offset < 0) || (offset > buf.length) || (length < 0) || ((offset + length) < 0)) { throw new IllegalArgumentException(); } this.buf = buf; this.pos = offset; this.count = Math.min(offset + length, buf.length); this.markedPos = offset; } /** * Read a single character. * * @throws IOException If an I/O error occurs */ public int read() throws IOException { if(pos >= count) return -1; else return buf[pos++]; } /** * Read characters into a portion of an array. * * @param b Destination buffer * @param off Offset at which to start storing characters * @param len Maximum number of characters to read * @return The actual number of characters read, or -1 if * the end of the stream has been reached * @throws IOException If an I/O error occurs */ public int read(char b[], int off, int len) throws IOException { if((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if(len == 0) { return 0; } if(pos >= count) { return -1; } if(pos + len > count) { len = count - pos; } if(len <= 0) { return 0; } System.arraycopy(buf, pos, b, off, len); pos += len; return len; } /** * Skip characters. * * @param n The number of characters to skip * @throws IOException If an I/O error occurs * @return The number of characters actually skipped */ public long skip(long n) throws IOException { if(pos + n > count) { n = count - pos; } if(n < 0) { return 0; } pos += n; return n; } /** * Tell whether this stream is ready to be read. Character-array readers * are always ready to be read. * * @throws IOException If an I/O error occurs */ public boolean ready() throws IOException { return (count - pos) > 0; } /** * Tell whether this stream supports the mark() operation, which it does. */ public boolean markSupported() { return true; } /** * Mark the present position in the stream. Subsequent calls to reset() * will reposition the stream to this point. * * @param readAheadLimit Limit on the number of characters that may be * read while still preserving the mark. Because * the stream's input comes from a character array, * there is no actual limit; hence this argument is * ignored. * @throws IOException If an I/O error occurs */ public void mark(int readAheadLimit) throws IOException { markedPos = pos; } /** * Reset the stream to the most recent mark, or to the beginning if it has * never been marked. * * @throws IOException If an I/O error occurs */ public void reset() throws IOException { pos = markedPos; } /** * Close the stream. */ public void close() { buf = null; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/FastByteArrayOutputStream.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/FastByteArrayOutputStream.ja0000644000175000017500000001004410014171324033715 0ustar twernertwerner/* * Title: FastByteArrayOutputStream * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.LinkedList; /** * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it * does not copy buffers when it's expanded. There's also no copying of the internal buffer * if it's contents is extracted with the writeTo(stream) method. * * @author Rickard �berg * @author Scott Farquhar * @version $Revision: 1.2 $ */ public class FastByteArrayOutputStream extends ByteArrayOutputStream { private static final int DEFAULT_BLOCK_SIZE = 8192; /** Internal buffer. */ private byte[] buffer; private LinkedList buffers; private int index; private int size; private int blockSize; public FastByteArrayOutputStream() { this(DEFAULT_BLOCK_SIZE); } public FastByteArrayOutputStream(int aSize) { blockSize = aSize; buffer = new byte[blockSize]; } public void writeTo(OutputStream out) throws IOException { // check if we have a list of buffers if (buffers != null) { Iterator iterator = buffers.iterator(); while (iterator.hasNext()) { byte[] bytes = (byte[]) iterator.next(); out.write(bytes, 0, blockSize); } } // write the internal buffer directly out.write(buffer, 0, index); } public int size() { return size + index; } public byte[] toByteArray() { byte[] data = new byte[size()]; // check if we have a list of buffers int pos = 0; if (buffers != null) { Iterator iterator = buffers.iterator(); while (iterator.hasNext()) { byte[] bytes = (byte[]) iterator.next(); System.arraycopy(bytes, 0, data, pos, blockSize); pos += blockSize; } } // write the internal buffer directly System.arraycopy(buffer, 0, data, pos, index); return data; } public void write(int datum) { if (index == blockSize) { // Create new buffer and store current in linked list if (buffers == null) buffers = new LinkedList(); buffers.addLast(buffer); buffer = new byte[blockSize]; size += index; index = 0; } // store the byte buffer[index++] = (byte) datum; } public void write(byte[] data, int offset, int length) { if (data == null) { throw new NullPointerException(); } else if ((offset < 0) || (offset + length > data.length) || (length < 0)) { throw new IndexOutOfBoundsException(); } else { if (index + length >= blockSize) { // Write byte by byte // FIXME optimize this to use arraycopy's instead for (int i = 0; i < length; i++) write(data[offset + i]); } else { // copy in the subarray System.arraycopy(data, offset, buffer, index, length); index += length; } } } public synchronized void reset() { buffer = new byte[blockSize]; buffers = null; } public String toString(String enc) throws UnsupportedEncodingException { return new String(toByteArray(), enc); } public String toString() { return new String(toByteArray()); } public void flush() throws IOException { // does nothing } public void close() throws IOException { // does nothing } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/OutputConverter.java0000644000175000017500000000445010057302646032335 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.util; import java.io.*; /** * A converter from one character type to another *

    * This class is not threadsafe */ public class OutputConverter { /** * Resin versions 2.1.12 and previously have encoding problems for internationalisation. *

    * This is fixed in Resin 2.1.13. Once 2.1.13 is used more widely, this parameter (and class) can be removed. */ public static final String WORK_AROUND_RESIN_I18N_BUG = "sitemesh.resin.i18n.workaround"; public static Writer getWriter(Writer out) { if ("true".equalsIgnoreCase(System.getProperty(WORK_AROUND_RESIN_I18N_BUG))) return new ResinWriter(out); else return out; } public static String convert(String inputString) throws IOException { if ("true".equalsIgnoreCase(System.getProperty(WORK_AROUND_RESIN_I18N_BUG))) { StringWriter sr = new StringWriter(); resinConvert(inputString, sr); return sr.getBuffer().toString(); } else return inputString; } /** * To get internationalised characters to work on Resin, some conversions need to take place. */ static class ResinWriter extends Writer { private final Writer target; private final CharArrayWriter buffer = new CharArrayWriter(); public ResinWriter(Writer target) { this.target = target; } public void close() throws IOException { flush(); } public void flush() throws IOException { resinConvert(buffer.toString(), target); buffer.reset(); } public void write(char cbuf[], int off, int len) throws IOException { buffer.write(cbuf, off, len); flush(); } } private static void resinConvert(String inputString, Writer writer) throws IOException { //does this need to be made configurable? Or are these two always correct? InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(inputString.getBytes("UTF-8")), "ISO-8859-1"); int i; while ((i = reader.read()) != -1) { writer.write(i); } writer.flush(); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/Container.java0000644000175000017500000000731510051635274031072 0ustar twernertwerner/* * Title: Container * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.util; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Utility for determining the Servlet Container the application is running in. * Currently supported containers: Tomcat, Resin, Orion, OC4J, WebLogic, HPAS, JRun, * Websphere. * *

    Usage:

    * * if (Container.get() == Container.TOMCAT) { .... } * * @author Joe Walnes * @version $Revision: 1.2 $ */ public final class Container { public static final int UNKNOWN = 0; public static final int TOMCAT = 1; public static final int RESIN = 2; public static final int ORION = 3; // Orion or OC4J public static final int WEBLOGIC = 4; public static final int HPAS = 5; public static final int JRUN = 6; public static final int WEBSPHERE = 7; private static int result = -1; /** * A map containing classes that can be searched for, * and which container they are typically found in. */ private static Map classMappings = null; static { // initialize the classes that can be searched for classMappings = new HashMap(6); classMappings.put("org.apache.jasper.runtime.JspFactoryImpl", new Integer(TOMCAT)); classMappings.put("com.caucho.jsp.JspServlet", new Integer(RESIN)); classMappings.put("com.evermind.server.http.JSPServlet", new Integer(ORION)); classMappings.put("weblogic.servlet.JSPServlet", new Integer(WEBLOGIC)); classMappings.put("com.hp.mwlabs.j2ee.containers.servlet.jsp.JspServlet", new Integer(HPAS)); classMappings.put("jrun.servlet.WebApplicationService", new Integer(JRUN)); classMappings.put("com.ibm.ws.webcontainer.jsp.servlet.JspServlet", new Integer(WEBSPHERE)); } /** Get the current container. */ public static int get() { if (result == -1) { final String classMatch = searchForClosestClass(classMappings); if (classMatch == null) { result = UNKNOWN; } else { result = ((Integer) classMappings.get(classMatch)).intValue(); } } return result; } /** * Walk up the classloader hierachy and attempt to find a class in the classMappings Map * that can be loaded. * * @return Name of the match class, or null if not found. */ private static String searchForClosestClass(Map classMappings) { // get closest classloader ClassLoader loader = Container.class.getClassLoader(); // iterate up through the classloader hierachy (through parents), until no more left. while (loader != null) { for (Iterator iterator = classMappings.keySet().iterator(); iterator.hasNext();) { String className = (String) iterator.next(); try { // attempt to load current classname with current classloader loader.loadClass(className); // if no exception has been thrown, we're in luck. return className; } catch (ClassNotFoundException e) { // no problem... we'll keep trying... } } loader = loader.getParent(); } // couldn't find anything return null; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/util/ClassLoaderUtil.java0000644000175000017500000000660310271264102032171 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.util; import java.net.URL; import java.io.InputStream; import java.io.IOException; /** * This class is extremely useful for loading resources and classes in a fault tolerant manner * that works across different applications servers. * * It has come out of many months of frustrating use of multiple application servers at Atlassian, * please don't change things unless you're sure they're not going to break in one server or another! */ public class ClassLoaderUtil { /** * Load a given resource. * * This method will try to load the resource using the following methods (in order): *
      *
    • From Thread.currentThread().getContextClassLoader() *
    • From ClassLoaderUtil.class.getClassLoader() *
    • callingClass.getClassLoader() *
    * * @param resourceName The name of the resource to load * @param callingClass The Class object of the calling object */ public static URL getResource(String resourceName, Class callingClass) { URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName); if (url == null) { url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName); } if (url == null) { ClassLoader cl = callingClass.getClassLoader(); if (cl != null) { url = cl.getResource(resourceName); } } if ((url == null) && (resourceName != null) && (resourceName.charAt(0) != '/')) { return getResource('/' + resourceName, callingClass); } return url; } /** * This is a convenience method to load a resource as a stream. * * The algorithm used to find the resource is given in getResource() * * @param resourceName The name of the resource to load * @param callingClass The Class object of the calling object */ public static InputStream getResourceAsStream(String resourceName, Class callingClass) { URL url = getResource(resourceName, callingClass); try { return (url != null) ? url.openStream() : null; } catch (IOException e) { return null; } } /** * Load a class with a given name. * * It will try to load the class in the following order: *
      *
    • From Thread.currentThread().getContextClassLoader() *
    • Using the basic Class.forName() *
    • From ClassLoaderUtil.class.getClassLoader() *
    • From the callingClass.getClassLoader() *
    * * @param className The name of the class to load * @param callingClass The Class object of the calling object * @throws ClassNotFoundException If the class cannot be found anywhere. */ public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException { try { return Thread.currentThread().getContextClassLoader().loadClass(className); } catch (ClassNotFoundException e) { try { return Class.forName(className); } catch (ClassNotFoundException ex) { try { return ClassLoaderUtil.class.getClassLoader().loadClass(className); } catch (ClassNotFoundException exc) { return callingClass.getClassLoader().loadClass(className); } } } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/freemarker/0000755000175000017500000000000011157130032027433 5ustar twernertwerner././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/freemarker/FreemarkerDecoratorServlet.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/freemarker/FreemarkerDecoratorSer0000644000175000017500000000456510057302646034002 0ustar twernertwerner/* * Title: FreemarkerDecoratorServlet Description: * * This software is published under the terms of the OpenSymphony Software License version 1.1, of which a copy has been included * with this distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.freemarker; import java.io.IOException; import java.io.StringWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.RequestConstants; import freemarker.ext.servlet.FreemarkerServlet; import freemarker.template.SimpleHash; import freemarker.template.Template; import freemarker.template.TemplateModel; /** * Servlet that allows Freemarker templates to be used as decorators. * * @author Richard HALLIER * @version $Revision: 1.2 $ */ public class FreemarkerDecoratorServlet extends FreemarkerServlet { /* (non-Javadoc) * @see freemarker.ext.servlet.FreemarkerServlet#preTemplateProcess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, freemarker.template.Template, freemarker.template.TemplateModel) */ protected boolean preTemplateProcess( HttpServletRequest request, HttpServletResponse response, Template template, TemplateModel templateModel) throws ServletException, IOException { boolean result=super.preTemplateProcess(request, response, template, templateModel); SimpleHash hash = (SimpleHash) templateModel; HTMLPage htmlPage = (HTMLPage) request.getAttribute(RequestConstants.PAGE); String title, body, head; if(htmlPage==null) { title="No Title"; body="No Body"; head=""; } else { title=htmlPage.getTitle(); StringWriter buffer = new StringWriter(); htmlPage.writeBody(buffer); body=buffer.toString(); buffer = new StringWriter(); htmlPage.writeHead(buffer); head=buffer.toString(); hash.put("page",htmlPage); } hash.put("title",title); hash.put("body",body); hash.put("head",head); hash.put("base",request.getContextPath()); /* Factory factory = Factory.getInstance(new Config(getServletConfig())); Decorator decorator = factory.getDecoratorMapper().getDecorator(request, htmlPage); -> decorator.getPage() */ return result; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/HTMLPage.java0000644000175000017500000000572310126462134027531 0ustar twernertwerner/* * Title: HTMLPage * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import java.io.IOException; import java.io.Writer; /** * Extension of {@link com.opensymphony.module.sitemesh.Page} providing access to HTML data. * *

    The page is parsed and the <title>, <head> * (minus the <title>) and <body> are split * into chunks. These can then be used by a {@link com.opensymphony.module.sitemesh.Decorator}. * Properties are also extracted from the HTML.

    * *

    Page Properties

    * *

    When the page is parsed, values from certain tags are added to the properties * to allow easy access to them. The following tags have properties extracted from them.

    * *
      *
    • * HTML Tag
      * All attributes of the <html> * tag shall be added as properties. *
    • *
    • * TITLE Tag
      * The contents of the <title> tag * shall be added as the title property. *
    • *
    • * META Tags
      * All the <meta> tags with * name and content attributes * will be added with the meta prefix. *
    • *
    • * BODY Tag
      * All attributes of the <body> tag * shall be added as properties with the * body prefix. *
    • *
    *

    Example

    *
     *   
     *     <html template="funky">
     *       <head>
     *         <title>My Funky Page</title>
     *         <meta name="description" content="Description of my page.">
     *         <meta name="author" content="Bob">
     *         ...
     *       </head>
     *       <body text="#ff00ff" bgcolor="green">
     *         ...
     *       </body>
     *     </html>
     *   
     * template=funky
     * title=My Funky Page
     * meta.description=Description of my page.
     * meta.author=Bob
     * body.text=#ff00ff
     * body.bgcolor=green
     * 
    * * @author Joe Walnes * @version $Revision: 1.3 $ */ public interface HTMLPage extends Page { /** * Write the contents of the <head> tag. */ void writeHead(Writer out) throws IOException; /** * Convenience method to return the contents of the <head> tag as a String. * * @since 2.1.1 * @see #writeHead(java.io.Writer) */ String getHead(); /** * Check to see if this page contains an * HTML frameset. */ boolean isFrameSet(); /** * Marks this page as a frameset. * * @since 2.3 * @see #isFrameSet() */ void setFrameSet(boolean frameset); }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/factory/0000755000175000017500000000000011157130032026757 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/factory/BaseFactory.java0000644000175000017500000001316410320161022032023 0ustar twernertwerner/* * Title: BaseFactory * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.factory; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Factory; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.util.ClassLoaderUtil; import com.opensymphony.module.sitemesh.mapper.PathMapper; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * Base Factory implementation. Provides utility methods for implementation. * * @author Joe Walnes * @version $Revision: 1.9 $ */ public abstract class BaseFactory extends Factory { /** ServletConfig or FilterConfig. */ protected Config config = null; /** * Instance of {@link com.opensymphony.module.sitemesh.DecoratorMapper}. * Because it is thread-safe, it can be shared by multiple clients. This * is only the last DecoratorMapper in the chain, and all parents will be * automatically delegated to it. */ protected DecoratorMapper decoratorMapper = null; /** Map that associates content-types with PageParser instances. */ protected Map pageParsers = null; /** A map of paths that are excluded from decoration */ protected PathMapper excludeUrls = null; /** * Constructor for default implementation of Factory. * Should never be called by client. Singleton instance should be * obtained instead. * * @see #getInstance(com.opensymphony.module.sitemesh.Config config) */ protected BaseFactory(Config config) { this.config = config; clearDecoratorMappers(); clearParserMappings(); clearExcludeUrls(); } /** Return instance of DecoratorMapper. */ public DecoratorMapper getDecoratorMapper() { return decoratorMapper; } /** * Create a PageParser suitable for the given content-type. * *

    For example, if the supplied parameter is text/html * a parser shall be returned that can parse HTML accordingly. Returns * null if no parser can be found for the supplied content type.

    * * @param contentType The MIME content-type of the data to be parsed * @return Appropriate PageParser for reading data, or * null if no suitable parser was found. */ public PageParser getPageParser(String contentType) { return (PageParser) pageParsers.get(contentType); } /** * Determine whether a Page of given content-type should be parsed or not. */ public boolean shouldParsePage(String contentType) { return pageParsers.containsKey(contentType); } /** * Returns true if the supplied path matches one of the exclude * URLs specified in sitemesh.xml, otherwise returns false. * @param path * @return whether the path is excluded */ public boolean isPathExcluded(String path) { return excludeUrls.get(path) != null; } /** * Clear all current DecoratorMappers. */ protected void clearDecoratorMappers() { decoratorMapper = null; } /** Push new DecoratorMapper onto end of chain. */ protected void pushDecoratorMapper(String className, Properties properties) { try { Class decoratorMapperClass = ClassLoaderUtil.loadClass(className, getClass()); DecoratorMapper newMapper = getDecoratorMapper(decoratorMapperClass); newMapper.init(config, properties, decoratorMapper); decoratorMapper = newMapper; } catch (ClassNotFoundException e) { throw new FactoryException("Could not load DecoratorMapper class : " + className, e); } catch (Exception e) { throw new FactoryException("Could not initialize DecoratorMapper : " + className, e); } } protected DecoratorMapper getDecoratorMapper(Class decoratorMapperClass) throws InstantiationException, IllegalAccessException { return (DecoratorMapper) decoratorMapperClass.newInstance(); } /** Clear all PageParser mappings. */ protected void clearParserMappings() { pageParsers = new HashMap(); } /** * Map new PageParser to given content-type. contentType = null signifies default * PageParser for unknown content-types. */ protected void mapParser(String contentType, String className) { if (className.endsWith(".DefaultPageParser")) { return; // Backwards compatability - this can safely be ignored. } try { PageParser pp = (PageParser) ClassLoaderUtil.loadClass(className, getClass()).newInstance(); // Store the parser even if the content type is NULL. [This // is most probably the legacy default page parser which // we no longer have a use for] pageParsers.put(contentType, pp); } catch (ClassNotFoundException e) { throw new FactoryException("Could not load PageParser class : " + className, e); } catch (Exception e) { throw new FactoryException("Could not instantiate PageParser : " + className, e); } } protected void addExcludeUrl(String path) { excludeUrls.put("", path); } /** * Clears all exclude URLs. */ protected void clearExcludeUrls() { excludeUrls = new PathMapper(); } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/factory/FactoryException.java0000644000175000017500000000345510566417556033145 0ustar twernertwerner/* * Title: FactoryException * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.factory; import java.io.PrintStream; import java.io.PrintWriter; /** * This RuntimeException is thrown by the Factory if it cannot initialize or perform * an appropriate function. * * @author Joe Walnes * @version $Revision: 1.2 $ */ public class FactoryException extends RuntimeException { protected Throwable exception = null; public FactoryException() { super(); } public FactoryException(String msg) { super(msg); } public FactoryException(Exception e) { super(); exception = e; } public FactoryException(String msg, Throwable e) { super(msg + ": " + e); exception = e; } /** * Get the original cause of the Exception. Returns null if not known. */ public Throwable getRootCause() { return exception; } public void printStackTrace() { super.printStackTrace(); if (exception != null) { synchronized (System.err) { System.err.println("\nRoot cause:"); exception.printStackTrace(); } } } public void printStackTrace(PrintStream s) { super.printStackTrace(s); if (exception != null) { synchronized (s) { s.println("\nRoot cause:"); exception.printStackTrace(s); } } } public void printStackTrace(PrintWriter s) { super.printStackTrace(s); if (exception != null) { synchronized (s) { s.println("\nRoot cause:"); exception.printStackTrace(s); } } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/factory/sitemesh-default.xml0000644000175000017500000000205010520674306032753 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/factory/DefaultFactory.java0000644000175000017500000002777410566421562032575 0ustar twernertwerner/* * Title: DefaultFactory * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.factory; import com.opensymphony.module.sitemesh.Config; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.*; /** * DefaultFactory, reads configuration from the sitemesh.configfile init param, * or /WEB-INF/sitemesh.xml if not specified, or uses the * default configuration if sitemesh.xml does not exist. * *

    To use the sitemesh.configfile parameter, add the following to your web.xml: *

     * <context-param>
     *      <param-name>sitemesh.configfile</param-name>
     *      <param-value>/WEB-INF/etc/sitemesh.xml</param-value>
     *  </context-param>
     * 
    *

    * * @author Joe Walnes * @author Mathias Bogaert * @version $Revision: 1.8 $ */ public class DefaultFactory extends BaseFactory { String configFileName; private static final String DEFAULT_CONFIG_FILENAME = "/WEB-INF/sitemesh.xml"; File configFile; long configLastModified; private long configLastCheck = 0L; public static long configCheckMillis = 3000L; Map configProps = new HashMap(); String excludesFileName; File excludesFile; public DefaultFactory(Config config) { super(config); configFileName = config.getServletContext().getInitParameter("sitemesh.configfile"); if (configFileName == null) { configFileName = DEFAULT_CONFIG_FILENAME; } // configFilePath is null if loaded from war file String initParamConfigFile = config.getConfigFile(); if(initParamConfigFile != null) { configFileName = initParamConfigFile; } String configFilePath = config.getServletContext().getRealPath(configFileName); if (configFilePath != null) { // disable config auto reloading for .war files configFile = new File(configFilePath); } loadConfig(); } /** Load configuration from file. */ private synchronized void loadConfig() { try { // Load and parse the sitemesh.xml file Element root = loadSitemeshXML(); NodeList sections = root.getChildNodes(); // Loop through child elements of root node for (int i = 0; i < sections.getLength(); i++) { if (sections.item(i) instanceof Element) { Element curr = (Element)sections.item(i); NodeList children = curr.getChildNodes(); if ("config-refresh".equalsIgnoreCase(curr.getTagName())) { String seconds = curr.getAttribute("seconds"); configCheckMillis = Long.parseLong(seconds) * 1000L; } else if ("property".equalsIgnoreCase(curr.getTagName())) { String name = curr.getAttribute("name"); String value = curr.getAttribute("value"); if (!"".equals(name) && !"".equals(value)) { configProps.put("${" + name + "}", value); } } else if ("page-parsers".equalsIgnoreCase(curr.getTagName())) { // handle loadPageParsers(children); } else if ("decorator-mappers".equalsIgnoreCase(curr.getTagName())) { // handle loadDecoratorMappers(children); } else if ("excludes".equalsIgnoreCase(curr.getTagName())) { // handle String fileName = replaceProperties(curr.getAttribute("file")); if (!"".equals(fileName)) { excludesFileName = fileName; loadExcludes(); } } } } } catch (ParserConfigurationException e) { throw new FactoryException("Could not get XML parser", e); } catch (IOException e) { throw new FactoryException("Could not read config file : " + configFileName, e); } catch (SAXException e) { throw new FactoryException("Could not parse config file : " + configFileName, e); } } private Element loadSitemeshXML() throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); InputStream is = null; if (configFile == null) { is = config.getServletContext().getResourceAsStream(configFileName); } else if (configFile.exists() && configFile.canRead()) { is = configFile.toURL().openStream(); } if (is == null){ // load the default sitemesh configuration is = getClass().getClassLoader().getResourceAsStream("com/opensymphony/module/sitemesh/factory/sitemesh-default.xml"); } if (is == null){ // load the default sitemesh configuration using another classloader is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/opensymphony/module/sitemesh/factory/sitemesh-default.xml"); } if (is == null){ throw new IllegalStateException("Cannot load default configuration from jar"); } if (configFile != null) configLastModified = configFile.lastModified(); Document doc = builder.parse(is); Element root = doc.getDocumentElement(); // Verify root element if (!"sitemesh".equalsIgnoreCase(root.getTagName())) { throw new FactoryException("Root element of sitemesh configuration file not ", null); } return root; } private void loadExcludes() throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); InputStream is = null; if (excludesFile == null) { is = config.getServletContext().getResourceAsStream(excludesFileName); } else if (excludesFile.exists() && excludesFile.canRead()) { is = excludesFile.toURL().openStream(); } if (is == null){ throw new IllegalStateException("Cannot load excludes configuration file \"" + excludesFileName + "\" as specified in \"sitemesh.xml\" or \"sitemesh-default.xml\""); } Document document = builder.parse(is); Element root = document.getDocumentElement(); NodeList sections = root.getChildNodes(); // Loop through child elements of root node looking for the block for (int i = 0; i < sections.getLength(); i++) { if (sections.item(i) instanceof Element) { Element curr = (Element)sections.item(i); if ("excludes".equalsIgnoreCase(curr.getTagName())) { loadExcludeUrls(curr.getChildNodes()); } } } } /** Loop through children of 'page-parsers' element and add all 'parser' mappings. */ private void loadPageParsers(NodeList nodes) { clearParserMappings(); for (int i = 0; i < nodes.getLength(); i++) { if (nodes.item(i) instanceof Element) { Element curr = (Element)nodes.item(i); if ("parser".equalsIgnoreCase(curr.getTagName())) { String className = curr.getAttribute("class"); String contentType = curr.getAttribute("content-type"); mapParser(contentType, className); } } } } private void loadDecoratorMappers(NodeList nodes) { clearDecoratorMappers(); Properties emptyProps = new Properties(); pushDecoratorMapper("com.opensymphony.module.sitemesh.mapper.NullDecoratorMapper", emptyProps); // note, this works from the bottom node up. for (int i = nodes.getLength() - 1; i > 0; i--) { if (nodes.item(i) instanceof Element) { Element curr = (Element)nodes.item(i); if ("mapper".equalsIgnoreCase(curr.getTagName())) { String className = curr.getAttribute("class"); Properties props = new Properties(); // build properties from tags. NodeList children = curr.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { if (children.item(j) instanceof Element) { Element currC = (Element)children.item(j); if ("param".equalsIgnoreCase(currC.getTagName())) { String value = currC.getAttribute("value"); props.put(currC.getAttribute("name"), replaceProperties(value)); } } } // add mapper pushDecoratorMapper(className, props); } } } pushDecoratorMapper("com.opensymphony.module.sitemesh.mapper.InlineDecoratorMapper", emptyProps); } /** * Reads in all the url patterns to exclude from decoration. */ private void loadExcludeUrls(NodeList nodes) { clearExcludeUrls(); for (int i = 0; i < nodes.getLength(); i++) { if (nodes.item(i) instanceof Element) { Element p = (Element) nodes.item(i); if ("pattern".equalsIgnoreCase(p.getTagName()) || "url-pattern".equalsIgnoreCase(p.getTagName())) { Text patternText = (Text) p.getFirstChild(); if (patternText != null) { String pattern = patternText.getData().trim(); if (pattern != null) { addExcludeUrl(pattern); } } } } } } /** Check if configuration file has been modified, and if so reload it. */ public void refresh() { long time = System.currentTimeMillis(); if (time - configLastCheck < configCheckMillis) return; configLastCheck = time; if (configFile != null && configLastModified != configFile.lastModified()) loadConfig(); } /** * Replaces any properties that appear in the supplied string * with their actual values * * @param str the string to replace the properties in * @return the same string but with any properties expanded out to their * actual values */ private String replaceProperties(String str) { Set props = configProps.entrySet(); for (Iterator it = props.iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); String key = (String) entry.getKey(); int idx; while ((idx = str.indexOf(key)) >= 0) { StringBuffer buf = new StringBuffer(100); buf.append(str.substring(0, idx)); buf.append(entry.getValue()); buf.append(str.substring(idx + key.length())); str = buf.toString(); } } return str; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/Config.java0000644000175000017500000000273710131601104027363 0ustar twernertwerner/* * Title: Config * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import javax.servlet.FilterConfig; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; /** * Common interface to ServletConfig and FilterConfig * (since javax.servlet.Config was removed from 2.3 spec). * * @author Joe Walnes * @version $Revision: 1.2 $ */ public class Config { private ServletConfig servletConfig; private FilterConfig filterConfig; private String configFile; public Config(ServletConfig servletConfig) { if (servletConfig == null) throw new NullPointerException("ServletConfig cannot be null"); this.servletConfig = servletConfig; this.configFile = servletConfig.getInitParameter("configFile"); } public Config(FilterConfig filterConfig) { if (filterConfig == null) throw new NullPointerException("FilterConfig cannot be null"); this.filterConfig = filterConfig; this.configFile = filterConfig.getInitParameter("configFile"); } public ServletContext getServletContext() { return servletConfig != null ? servletConfig.getServletContext() : filterConfig.getServletContext(); } public String getConfigFile() { return configFile; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/0000755000175000017500000000000011157130036027335 5ustar twernertwerner././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/MultipassReplacementPageParser.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/MultipassReplacementPag0000644000175000017500000000256010276421210034052 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.multipass; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.html.HTMLProcessor; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class MultipassReplacementPageParser implements PageParser { private final Page page; private final HttpServletResponse response; public MultipassReplacementPageParser(Page page, HttpServletResponse response) { this.page = page; this.response = response; } public Page parse(char[] data) throws IOException { final CharArray result = new CharArray(4096); HTMLProcessor processor = new HTMLProcessor(data, result); processor.addRule(new BasicRule("sitemesh:multipass") { public void process(Tag tag) { String id = tag.getAttributeValue("id", true); if (!page.isPropertySet("_sitemesh.removefrompage." + id)) { currentBuffer().append(page.getProperty(id)); } } }); processor.process(); result.writeTo(response.getWriter()); return null; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/ExtractPropertyTag.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/ExtractPropertyTag.java0000644000175000017500000000062510276421210034014 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.multipass; import com.opensymphony.module.sitemesh.taglib.decorator.PropertyTag; import com.opensymphony.module.sitemesh.Page; public class ExtractPropertyTag extends PropertyTag { public int doEndTag() { Page page = getPage(); page.addProperty("_sitemesh.removefrompage." + getProperty(), "true"); return super.doEndTag(); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/MultipassFilter.java0000644000175000017500000000243010550354754033341 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.multipass; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.PageParserSelector; import com.opensymphony.sitemesh.webapp.SiteMeshFilter; import com.opensymphony.module.sitemesh.filter.PageResponseWrapper; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class MultipassFilter extends SiteMeshFilter { protected void writeDecorator(final HttpServletResponse response, final Page page, RequestDispatcher dispatcher, HttpServletRequest request) throws ServletException, IOException { PageResponseWrapper pageResponse = new PageResponseWrapper(response, new PageParserSelector() { public boolean shouldParsePage(String contentType) { return true; } public PageParser getPageParser(String contentType) { return new MultipassReplacementPageParser(page, response); } }); pageResponse.activateSiteMesh("text/html", ""); dispatcher.include(request, pageResponse); pageResponse.getPage(); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/DivExtractingPageParser.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/multipass/DivExtractingPageParser0000644000175000017500000000342210276421206034011 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.multipass; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.State; import com.opensymphony.module.sitemesh.html.Tag; import com.opensymphony.module.sitemesh.html.rules.PageBuilder; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.parser.HTMLPageParser; public class DivExtractingPageParser extends HTMLPageParser { protected void addUserDefinedRules(State html, final PageBuilder page) { super.addUserDefinedRules(html, page); html.addRule(new TopLevelDivExtractingRule(page)); } private static class TopLevelDivExtractingRule extends BasicRule { private String blockId; private int depth; private final PageBuilder page; public TopLevelDivExtractingRule(PageBuilder page) { super("div"); this.page = page; } public void process(Tag tag) { if (tag.getType() == Tag.OPEN) { String id = tag.getAttributeValue("id", false); if (depth == 0 && id != null) { currentBuffer().append(""); blockId = id; context.pushBuffer(new CharArray(512)); } tag.writeTo(currentBuffer()); depth++; } else if (tag.getType() == Tag.CLOSE) { depth--; tag.writeTo(currentBuffer()); if (depth == 0 && blockId != null) { page.addProperty("div." + blockId, currentBuffer().toString()); blockId = null; context.popBuffer(); } } } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/RequestConstants.java0000644000175000017500000000324110550354754031517 0ustar twernertwerner/* * Title: RequestConstants * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; /** * A set of static constants of Strings to be used as ServletRequest attribute keys * to represent various objects passed between pages. * * @author Joe Walnes * @version $Revision: 1.3 $ * * @see com.opensymphony.sitemesh.webapp.SiteMeshFilter * @see com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag * @see com.opensymphony.module.sitemesh.mapper.InlineDecoratorMapper * @see com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper */ public interface RequestConstants { /** * Stores {@link com.opensymphony.module.sitemesh.Page} instance for parsed page to be * passed across to {@link com.opensymphony.module.sitemesh.Decorator}. */ String PAGE = "__sitemesh__page"; /** * The name (String) of the Decorator to suggest using. This is set by * the {@link com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag} * and used by the corresponding {@link com.opensymphony.module.sitemesh.DecoratorMapper}. */ String DECORATOR = "__sitemesh__decorator"; /** * Marker that stores a Boolean (under the session) to state whether the current * session is the session of a web search engine spider. This is set and used by the * {@link com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper}. */ String ROBOT = "__sitemesh__robot"; }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/0000755000175000017500000000000011157130040027162 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Head.jwc0000644000175000017500000000117610273774306030556 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Property.jwc0000644000175000017500000000143310273774310031530 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Body.html0000644000175000017500000000002610273774306030764 0ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/SiteMeshBase.java0000644000175000017500000000057110273774310032360 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.tapestry; import com.opensymphony.module.sitemesh.Page; import org.apache.tapestry.BaseComponent; /** * Base class for Tapestry decorator components. * * @author Erik Hatcher */ public class SiteMeshBase extends BaseComponent { public Page getSiteMeshPage() { return Util.getPage(getPage().getRequestCycle()); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/sitemesh.library0000644000175000017500000000102410273774310032402 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Title.jwc0000644000175000017500000000130110273774310030757 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Title.html0000644000175000017500000000002610273774310031143 0ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Body.jwc0000644000175000017500000000117610273774306030612 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Util.java0000644000175000017500000000261110273774310030756 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.tapestry; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.RequestConstants; import org.apache.tapestry.IRender; import org.apache.tapestry.IRequestCycle; import org.apache.tapestry.valid.RenderString; /** * This utility class gives easy access to the SiteMesh page, with convenience * methods for title and property. A common usage would be with OGNL expressions * like this: *

    * *

    * In future versions of Tapestry, thanks to HiveMind integration, this will * become a lot cleaner, probably like this: *

    * * * @author Erik Hatcher */ public class Util { public static String getTitle(IRequestCycle cycle) { return getPage(cycle).getTitle(); } public static String getProperty(String name, IRequestCycle cycle) { return getPage(cycle).getProperty(name); } public static Page getPage(IRequestCycle cycle) { return (Page) cycle.getRequestContext().getRequest().getAttribute( RequestConstants.PAGE); } public static IRender getHeadRenderer(IRequestCycle cycle) { return new RenderString(((HTMLPage) getPage(cycle)).getHead(), true); } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Title.java0000644000175000017500000000052710273774310031126 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.tapestry; import org.apache.tapestry.Tapestry; public abstract class Title extends SiteMeshBase { public abstract String getDefault(); public String getTitle() { String title = getSiteMeshPage().getTitle(); return Tapestry.isBlank(title) ? getDefault() : title; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Property.java0000644000175000017500000000212010273774310031660 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.tapestry; import org.apache.tapestry.Tapestry; /** * Because Tapestry templating works differently than JSP taglibs, * the writeEntireProperty feature is not implemented here. The built-in * * @Body component is most frequently used, to do something like * this taglib example: *

    * > *

    * it would be done like this in Tapestry: *

    * * * @author Erik Hatcher */ public abstract class Property extends SiteMeshBase { public abstract String getProperty(); public abstract String getDefault(); public String getValue() { String propertyName = getProperty(); String propertyValue = getSiteMeshPage().getProperty(propertyName); if (Tapestry.isBlank(propertyValue)) { propertyValue = getDefault(); } return propertyValue; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Head.html0000644000175000017500000000002610273774306030730 0ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/tapestry/Property.html0000644000175000017500000000002610273774306031713 0ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/servlets/0000755000175000017500000000000011157130036027163 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/PageParserSelector.java0000644000175000017500000000131610276421212031712 0ustar twernertwernerpackage com.opensymphony.module.sitemesh; /** * @author Joe Walnes */ public interface PageParserSelector { /** * Determine whether a Page of given content-type should be parsed or not. */ boolean shouldParsePage(String contentType); /** * Create a PageParser suitable for the given content-type. * *

    For example, if the supplied parameter is text/html * a parser shall be returned that can parse HTML accordingly.

    Never returns null. * * @param contentType The MIME content-type of the data to be parsed * @return Appropriate PageParser for reading data * */ PageParser getPageParser(String contentType); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/0000755000175000017500000000000011157130034026256 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/tokenizer/0000755000175000017500000000000011157130034030270 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/tokenizer/Parser.java0000644000175000017500000003106410272462012032374 0ustar twernertwerner/* * IF YOU ARE HAVING TROUBLE COMPILING THIS CLASS, IT IS PROBABLY BECAUSE Lexer.java IS MISSING. * * Use 'ant jflex' to generate the file, which will reside in build/java */ package com.opensymphony.module.sitemesh.html.tokenizer; import com.opensymphony.module.sitemesh.html.Tag; import com.opensymphony.module.sitemesh.html.Text; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.util.CharArrayReader; import java.io.IOException; /** * Looks for patterns of tokens in the Lexer and translates these to calls to pass to the TokenHandler. * * @author Joe Walnes * @see TagTokenizer */ public class Parser extends Lexer { private final CharArray attributeBuffer = new CharArray(64); private final ReusableToken reusableToken = new ReusableToken(); private int pushbackToken = -1; private String pushbackText; public final static short SLASH=257; public final static short WHITESPACE=258; public final static short EQUALS=259; public final static short QUOTE=260; public final static short WORD=261; public final static short TEXT=262; public final static short QUOTED=263; public final static short LT=264; public final static short GT=265; public final static short LT_OPEN_MAGIC_COMMENT=266; public final static short LT_CLOSE_MAGIC_COMMENT=267; private final char[] input; private TokenHandler handler; private int position; private int length; private String name; private int type; public Parser(char[] input, TokenHandler handler) { super(new CharArrayReader(input)); this.input = input; this.handler = handler; } private String text() { if (pushbackToken == -1) { return yytext(); } else { return pushbackText; } } private void skipWhiteSpace() throws IOException { while (true) { int next; if (pushbackToken == -1) { next = yylex(); } else { next = pushbackToken; pushbackToken = -1; } if (next != Parser.WHITESPACE) { pushBack(next); break; } } } private void pushBack(int next) { if (pushbackToken != -1) { reportError("Cannot pushback more than once", line(), column()); } pushbackToken = next; if (next == Parser.WORD || next == Parser.QUOTED || next == Parser.SLASH || next == Parser.EQUALS) { pushbackText = yytext(); } else { pushbackText = null; } } public void start() { try { while (true) { int token; if (pushbackToken == -1) { token = yylex(); } else { token = pushbackToken; pushbackToken = -1; } if (token == 0) { // EOF return; } else if (token == Parser.TEXT) { // Got some text parsedText(position(), length()); } else if (token == Parser.LT) { // Token "<" - start of tag parseTag(Tag.OPEN); } else if (token == Parser.LT_OPEN_MAGIC_COMMENT) { // Token "" { return Parser.TEXT; } /* All comments unless they start with " { return Parser.TEXT; } "" { return Parser.TEXT; } "" { return Parser.TEXT; } "" { return Parser.TEXT; } "" { return Parser.TEXT; } "" { return Parser.TEXT; } [^<]+ { return Parser.TEXT; } "<" { yybegin(ELEMENT); return Parser.LT; } "" { yybegin(YYINITIAL); return Parser.GT; } } /* Fallback rule - if nothing else matches. */ .|\n { reportError("Illegal character <"+ yytext() +">", line(), column()); return Parser.TEXT; } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/0000755000175000017500000000000011157130034027410 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/FramesetRule.java0000644000175000017500000000071710174661266032674 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; public class FramesetRule extends BasicRule { private final PageBuilder page; public FramesetRule(PageBuilder page) { super(new String[] {"frame", "frameset"}); this.page = page; } public void process(Tag tag) { page.addProperty("frameset", "true"); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/RegexReplacementTextFilter.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/RegexReplacementTextFi0000644000175000017500000000233110211673544033720 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.TextFilter; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * TextFilter that substitutes content using a JDK 1.4 regular expression. * *

    Example

    * * This will substitute 'Google:Blah' for a link to a google search. * *
    HTMLProcessor processor = new HTMLProcessor(in, out);
     * processor.addTextFilter(new RegexReplacementTextFilter("Google:([a-zA-Z]+)", "$1"));
     * // add more TextFilters and TagRules
     * processor.process();
    * * @author Joe Walnes */ public class RegexReplacementTextFilter implements TextFilter { private final Pattern regex; private final String replacement; public RegexReplacementTextFilter(String regex, String replacement) { this.regex = Pattern.compile(regex); this.replacement = replacement; } public RegexReplacementTextFilter(Pattern regex, String replacement) { this.regex = regex; this.replacement = replacement; } public String filter(String text) { Matcher matcher = regex.matcher(text); return matcher.replaceAll(replacement); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/HeadExtractingRule.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/HeadExtractingRule.jav0000644000175000017500000000071610174661264033654 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BlockExtractingRule; import com.opensymphony.module.sitemesh.html.util.CharArray; public class HeadExtractingRule extends BlockExtractingRule { private final CharArray head; public HeadExtractingRule(CharArray head) { super(false, "head"); this.head = head; } protected CharArray createBuffer() { return head; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/PageBuilder.java0000644000175000017500000000067710174661266032466 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; /** * Allows a TagRule to add information to a Page object. * * The standard HTML processing rules bundled with SiteMesh use this interface instead of direct coupling to the HTMLPage * class, allowing the rules to be used for HTML processing in applications outside of SiteMesh. * * @author Joe Walnes */ public interface PageBuilder { void addProperty(String key, String value); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/HtmlAttributesRule.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/HtmlAttributesRule.jav0000644000175000017500000000114610174661266033735 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; public class HtmlAttributesRule extends BasicRule{ private final PageBuilder page; public HtmlAttributesRule(PageBuilder page) { super("html"); this.page = page; } public void process(Tag tag) { if (tag.getType() == Tag.OPEN) { for (int i = 0; i < tag.getAttributeCount(); i++) { page.addProperty(tag.getAttributeName(i), tag.getAttributeValue(i)); } } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/TagReplaceRule.java0000644000175000017500000000154510174661266033135 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; import com.opensymphony.module.sitemesh.html.CustomTag; /** * Very simple rule for replacing all occurences of one tag with another. * *

    For example, to convert all <b> tags to <strong>:

    *

    html.addRule(new TagReplaceRule("b", "strong"));

    * * @author Joe Walnes */ public class TagReplaceRule extends BasicRule { private final String newTagName; public TagReplaceRule(String originalTagName, String newTagName) { super(originalTagName); this.newTagName = newTagName; } public void process(Tag tag) { CustomTag customTag = new CustomTag(tag); customTag.setName(newTagName); customTag.writeTo(currentBuffer()); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/ContentBlockExtractingRule.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/ContentBlockExtracting0000644000175000017500000000123310174661266033766 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BlockExtractingRule; import com.opensymphony.module.sitemesh.html.Tag; public class ContentBlockExtractingRule extends BlockExtractingRule { private final PageBuilder page; private String contentBlockId; public ContentBlockExtractingRule(PageBuilder page) { super(false, "content"); this.page = page; } protected void start(Tag tag) { contentBlockId = tag.getAttributeValue("tag", false); } protected void end(Tag tag) { page.addProperty("page." + contentBlockId, currentBuffer().toString()); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/BodyTagRule.java0000644000175000017500000000164110174661266032454 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; import com.opensymphony.module.sitemesh.html.util.CharArray; public class BodyTagRule extends BasicRule { private final PageBuilder page; private final CharArray body; public BodyTagRule(PageBuilder page, CharArray body) { super("body"); this.page = page; this.body = body; } public void process(Tag tag) { if (tag.getType() == Tag.OPEN || tag.getType() == Tag.EMPTY) { for (int i = 0; i < tag.getAttributeCount(); i++) { page.addProperty("body." + tag.getAttributeName(i), tag.getAttributeValue(i)); } body.clear(); } else { context.pushBuffer(new CharArray(64)); // unused buffer: everything after is discarded. } } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/MSOfficeDocumentPropertiesRule.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/MSOfficeDocumentProper0000644000175000017500000000241410174661266033674 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BlockExtractingRule; import com.opensymphony.module.sitemesh.html.Tag; /** * Extracts the extra properties saved in HTML from MS Office applications (Word and Excel), * such as Author, Company, Version, etc. * * @author Joe Walnes */ public class MSOfficeDocumentPropertiesRule extends BlockExtractingRule { private final PageBuilder page; private boolean inDocumentProperties; public MSOfficeDocumentPropertiesRule(PageBuilder page) { super(true); this.page = page; } public boolean shouldProcess(String name) { return (inDocumentProperties && name.startsWith("o:")) || name.equals("o:documentproperties"); } public void process(Tag tag) { if (tag.getName().equals("o:DocumentProperties")) { inDocumentProperties = (tag.getType() == Tag.OPEN); tag.writeTo(currentBuffer()); } else { super.process(tag); } } protected void start(Tag tag) { } protected void end(Tag tag) { String name = tag.getName().substring(2); page.addProperty("office.DocumentProperties." + name, currentBuffer().toString()); context.mergeBuffer(); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/MetaTagRule.java0000644000175000017500000000143410174661264032443 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; public class MetaTagRule extends BasicRule { private final PageBuilder page; public MetaTagRule(PageBuilder page) { super("meta"); this.page = page; } public void process(Tag tag) { if (tag.hasAttribute("name", false)) { page.addProperty("meta." + tag.getAttributeValue("name", false), tag.getAttributeValue("content", false)); } else if (tag.hasAttribute("http-equiv", false)) { page.addProperty("meta.http-equiv." + tag.getAttributeValue("http-equiv", false), tag.getAttributeValue("content", false)); } tag.writeTo(currentBuffer()); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/TitleExtractingRule.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/TitleExtractingRule.ja0000644000175000017500000000112210174661264033676 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BlockExtractingRule; import com.opensymphony.module.sitemesh.html.Tag; public class TitleExtractingRule extends BlockExtractingRule { private final PageBuilder page; private boolean seenTitle; public TitleExtractingRule(PageBuilder page) { super(false, "title"); this.page = page; } protected void end(Tag tag) { if (!seenTitle) { page.addProperty("title", currentBuffer().toString()); seenTitle = true; } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/ParameterExtractingRule.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/rules/ParameterExtractingRul0000644000175000017500000000101710174661266034004 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.rules; import com.opensymphony.module.sitemesh.html.BasicRule; import com.opensymphony.module.sitemesh.html.Tag; public class ParameterExtractingRule extends BasicRule{ private final PageBuilder page; public ParameterExtractingRule(PageBuilder page) { super("parameter"); this.page = page; } public void process(Tag tag) { page.addProperty("page." + tag.getAttributeValue("name", false), tag.getAttributeValue("value", false)); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/Tag.java0000644000175000017500000000420110165645470027646 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import com.opensymphony.module.sitemesh.html.util.CharArray; /** * Tag returned by HTMLTagTokenizer. Allows easy access to element name and attributes. * * This interface supports read-only operations on the tag. To change a tag, use {@link CustomTag}. * * @see com.opensymphony.module.sitemesh.html.tokenizer.TokenHandler * @see com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer * @see CustomTag * * @author Joe Walnes */ public interface Tag { int OPEN = 1; int CLOSE = 2; int EMPTY = 3; int OPEN_MAGIC_COMMENT = 4; int CLOSE_MAGIC_COMMENT = 5; /** * Get the complete tag in its original form, preserving original formatting. * * This has a slight overhead in that it needs to construct a String. For improved performance, use writeTo() instead. * * @see #writeTo(com.opensymphony.module.sitemesh.html.util.CharArray) */ String getContents(); /** * Write out the complete tag in its original form, preserving original formatting. */ void writeTo(CharArray out); /** * Name of tag (ie. element name). */ String getName(); /** * Type of tag:
    * <blah> - Tag.OPEN
    * </blah> - Tag.CLOSE
    * <blah/> - Tag.EMPTY
    */ int getType(); /** * Number of attributes in tag. */ int getAttributeCount(); /** * Determine which attribute has the specified name. */ int getAttributeIndex(String name, boolean caseSensitive); /** * Get name of attribute. */ String getAttributeName(int index); /** * Get value of an attribute. If this is an empty attribute (i.e. just a name, without a value), null is returned. */ String getAttributeValue(int index); /** * Get value of an attribute. If this is an empty attribute (i.e. just a name, without a value), null is returned. */ String getAttributeValue(String name, boolean caseSensitive); /** * Determine if an attribute is present. */ boolean hasAttribute(String name, boolean caseSensitive); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/Text.java0000644000175000017500000000147410126462130030053 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import com.opensymphony.module.sitemesh.html.util.CharArray; /** * Text returned by HTMLTagTokenizer. * * @see com.opensymphony.module.sitemesh.html.tokenizer.TokenHandler * @see com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer * * @author Joe Walnes */ public interface Text { /** * Get the complete contents of the text block, preserving original formatting. * * This has a slight overhead in that it needs to construct a String. For improved performance, use writeTo() instead. * * @see #writeTo(com.opensymphony.module.sitemesh.html.util.CharArray) */ String getContents(); /** * Write out the complete contents of the text block, preserving original formatting. */ void writeTo(CharArray out); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/BasicRule.java0000644000175000017500000000240610165645350031006 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import com.opensymphony.module.sitemesh.html.util.CharArray; public abstract class BasicRule implements TagRule { private final String[] acceptableTagNames; protected HTMLProcessorContext context; protected BasicRule(String[] acceptableTagNames) { this.acceptableTagNames = acceptableTagNames; } protected BasicRule(String acceptableTagName) { this.acceptableTagNames = new String[] {acceptableTagName}; } protected BasicRule() { this.acceptableTagNames = null; } public void setContext(HTMLProcessorContext context) { this.context = context; } public boolean shouldProcess(String name) { if (acceptableTagNames == null || acceptableTagNames.length < 1) { throw new UnsupportedOperationException(getClass().getName() + " should be constructed with acceptableTagNames OR should implement shouldProcess()"); } for (int i=0; iMore than one TextFilter may be added to each HTMLProcessor/State and they will be called in the order they were added.

    * * @author Joe Walnes * * @see HTMLProcessor * @see State * @see com.opensymphony.module.sitemesh.html.rules.RegexReplacementTextFilter */ public interface TextFilter { String filter(String content); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/State.java0000644000175000017500000000464510273515032030215 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public final class State { private TagRule[] rules = new TagRule[16]; // List is too slow, according to profiler private int ruleCount = 0; private List listeners = null; private List textFilters = null; // lazily instantiated to reduce overhead for most cases where it's not needed. public void addRule(TagRule rule) { if (ruleCount == rules.length) { // grow array if necessary TagRule[] longerArray = new TagRule[rules.length * 2]; System.arraycopy(rules, 0, longerArray, 0, ruleCount); rules = longerArray; } rules[ruleCount++] = rule; } public void addTextFilter(TextFilter textFilter) { if (textFilters == null) { textFilters = new ArrayList(); // lazy instantiation } textFilters.add(textFilter); } public boolean shouldProcessTag(String tagName) { for (int i = ruleCount - 1; i >= 0; i--) { // reverse iteration to so most recently added rule matches if (rules[i].shouldProcess(tagName)) { return true; } } return false; } public TagRule getRule(String tagName) { for (int i = ruleCount - 1; i >= 0; i--) { // reverse iteration to so most recently added rule matches if (rules[i].shouldProcess(tagName)) { return rules[i]; } } return null; } public void addListener(StateChangeListener listener) { if(listeners == null) listeners = new ArrayList(); listeners.add(listener); } public void endOfState() { if(listeners == null) return; for (Iterator iter = listeners.iterator(); iter.hasNext();) { StateChangeListener listener = (StateChangeListener) iter.next(); listener.stateFinished(); } } public void handleText(Text text, HTMLProcessorContext context) { if (textFilters == null) { text.writeTo(context.currentBuffer()); } else { String asString = text.getContents(); for (Iterator iterator = textFilters.iterator(); iterator.hasNext();) { TextFilter textFilter = (TextFilter) iterator.next(); asString = textFilter.filter(asString); } context.currentBuffer().append(asString); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/util/0000755000175000017500000000000011157130034027233 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/util/CharArray.java0000644000175000017500000001724410276421206031767 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html.util; import java.io.PrintWriter; /** * A leaner, meaner version of StringBuffer. *

    * It provides basic functionality to handle dynamically-growing * char arrays as quickly as possible. This class is not threadsafe. * * @author Chris Miller */ public class CharArray { int size = 0; char[] buffer; // These properties allow us to specify a substring within the character array // that we can perform comparisons against. This is here purely for performance - // the comparisons are at the heart of the FastPageParser loop and any speed increase // we can get at this level has a huge impact on performance. int subStrStart = 0; int subStrLen = 0; /** * Constructs a CharArray that is initialized to the specified size. * * Do not pass in a negative value because there is no bounds checking! */ public CharArray(int size) { buffer = new char[size]; } /** * Returns a String represenation of the character array. */ public String toString() { return new String(buffer, 0, size); } /** * Returns the character that is at the specified position in the array. * * There is no bounds checking on this method so be sure to pass in a * sensible value. */ public char charAt(int pos) { return buffer[pos]; } /** * Changes the size of the character array to the value specified. * * If the new size is less than the current size, the data in the * internal array will be truncated. If the new size is <= 0, * the array will be reset to empty (but, unlike StringBuffer, the * internal array will NOT be shrunk). If the new size is > the * current size, the array will be padded out with null characters * ('\u0000'). * * @param newSize the new size of the character array */ public void setLength(int newSize) { if (newSize < 0) { newSize = 0; } if (newSize <= size) { size = newSize; } else { if (newSize >= buffer.length) grow(newSize); // Pad the array for (; size < newSize; size++) buffer[size] = '\0'; } } /** * Returns the current length of the character array. */ public int length() { return size; } /** * Appends an existing CharArray on to this one. * * Passing in a null CharArray will result in a NullPointerException. */ public CharArray append(CharArray chars) { return append(chars.buffer, 0, chars.size); } /** * Appends the supplied characters to the end of the array. */ public CharArray append(char[] chars) { return append(chars, 0, chars.length); } public CharArray append(char[] chars, int position, int length) { int requiredSize = length + size; if (requiredSize >= buffer.length) grow(requiredSize); System.arraycopy(chars, position, buffer, size, length); size = requiredSize; return this; } /** * Appends a single character to the end of the character array. */ public CharArray append(char c) { if (buffer.length == size) grow(0); buffer[size++] = c; return this; } /** * Appends the supplied string to the end of this character array. * * Passing in a null string will result in a NullPointerException. */ public CharArray append(String str) { int requiredSize = str.length() + size; if (requiredSize >= buffer.length) grow(requiredSize); for (int i = 0; i < str.length(); i++) buffer[size + i] = str.charAt(i); size = requiredSize; return this; } /** * Returns a substring from within this character array. * * Note that NO range checking is performed! */ public String substring(int begin, int end) { return new String(buffer, begin, end - begin); } /** * Allows an arbitrary substring of this character array to be specified. * This method should be called prior to calling {@link #compareLowerSubstr(String)} * to set the range of the substring comparison. * * @param begin the starting offset into the character array. * @param end the ending offset into the character array. */ public void setSubstr(int begin, int end) { subStrStart = begin; subStrLen = end - begin; } /** * Returns the substring that was specified by the {@link #setSubstr(int, int)} call. */ public String getLowerSubstr() { for (int i = subStrStart; i < subStrStart + subStrLen; i++) buffer[i] |= 32; return new String(buffer, subStrStart, subStrLen); } /** * This compares a substring of this character array (as specified * by the {@link #setSubstr(int, int)} method call) with the supplied * string. The supplied string must be lowercase, otherwise * the comparison will fail. */ public boolean compareLowerSubstr(String lowerStr) { // Range check if (lowerStr.length() != subStrLen || subStrLen <= 0) return false; for (int i = 0; i < lowerStr.length(); i++) { // | 32 converts from ASCII uppercase to ASCII lowercase if ((buffer[subStrStart + i] | 32) != lowerStr.charAt(i)) return false; } return true; } /** * Returns the hashcode for a lowercase version of the array's substring * (as set by the {@link #setSubstr(int, int)} method). * * This uses the same calculation as the String.hashCode() method * so that it remains compatible with the hashcodes of normal strings. */ public int substrHashCode() { int hash = 0; int offset = subStrStart; for (int i = 0; i < subStrLen; i++) { hash = 31 * hash + (buffer[offset++] | 32); } return hash; } /** * Compares the supplied uppercase string with the contents of * the character array, starting at the offset specified. * * This is a specialized method to help speed up the FastPageParser * slightly. *

    * The supplied string is assumed to contain only uppercase ASCII * characters. The offset indicates the offset into the character * array that the comparison should start from. *

    * If (and only if) the supplied string and the relevant portion of the * character array are considered equal, this method will return true. */ public boolean compareLower(String lowerStr, int offset) { // Range check if (offset < 0 || offset + lowerStr.length() > size) return false; for (int i = 0; i < lowerStr.length(); i++) { // | 32 converts from ASCII uppercase to ASCII lowercase if ((buffer[offset + i] | 32) != lowerStr.charAt(i)) return false; } return true; } /** * Grows the internal array by either ~100% or minSize (whichever is larger), * up to a maximum size of Integer.MAX_VALUE. */ private final void grow(int minSize) { int newCapacity = (buffer.length + 1) * 2; if (newCapacity < 0) { newCapacity = Integer.MAX_VALUE; } else if (minSize > newCapacity) { newCapacity = minSize; } char newBuffer[] = new char[newCapacity]; System.arraycopy(buffer, 0, newBuffer, 0, size); buffer = newBuffer; } /** * Clear the contents. */ public final void clear() { size = 0; } public void writeTo(PrintWriter writer) { writer.write(buffer, 0, size); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/StateTransitionRule.java0000644000175000017500000000173610211673542033121 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; public class StateTransitionRule extends BasicRule { private final State newState; private final boolean writeEnclosingTag; private State lastState; public StateTransitionRule(String tagName, State newState) { this(tagName, newState, true); } public StateTransitionRule(String tagName, State newState, boolean writeEnclosingTag) { super(tagName); this.newState = newState; this.writeEnclosingTag = writeEnclosingTag; } public void process(Tag tag) { if (tag.getType() == Tag.OPEN) { lastState = context.currentState(); context.changeState(newState); newState.addRule(this); } else if (tag.getType() == Tag.CLOSE && lastState != null) { context.changeState(lastState); lastState = null; } if (writeEnclosingTag) { tag.writeTo(context.currentBuffer()); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/BlockExtractingRule.java0000644000175000017500000000260710550416146033050 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import com.opensymphony.module.sitemesh.html.util.CharArray; public abstract class BlockExtractingRule extends BasicRule { private boolean includeEnclosingTags; // we should only handle tags that have been opened previously. // else the parser throws a NoSuchElementException (SIM-216) private boolean seenOpeningTag; protected BlockExtractingRule(boolean includeEnclosingTags, String acceptableTagName) { super(acceptableTagName); this.includeEnclosingTags = includeEnclosingTags; } protected BlockExtractingRule(boolean includeEnclosingTags) { this.includeEnclosingTags = includeEnclosingTags; } public void process(Tag tag) { if (tag.getType() == Tag.OPEN) { if (includeEnclosingTags) { tag.writeTo(context.currentBuffer()); } context.pushBuffer(createBuffer()); start(tag); seenOpeningTag = true; } else if (tag.getType() == Tag.CLOSE && seenOpeningTag) { end(tag); context.popBuffer(); if (includeEnclosingTags) { tag.writeTo(context.currentBuffer()); } } } protected void start(Tag tag) { } protected void end(Tag tag) { } protected CharArray createBuffer() { return new CharArray(512); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/StateChangeListener.java0000644000175000017500000000016010131001216033000 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; public interface StateChangeListener { void stateFinished(); } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/HTMLProcessor.java0000644000175000017500000000721310272511404031571 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer; import com.opensymphony.module.sitemesh.html.tokenizer.TokenHandler; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.util.CharArrayWriter; import java.io.Reader; import java.io.Writer; //import java.io.CharArrayWriter; import java.io.IOException; public class HTMLProcessor { private final char[] in; private final CharArray out; private final State defaultState = new State(); private State currentState = defaultState; private Writer outStream; public HTMLProcessor(char[] in, CharArray out) { this.in = in; this.out = out; } public HTMLProcessor(Reader in, Writer out) throws IOException { CharArrayWriter inBuffer = new CharArrayWriter(); char[] buffer = new char[2048]; int n; while (-1 != (n = in.read(buffer))) { inBuffer.write(buffer, 0, n); } this.in = inBuffer.toCharArray(); this.out = new CharArray(2048); this.outStream = out; } public State defaultState() { return defaultState; } /** * Equivalent of htmlProcessor.defaultState().addRule() */ public void addRule(TagRule rule) { defaultState.addRule(rule); } public void process() throws IOException { TagTokenizer tokenizer = new TagTokenizer(in); final HTMLProcessorContext context = new HTMLProcessorContext() { public State currentState() { return currentState; } public void changeState(State newState) { currentState = newState; } private CharArray[] buffers = new CharArray[10]; private int size; public void pushBuffer(CharArray buffer) { if(size == buffers.length) { CharArray[] newBuffers = new CharArray[buffers.length * 2]; System.arraycopy(buffers, 0, newBuffers, 0, buffers.length); buffers = newBuffers; } buffers[size++] = buffer; } public CharArray currentBuffer() { return buffers[size - 1]; } public CharArray popBuffer() { CharArray last = buffers[size - 1]; buffers[--size] = null; return last; } public void mergeBuffer() { CharArray top = buffers[size - 1]; CharArray nextDown = buffers[size - 2]; nextDown.append(top); } }; context.pushBuffer(out); tokenizer.start(new TokenHandler() { public boolean shouldProcessTag(String name) { return currentState.shouldProcessTag(name.toLowerCase()); } public void tag(Tag tag) { TagRule tagRule = currentState.getRule(tag.getName().toLowerCase()); tagRule.setContext(context); tagRule.process(tag); } public void text(Text text) { currentState.handleText(text, context); } public void warning(String message, int line, int column) { // TODO // System.out.println(line + "," + column + ": " + message); } }); defaultState.endOfState(); if (outStream != null) { outStream.write(out.toString()); } } public void addTextFilter(TextFilter textFilter) { currentState.addTextFilter(textFilter); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/html/CustomTag.java0000644000175000017500000002223510456125666031053 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.html; import java.util.Arrays; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.html.tokenizer.Parser; /** * A CustomTag provides a mechanism to manipulate the contents of a Tag. The standard Tag implementations * are immutable, however CustomTag allows a copy to be taken of an immutable Tag that can then be manipulated. * * @see Tag * * @author Joe Walnes */ public class CustomTag implements Tag { private String[] attributes = new String[10]; // name1, value1, name2, value2... private int attributeCount = 0; private String name; private int type; /** * Type of tag:
    * <blah> - Tag.OPEN
    * </blah> - Tag.CLOSE
    * <blah/> - Tag.EMPTY
    */ public CustomTag(String name, int type) { setName(name); setType(type); } /** * Create a CustomTag based on an existing Tag - this takes a copy of the Tag. */ public CustomTag(Tag tag) { setName(tag.getName()); setType(tag.getType()); if(tag instanceof Parser.ReusableToken) { Parser.ReusableToken orig = (Parser.ReusableToken)tag; attributeCount = orig.attributeCount; attributes = new String[attributeCount]; System.arraycopy(orig.attributes, 0, attributes, 0, attributeCount); } else if(tag instanceof CustomTag) { CustomTag orig = (CustomTag)tag; attributeCount = orig.attributeCount; attributes = new String[attributeCount]; System.arraycopy(orig.attributes, 0, attributes, 0, attributeCount); } else { int c = tag.getAttributeCount(); attributes = new String[c * 2]; for (int i = 0; i < c; i++) { attributes[attributeCount++] = tag.getAttributeName(i); attributes[attributeCount++] = tag.getAttributeValue(i); } } } public String getContents() { CharArray c = new CharArray(64); writeTo(c); return c.toString(); } public void writeTo(CharArray out) { if (type == Tag.CLOSE) { out.append(""); } else { out.append('>'); } } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof CustomTag)) return false; final CustomTag customTag = (CustomTag) o; if (type != customTag.type) return false; if (attributes != null ? !Arrays.equals(attributes, customTag.attributes) : customTag.attributes != null) return false; if (name != null ? !name.equals(customTag.name) : customTag.name != null) return false; return true; } public int hashCode() { int result = (attributes != null ? attributes.hashCode() : 0); result = 29 * result + (name != null ? name.hashCode() : 0); result = 29 * result + type; return result; } public String toString() { return getContents(); } // ---------- Standard methods to implement Tag interface ------ public int getAttributeCount() { return attributeCount / 2; } public int getAttributeIndex(String name, boolean caseSensitive) { if (attributes == null) { return -1; } final int len = attributeCount; for (int i = 0; i < len; i += 2) { final String current = attributes[i]; if (caseSensitive ? name.equals(current) : name.equalsIgnoreCase(current)) { return i / 2; } } return -1; } public String getAttributeName(int index) { return attributes[index * 2]; } public String getAttributeValue(int index) { return attributes[index * 2 + 1]; } public String getAttributeValue(String name, boolean caseSensitive) { int attributeIndex = getAttributeIndex(name, caseSensitive); if (attributeIndex == -1) { return null; } else { return attributes[attributeIndex * 2 + 1]; } } public boolean hasAttribute(String name, boolean caseSensitive) { return getAttributeIndex(name, caseSensitive) > -1; } public String getName() { return name; } /** * Type of tag:
    * <blah> - Tag.OPEN
    * </blah> - Tag.CLOSE
    * <blah/> - Tag.EMPTY
    */ public int getType() { return type; } // ----------- Additional methods for changing a tag ----------- /** * Change the name of the attribute. */ public void setName(String name) { if (name == null || name.length() == 0) { throw new IllegalArgumentException("CustomTag requires a name"); } else { this.name = name; } } /** * Change the type of the tag. * * Type of tag:
    * <blah> - Tag.OPEN
    * </blah> - Tag.CLOSE
    * <blah/> - Tag.EMPTY
    */ public void setType(int type) { if (type == Tag.OPEN || type == Tag.CLOSE || type == Tag.EMPTY) { this.type = type; } else { throw new IllegalArgumentException("CustomTag must be of type Tag.OPEN, Tag.CLOSE or Tag.EMPTY - was " + type); } } private void growAttributes() { int newSize = attributes.length == 0 ? 4 : attributes.length * 2; String[] newAttributes = new String[newSize]; System.arraycopy(attributes, 0, newAttributes, 0, attributes.length); attributes = newAttributes; } /** * Add a new attribute. This does not check for the existence of an attribute with the same name, * thus allowing duplicate attributes. * * @param name Name of attribute to change. * @param value New value of attribute or null for an HTML style empty attribute. * @return Index of new attribute. */ public int addAttribute(String name, String value) { if(attributeCount == attributes.length) { growAttributes(); } attributes[attributeCount++] = name; attributes[attributeCount++] = value; return (attributeCount / 2) - 1; } /** * Change the value of an attribute, or add an attribute if it does not already exist. * * @param name Name of attribute to change. * @param caseSensitive Whether the name should be treated as case sensitive when searching for an existing value. * @param value New value of attribute or null for an HTML style empty attribute. */ public void setAttributeValue(String name, boolean caseSensitive, String value) { int attributeIndex = getAttributeIndex(name, caseSensitive); if (attributeIndex == -1) { addAttribute(name, value); } else { attributes[attributeIndex * 2 + 1] = value; } } /** * Change the name of an existing attribute. */ public void setAttributeName(int attributeIndex, String name) { attributes[attributeIndex * 2] = name; } /** * Change the value of an existing attribute. The value may be null for an HTML style empty attribute. */ public void setAttributeValue(int attributeIndex, String value) { attributes[(attributeIndex * 2) + 1] = value; } /** * Remove an attribute. */ public void removeAttribute(int attributeIndex) { if(attributeIndex > attributeCount / 2) { throw new ArrayIndexOutOfBoundsException("Cannot remove attribute at index " + attributeIndex + ", max index is " + attributeCount/2); } //shift everything down one and null the last two String[] newAttributes = new String[attributes.length - 2]; System.arraycopy(attributes, 0, newAttributes, 0, attributeIndex * 2); int next = (attributeIndex * 2) + 2; System.arraycopy(attributes, next, newAttributes, attributeIndex * 2, attributes.length - next); attributeCount = attributeCount - 2; attributes = newAttributes; } /** * Change the value of an attribute, or add an attribute if it does not already exist. * * @param name Name of attribute to remove. * @param caseSensitive Whether the name should be treated as case sensitive. */ public void removeAttribute(String name, boolean caseSensitive) { int attributeIndex = getAttributeIndex(name, caseSensitive); if (attributeIndex == -1) { throw new IllegalArgumentException("Attribute " + name + " not found"); } else { removeAttribute(attributeIndex); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/0000755000175000017500000000000011157157202026614 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/tokenizer/0000755000175000017500000000000011157130036030622 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/rules/0000755000175000017500000000000011157130036027742 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/HTMLPageParser.java0000644000175000017500000000660710520674306032210 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.html.HTMLProcessor; import com.opensymphony.module.sitemesh.html.State; import com.opensymphony.module.sitemesh.html.StateTransitionRule; import com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.html.rules.BodyTagRule; import com.opensymphony.module.sitemesh.html.rules.ContentBlockExtractingRule; import com.opensymphony.module.sitemesh.html.rules.FramesetRule; import com.opensymphony.module.sitemesh.html.rules.HeadExtractingRule; import com.opensymphony.module.sitemesh.html.rules.HtmlAttributesRule; import com.opensymphony.module.sitemesh.html.rules.MSOfficeDocumentPropertiesRule; import com.opensymphony.module.sitemesh.html.rules.MetaTagRule; import com.opensymphony.module.sitemesh.html.rules.ParameterExtractingRule; import com.opensymphony.module.sitemesh.html.rules.TitleExtractingRule; import com.opensymphony.module.sitemesh.html.rules.PageBuilder; import java.io.IOException; /** *

    Builds an HTMLPage object from an HTML document. This behaves * similarly to the FastPageParser, however it's a complete rewrite that is simpler to add custom features to such as * extraction and transformation of elements.

    * *

    To customize the rules used, this class can be extended and have the userDefinedRules() methods overridden.

    * * @author Joe Walnes * * @see HTMLProcessor */ public class HTMLPageParser implements PageParser { public Page parse(char[] data) throws IOException { CharArray head = new CharArray(64); CharArray body = new CharArray(4096); TokenizedHTMLPage page = new TokenizedHTMLPage(data, body, head); HTMLProcessor processor = new HTMLProcessor(data, body); State html = processor.defaultState(); // Core rules for SiteMesh to be functional. html.addRule(new HeadExtractingRule(head)); // contents of html.addRule(new BodyTagRule(page, body)); // contents of html.addRule(new TitleExtractingRule(page)); // the html.addRule(new FramesetRule(page)); // if the page is a frameset // Additional rules - designed to be tweaked. addUserDefinedRules(html, page); processor.process(); return page; } protected void addUserDefinedRules(State html, PageBuilder page) { // Ensure that while in <xml> tag, none of the other rules kick in. // For example <xml><book><title>hello should not change the affect the title of the page. State xml = new State(); html.addRule(new StateTransitionRule("xml", xml)); // Useful properties html.addRule(new HtmlAttributesRule(page)); // attributes in element html.addRule(new MetaTagRule(page)); // all tags html.addRule(new ParameterExtractingRule(page)); // blocks html.addRule(new ContentBlockExtractingRule(page)); // blocks // Capture properties written to documents by MS Office (author, version, company, etc). // Note: These properties are from the xml state, not the html state. xml.addRule(new MSOfficeDocumentPropertiesRule(page)); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/AbstractPage.java0000644000175000017500000001370410324611374032024 0ustar twernertwerner/* * Title: AbstractPage * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * Abstract implementation of {@link com.opensymphony.module.sitemesh.Page} . * *

    Contains base methods for storing and accessing page properties. * Also stores {@link #pageData} as byte[] and implements write???() * methods.

    * *

    Concrete implementations need only set the {@link #pageData} and * call {@link #addProperty(java.lang.String,java.lang.String)} to * add all the required information.

    * * @author Joe Walnes * @version $Revision: 1.6 $ * * @see com.opensymphony.module.sitemesh.Page */ public abstract class AbstractPage implements Page { /** * Map of all properties. * Key is String. Value is java.util.List of multiple String values. */ private final Map properties = new HashMap(); /** Date of page contents. */ protected char[] pageData = new char[0]; /** RequestURI of original Page. */ private HttpServletRequest request; public void writePage(Writer out) throws IOException { out.write(pageData); } public String getPage() { try { StringWriter writer = new StringWriter(); writePage(writer); return writer.toString(); } catch (IOException e) { throw new IllegalStateException("Could not get page " + e.getMessage()); } } /** * Write data of html <body> tag. * *

    Must be implemented. Data written should not actually contain the * body tags, but all the data in between. */ public abstract void writeBody(Writer out) throws IOException; public String getBody() { try { StringWriter writer = new StringWriter(); writeBody(writer); return writer.toString(); } catch (IOException e) { throw new IllegalStateException("Could not get body " + e.getMessage()); } } /** Return title of from "title" property. Never returns null. */ public String getTitle() { return noNull(getProperty("title")); } public int getContentLength() { try { //todo - this needs to be fixed properly (SIM-196) return new String(pageData).getBytes("UTF-8").length; // we cannot just measure pageData.length, due to i18n issues (SIM-157) } catch (UnsupportedEncodingException e) { return new String(pageData).getBytes().length; } } public String getProperty(String name) { if (!isPropertySet(name)) return null; return (String)properties.get(name); } public int getIntProperty(String name) { try { return Integer.parseInt(noNull(getProperty(name))); } catch (NumberFormatException e) { return 0; } } public long getLongProperty(String name) { try { return Long.parseLong(noNull(getProperty(name))); } catch (NumberFormatException e) { return 0; } } public boolean getBooleanProperty(String name) { String property = getProperty(name); if (property == null || property.trim().length() == 0) return false; switch (property.charAt(0)) { case '1': case 't': case 'T': case 'y': case 'Y': return true; default: return false; } } public boolean isPropertySet(String name) { return properties.containsKey(name); } public String[] getPropertyKeys() { synchronized(properties) { Set keys = properties.keySet(); return (String[])keys.toArray(new String[keys.size()]); } } public Map getProperties() { return properties; } /** @see com.opensymphony.module.sitemesh.Page#getRequest() */ public HttpServletRequest getRequest() { return request; } /** * Create snapshot of Request. * * @see com.opensymphony.module.sitemesh.Page#getRequest() */ public void setRequest(HttpServletRequest request) { this.request = new PageRequest(request); } /** * Add a property to the properties list. * * @param name Name of property * @param value Value of property */ public void addProperty(String name, String value) { properties.put(name, value); } /** Return String as is, or "" if null. (Prevents NullPointerExceptions) */ protected static String noNull(String in) { return in == null ? "" : in; } } class PageRequest extends HttpServletRequestWrapper { private String requestURI, method, pathInfo, pathTranslated, queryString, servletPath; public PageRequest(HttpServletRequest request) { super(request); requestURI = request.getRequestURI(); method = request.getMethod(); pathInfo = request.getPathInfo(); pathTranslated = request.getPathTranslated(); queryString = request.getQueryString(); servletPath = request.getServletPath(); } public String getRequestURI() { return requestURI; } public String getMethod() { return method; } public String getPathInfo() { return pathInfo; } public String getPathTranslated() { return pathTranslated; } public String getQueryString() { return queryString; } public String getServletPath() { return servletPath; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/TokenizedHTMLPage.java0000644000175000017500000000241410276421210032670 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.html.rules.PageBuilder; import java.io.IOException; import java.io.Writer; /** * HTMLPage implementation that builds itself based on the incoming 'tag' and 'text' tokens fed to it from the * HTMLTagTokenizer. * * @see com.opensymphony.module.sitemesh.parser.HTMLPageParser * @see com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer * * @author Joe Walnes */ public class TokenizedHTMLPage extends AbstractHTMLPage implements PageBuilder { private CharArray body; private CharArray head; public TokenizedHTMLPage(char[] original, CharArray body, CharArray head) { this.pageData = original; this.body = body; this.head = head; addProperty("title", ""); } public void writeHead(Writer out) throws IOException { out.write(head.toString()); } public void writeBody(Writer out) throws IOException { out.write(body.toString()); } public String getHead() { return head.toString(); } public String getBody() { return body.toString(); } public String getPage() { return new String(pageData); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/FastPageParser.java0000644000175000017500000007374210520674306032345 0ustar twernertwerner/* * Title: FastPageParser * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.html.util.CharArray; import com.opensymphony.module.sitemesh.util.CharArrayReader; import java.io.IOException; import java.io.Reader; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * Very fast PageParser implementation for parsing HTML. * *

    Produces FastPage.

    * * @author Victor Salaman * @version $Revision: 1.13 $ * @deprecated Use HTMLPageParser instead - it performs better and is more extensible. */ public final class FastPageParser implements PageParser { private static final int TOKEN_NONE = -0; private static final int TOKEN_EOF = -1; private static final int TOKEN_TEXT = -2; private static final int TOKEN_TAG = -3; private static final int TOKEN_COMMENT = -4; private static final int TOKEN_CDATA = -5; private static final int TOKEN_SCRIPT = -6; private static final int TOKEN_DOCTYPE = -7; private static final int TOKEN_EMPTYTAG = -8; private static final int STATE_EOF = -1; private static final int STATE_TEXT = -2; private static final int STATE_TAG = -3; private static final int STATE_COMMENT = -4; private static final int STATE_TAG_QUOTE = -5; private static final int STATE_CDATA = -6; private static final int STATE_SCRIPT = -7; private static final int STATE_DOCTYPE = -8; private static final int TAG_STATE_NONE = 0; private static final int TAG_STATE_HTML = -1; private static final int TAG_STATE_HEAD = -2; private static final int TAG_STATE_TITLE = -3; private static final int TAG_STATE_BODY = -4; private static final int TAG_STATE_XML = -6; private static final int TAG_STATE_XMP = -7; // These hashcodes are hardcoded because swtich statements can only // switch on compile-time constants. // In theory it is possible for there to be a hashcode collision with // other HTML tags, however in practice it is *very* unlikely because // tags are generally only a few characters long and hence are likely // to produce unique values. private static final int SLASH_XML_HASH = 1518984; // "/xml".hashCode(); private static final int XML_HASH = 118807; // "xml".hashCode(); private static final int SLASH_XMP_HASH = 1518988; // "/xmp".hashCode(); private static final int XMP_HASH = 118811; // "xmp".hashCode(); private static final int HTML_HASH = 3213227; // "html".hashCode(); private static final int SLASH_HTML_HASH = 46618714; // "/html".hashCode(); private static final int HEAD_HASH = 3198432; // "head".hashCode(); private static final int TITLE_HASH = 110371416; // "title".hashCode(); private static final int SLASH_TITLE_HASH = 1455941513; // "/title".hashCode(); private static final int PARAMETER_HASH = 1954460585; // "parameter".hashCode(); private static final int META_HASH = 3347973; // "meta".hashCode(); private static final int SLASH_HEAD_HASH = 46603919; // "/head".hashCode(); private static final int FRAMESET_HASH = -1644953643; // "frameset".hashCode(); private static final int FRAME_HASH = 97692013; // "frame".hashCode(); private static final int BODY_HASH = 3029410; // "body".hashCode(); private static final int SLASH_BODY_HASH = 46434897; // "/body".hashCode(); private static final int CONTENT_HASH = 951530617; // "content".hashCode(); public Page parse(char[] data) throws IOException { FastPage page = internalParse(new CharArrayReader(data)); page.setVerbatimPage(data); return page; } public Page parse(Reader reader) { return internalParse(reader); } private FastPage internalParse(Reader reader) { CharArray _buffer = new CharArray(4096); CharArray _body = new CharArray(4096); CharArray _head = new CharArray(512); CharArray _title = new CharArray(128); Map _htmlProperties = null; Map _metaProperties = new HashMap(6); Map _sitemeshProperties = new HashMap(6); Map _bodyProperties = null; CharArray _currentTaggedContent = new CharArray(1024); String _contentTagId = null; boolean tagged = false; boolean _frameSet = false; int _state = STATE_TEXT; int _tokenType = TOKEN_NONE; int _pushBack = 0; int _comment = 0; int _quote = 0; boolean hide = false; int state = TAG_STATE_NONE; int laststate = TAG_STATE_NONE; boolean doneTitle = false; // This tag object gets reused each iteration. Tag tagObject = new Tag(); while (_tokenType != TOKEN_EOF) { if(tagged) { if(_tokenType == TOKEN_TAG || _tokenType == TOKEN_EMPTYTAG) { if(_buffer==null || _buffer.length()==0) { _tokenType=TOKEN_NONE; continue; } if (parseTag(tagObject, _buffer) == null) continue; if (_buffer.compareLowerSubstr("/content")) // Note that the '/' survives the | 32 operation { tagged = false; if(_contentTagId != null) { state = TAG_STATE_NONE; _sitemeshProperties.put(_contentTagId, _currentTaggedContent.toString()); _currentTaggedContent.setLength(0); _contentTagId = null; } } else { _currentTaggedContent.append('<').append(_buffer).append('>'); } } else { if(_buffer.length() > 0) _currentTaggedContent.append(_buffer); } } else { if(_tokenType == TOKEN_TAG || _tokenType == TOKEN_EMPTYTAG) { if(_buffer==null || _buffer.length()==0) { _tokenType=TOKEN_NONE; continue; } if(parseTag(tagObject, _buffer) == null) { _tokenType=TOKEN_TEXT; continue; } int tagHash = _buffer.substrHashCode(); if(state == TAG_STATE_XML || state == TAG_STATE_XMP) { writeTag(state, laststate, hide, _head, _buffer, _body); if( (state == TAG_STATE_XML && tagHash == SLASH_XML_HASH) ||(state == TAG_STATE_XMP && tagHash == SLASH_XMP_HASH) ) { state = laststate; } } else { boolean doDefault = false; switch (tagHash) { case HTML_HASH: if (!_buffer.compareLowerSubstr("html")) { // skip any accidental hash collisions doDefault = true; break; } state = TAG_STATE_HTML; _htmlProperties = parseProperties(tagObject, _buffer).properties; break; case HEAD_HASH: if (!_buffer.compareLowerSubstr("head")) { // skip any accidental hash collisions doDefault = true; break; } state = TAG_STATE_HEAD; break; case XML_HASH: if (!_buffer.compareLowerSubstr("xml")) { // skip any accidental hash collisions doDefault = true; break; } laststate = state; writeTag(state, laststate, hide, _head, _buffer, _body); state = TAG_STATE_XML; break; case XMP_HASH: if (!_buffer.compareLowerSubstr("xmp")) { // skip any accidental hash collisions doDefault = true; break; } laststate = state; writeTag(state, laststate, hide, _head, _buffer, _body); state = TAG_STATE_XMP; break; case TITLE_HASH: if (!_buffer.compareLowerSubstr("title")) { // skip any accidental hash collisions doDefault = true; break; } if (doneTitle) { hide = true; } else { laststate = state; state = TAG_STATE_TITLE; } break; case SLASH_TITLE_HASH: if (!_buffer.compareLowerSubstr("/title")) { // skip any accidental hash collisions doDefault = true; break; } if (doneTitle) { hide = false; } else { doneTitle = true; state = laststate; } break; case PARAMETER_HASH: if (!_buffer.compareLowerSubstr("parameter")) { // skip any accidental hash collisions doDefault = true; break; } parseProperties(tagObject, _buffer); String name = (String) tagObject.properties.get("name"); String value = (String) tagObject.properties.get("value"); if (name != null && value != null) { _sitemeshProperties.put(name, value); } break; case META_HASH: if (!_buffer.compareLowerSubstr("meta")) { // skip any accidental hash collisions doDefault = true; break; } CharArray metaDestination = state == TAG_STATE_HEAD ? _head : _body; metaDestination.append('<'); metaDestination.append(_buffer); metaDestination.append('>'); parseProperties(tagObject, _buffer); name = (String) tagObject.properties.get("name"); value = (String) tagObject.properties.get("content"); if (name == null) { String httpEquiv = (String) tagObject.properties.get("http-equiv"); if (httpEquiv != null) { name = "http-equiv." + httpEquiv; } } if (name != null && value != null) { _metaProperties.put(name, value); } break; case SLASH_HEAD_HASH: if (!_buffer.compareLowerSubstr("/head")) { // skip any accidental hash collisions doDefault = true; break; } state = TAG_STATE_HTML; break; case FRAME_HASH: if (!_buffer.compareLowerSubstr("frame")) { // skip any accidental hash collisions doDefault = true; break; } _frameSet = true; break; case FRAMESET_HASH: if (!_buffer.compareLowerSubstr("frameset")) { // skip any accidental hash collisions doDefault = true; break; } _frameSet = true; break; case BODY_HASH: if (!_buffer.compareLowerSubstr("body")) { // skip any accidental hash collisions doDefault = true; break; } if (_tokenType == TOKEN_EMPTYTAG) { state = TAG_STATE_BODY; } _bodyProperties = parseProperties(tagObject, _buffer).properties; break; case CONTENT_HASH: if (!_buffer.compareLowerSubstr("content")) { // skip any accidental hash collisions doDefault = true; break; } state = TAG_STATE_NONE; Map props = parseProperties(tagObject, _buffer).properties; if (props != null) { tagged = true; _contentTagId = (String) props.get("tag"); } break; case SLASH_XMP_HASH: if (!_buffer.compareLowerSubstr("/xmp")) { // skip any accidental hash collisions doDefault = true; break; } hide = false; break; case SLASH_BODY_HASH: if (!_buffer.compareLowerSubstr("/body")) { // skip any accidental hash collisions doDefault = true; break; } state = TAG_STATE_NONE; hide = true; break; case SLASH_HTML_HASH: if (!_buffer.compareLowerSubstr("/html")) { // skip any accidental hash collisions doDefault = true; break; } state = TAG_STATE_NONE; hide = true; break; default: doDefault = true; } if (doDefault) writeTag(state, laststate, hide, _head, _buffer, _body); } } else if (!hide) { if (_tokenType == TOKEN_TEXT) { if (state == TAG_STATE_TITLE) { _title.append(_buffer); } else if (shouldWriteToHead(state, laststate)) { _head.append(_buffer); } else { _body.append(_buffer); } } else if (_tokenType == TOKEN_COMMENT) { final CharArray commentDestination = shouldWriteToHead(state, laststate) ? _head : _body; commentDestination.append(""); } else if (_tokenType == TOKEN_CDATA) { final CharArray commentDestination = state == TAG_STATE_HEAD ? _head : _body; commentDestination.append(""); } else if (_tokenType == TOKEN_SCRIPT) { final CharArray commentDestination = state == TAG_STATE_HEAD ? _head : _body; commentDestination.append('<'); commentDestination.append(_buffer); } } } _buffer.setLength(0); start: while (true) { int c; if(_pushBack != 0) { c = _pushBack; _pushBack = 0; } else { try { c = reader.read(); } catch(IOException e) { _tokenType = TOKEN_EOF; break start; } } if(c < 0) { int tmpstate = _state; _state = STATE_EOF; if(_buffer.length() > 0 && tmpstate == STATE_TEXT) { _tokenType = TOKEN_TEXT; break start; } else { _tokenType = TOKEN_EOF; break start; } } switch(_state) { case STATE_TAG: { int buflen = _buffer.length(); if(c == '>') { if (_buffer.length() > 1 && _buffer.charAt(_buffer.length() - 1) == '/') { _tokenType = TOKEN_EMPTYTAG; } else { _tokenType = TOKEN_TAG; } _state = STATE_TEXT; break start; } else if(c == '/') { _buffer.append('/'); } else if(c == '<' && buflen == 0) { _buffer.append("<<"); _state = STATE_TEXT; } else if(c == '-' && buflen == 2 && _buffer.charAt(1) == '-' && _buffer.charAt(0) == '!') { _buffer.setLength(0); _state = STATE_COMMENT; } else if(c == '[' && buflen == 7 && _buffer.charAt(0) == '!' && _buffer.charAt(1) == '[' && _buffer.compareLower("cdata", 2)) { _buffer.setLength(0); _state = STATE_CDATA; } else if((c == 'e' || c == 'E') && buflen == 7 && _buffer.charAt(0) == '!' && _buffer.compareLower("doctyp", 1)) { _buffer.append((char)c); _state = STATE_DOCTYPE; } else if((c == 'T' || c == 't') && buflen == 5 && _buffer.compareLower("scrip", 0)) { _buffer.append((char)c); _state = STATE_SCRIPT; } else if(c == '"' || c == '\'') { _quote = c; _buffer.append(( char ) c); _state = STATE_TAG_QUOTE; } else { _buffer.append(( char ) c); } } break; case STATE_TEXT: { if(c == '<') { _state = STATE_TAG; if(_buffer.length() > 0) { _tokenType = TOKEN_TEXT; break start; } } else { _buffer.append(( char ) c); } } break; case STATE_TAG_QUOTE: { if(c == '>') { _pushBack = c; _state = STATE_TAG; } else { _buffer.append(( char ) c); if(c == _quote) { _state = STATE_TAG; } } } break; case STATE_COMMENT: { if(c == '>' && _comment >= 2) { _buffer.setLength(_buffer.length() - 2); _comment = 0; _state = STATE_TEXT; _tokenType = TOKEN_COMMENT; break start; } else if(c == '-') { _comment++; } else { _comment = 0; } _buffer.append(( char ) c); } break; case STATE_CDATA: { if(c == '>' && _comment >= 2) { _buffer.setLength(_buffer.length() - 2); _comment = 0; _state = STATE_TEXT; _tokenType = TOKEN_CDATA; break start; } else if(c == ']') { _comment++; } else { _comment = 0; } _buffer.append(( char ) c); } break; case STATE_SCRIPT: { _buffer.append((char) c); if (c == '<') { _comment = 0; } else if ((c == '/' && _comment == 0) ||((c == 's' || c == 'S' ) && _comment == 1) ||((c == 'c' || c == 'C' ) && _comment == 2) ||((c == 'r' || c == 'R' ) && _comment == 3) ||((c == 'i' || c == 'I' ) && _comment == 4) ||((c == 'p' || c == 'P' ) && _comment == 5) ||((c == 't' || c == 'T' ) && _comment == 6) ) { _comment++; } else if(c == '>' && _comment >= 7) { _comment = 0; _state = STATE_TEXT; _tokenType = TOKEN_SCRIPT; break start; } } break; case STATE_DOCTYPE: { _buffer.append((char) c); if (c == '>') { _state = STATE_TEXT; _tokenType = TOKEN_DOCTYPE; break start; } else { _comment = 0; } } break; } } } // Help the GC _currentTaggedContent = null; _buffer = null; return new FastPage(_sitemeshProperties, _htmlProperties, _metaProperties, _bodyProperties, _title.toString().trim(), _head.toString().trim(), _body.toString().trim(), _frameSet); } private static void writeTag(int state, int laststate, boolean hide, CharArray _head, CharArray _buffer, CharArray _body) { if (!hide) { if (shouldWriteToHead(state, laststate)) { _head.append('<').append(_buffer).append('>'); } else { _body.append('<').append(_buffer).append('>'); } } } private static boolean shouldWriteToHead(int state, int laststate) { return state == TAG_STATE_HEAD ||(laststate == TAG_STATE_HEAD && (state == TAG_STATE_XML || state == TAG_STATE_XMP)); } /** * Populates a {@link Tag} object using data from the supplied {@link CharArray}. * * The supplied tag parameter is reset and reused - this avoids excess object * creation which hwlps performance. * * @return the same tag instance that was passed in, except it will be populated * with a new name value (and the corresponding nameEndIdx value). * However if the tag contained nathing but whitespace, this method will return * null. */ private Tag parseTag(Tag tag, CharArray buf) { int len = buf.length(); int idx = 0; int begin; // Skip over any leading whitespace in the tag while (idx < len && Character.isWhitespace(buf.charAt(idx))) idx++; if(idx == len) return null; // Find out where the non-whitespace characters end. This will give us the tag name. begin = idx; while (idx < len && !Character.isWhitespace(buf.charAt(idx))) idx++; // Mark the tag name as a substring within the buffer. This allows us to perform // a substring comparison against it at a later date buf.setSubstr(begin, buf.charAt(idx - 1) == '/' ? idx - 1 : idx); // Remember where the name finishes so we can pull out the properties later if need be tag.nameEndIdx = idx; return tag; } /** * This is called when we need to extract the properties for the tag from the tag's HTML. * We only call this when necessary since it has quite a lot of overhead. * * @param tag the tag that is currently being processed. This should be the * tag that was returned as a result of a call to {@link #parseTag(FastPageParser.Tag, CharArray)} * (ie, it has the name and nameEndIdx fields set correctly for the * tag in question. The properties field can be in an undefined state - it * will get replaced regardless). * @param buffer a CharArray containing the entire tag that is being parsed. * @return the same tag instance that was passed in, only it will now be populated * with any properties that were specified in the tag's HTML. */ private static Tag parseProperties(Tag tag, CharArray buffer) { int len = buffer.length(); int idx = tag.nameEndIdx; // Start with an empty hashmap. A new HashMap is lazy-created if we happen to find any properties tag.properties = Collections.EMPTY_MAP; int begin; while (idx < len) { // Skip forward to the next non-whitespace character while (idx < len && Character.isWhitespace(buffer.charAt(idx))) idx++; if(idx == len) continue; begin = idx; if(buffer.charAt(idx) == '"') { idx++; while (idx < len && buffer.charAt(idx) != '"') idx++; if(idx == len) continue; idx++; } else if(buffer.charAt(idx) == '\'') { idx++; while (idx < len && buffer.charAt(idx) != '\'') idx++; if(idx == len) continue; idx++; } else { while (idx < len && !Character.isWhitespace(buffer.charAt(idx)) && buffer.charAt(idx) != '=') idx++; } // Mark the substring. This is the attribute name buffer.setSubstr(begin, idx); if(idx < len && Character.isWhitespace(buffer.charAt(idx))) { while (idx < len && Character.isWhitespace(buffer.charAt(idx))) idx++; } if(idx == len || buffer.charAt(idx) != '=') continue; idx++; if(idx == len) continue; while(idx < len && (buffer.charAt(idx) == '\n' || buffer.charAt(idx) == '\r')) idx++; if(buffer.charAt(idx) == ' ') { while (idx < len && Character.isWhitespace(buffer.charAt(idx))) idx++; if(idx == len || (buffer.charAt(idx) != '"' && buffer.charAt(idx) != '"')) continue; } begin = idx; int end; if(buffer.charAt(idx) == '"') { idx++; begin = idx; while (idx < len && buffer.charAt(idx) != '"') idx++; if(idx == len) continue; end = idx; idx++; } else if(buffer.charAt(idx) == '\'') { idx++; begin = idx; while (idx < len && buffer.charAt(idx) != '\'') idx++; if(idx == len) continue; end = idx; idx++; } else { while (idx < len && !Character.isWhitespace(buffer.charAt(idx))) idx++; end = idx; } // Extract the name and value as String objects and add them to the property map String name = buffer.getLowerSubstr(); String value = buffer.substring(begin, end); tag.addProperty(name, value); } return tag; } private class Tag { // The index where the name string ends. This is used as the starting // offet if we need to continue processing to find the tag's properties public int nameEndIdx = 0; // This holds a map of the various properties for a particular tag. // This map is only populated when required - normally it will remain empty public Map properties = Collections.EMPTY_MAP; /** * Adds a name/value property pair to this tag. Each property that is * added represents a property that was parsed from the tag's HTML. */ public void addProperty(String name, String value) { if(properties==Collections.EMPTY_MAP) { properties = new HashMap(8); } properties.put(name, value); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/AbstractHTMLPage.java0000644000175000017500000000273210176645472032523 0ustar twernertwerner/* * Title: AbstractHTMLPage * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.HTMLPage; import java.io.IOException; import java.io.Writer; /** * Abstract implementation of {@link com.opensymphony.module.sitemesh.HTMLPage}. * *

    Adds to {@link com.opensymphony.module.sitemesh.parser.AbstractPage} some HTML methods. * To implement, follow guidelines of super-class, and implement the 2 * abstract methods states below.

    * * @author Joe Walnes * @version $Revision: 1.5 $ * * @see com.opensymphony.module.sitemesh.parser.AbstractPage * @see com.opensymphony.module.sitemesh.HTMLPage */ public abstract class AbstractHTMLPage extends AbstractPage implements HTMLPage { /** * Write data of html <head> tag. * *

    Must be implemented. Data written should not actually contain the * head tags, but all the data in between. */ public abstract void writeHead(Writer out) throws IOException; public boolean isFrameSet() { return isPropertySet("frameset") && getProperty("frameset").equalsIgnoreCase("true"); } public void setFrameSet(boolean frameset) { addProperty("frameset", frameset ? "true" : "false"); } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/html/0000755000175000017500000000000011157130036027554 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/parser/FastPage.java0000644000175000017500000000372410126462134031155 0ustar twernertwerner/* * Title: FastPage * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.parser; import java.io.IOException; import java.io.Writer; import java.util.Iterator; import java.util.Map; /** * HTMLPage implementation produced by FastPageParser. * * @author Victor Salaman * @version $Revision: 1.5 $ */ public final class FastPage extends AbstractHTMLPage { private String head; private String body; public FastPage(Map sitemeshProps, Map htmlProps, Map metaProps, Map bodyProps, String title, String head, String body, boolean frameSet) { this.head = head; this.body = body; setFrameSet(frameSet); addAttributeList("", htmlProps); addAttributeList("page.", sitemeshProps); addAttributeList("body.", bodyProps); addAttributeList("meta.", metaProps); addProperty("title", title); } public void writeHead(Writer out) throws IOException { out.write(head); } public void writeBody(Writer out) throws IOException { out.write(body); } private void addAttributeList(String prefix, Map attributes) { if(attributes == null || attributes.isEmpty()) return; String name, value; Iterator i = attributes.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); name = (String) entry.getKey(); value = (String) entry.getValue(); if(value != null && value.trim().length() > 0) { addProperty(prefix + name, value); } } } public void setVerbatimPage(char[] v) { this.pageData = v; } public String getBody() { return body; } public String getHead() { return head; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/0000755000175000017500000000000011157130036026600 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/ConfigLoader.java0000644000175000017500000003361410560506772032021 0ustar twernertwerner/* * Title: ConfigLoader * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.factory.DefaultFactory; import org.w3c.dom.*; import org.xml.sax.SAXException; import javax.servlet.ServletException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * The ConfigLoader reads a configuration XML file that contains Decorator definitions * (name, url, init-params) and path-mappings (pattern, name). * *

    These can then be accessed by the getDecoratorByName() methods and getMappedName() * methods respectively.

    * *

    The DTD for the configuration file in old (deprecated) format is located at * * http://www.opensymphony.com/dtds/sitemesh_1_0_decorators.dtd * .

    * *

    The DTD for the configuration file in new format is located at * * http://www.opensymphony.com/dtds/sitemesh_1_5_decorators.dtd * .

    * *

    Editing the config file will cause it to be auto-reloaded.

    * *

    This class is used by ConfigDecoratorMapper, and uses PathMapper for pattern matching.

    * * @author Joe Walnes * @author Mathias Bogaert * @version $Revision: 1.8 $ * * @see com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper * @see com.opensymphony.module.sitemesh.mapper.PathMapper */ public class ConfigLoader { /** * State visibile across threads stored in a single container so that we * can efficiently atomically access it with the guarantee that we wont see * a partially loaded configuration in the face of one thread reloading the * configuration while others are trying to read it. */ private static class State { /** * Timestamp of the last time we checked for an update to the * configuration file used to rate limit the frequency at which we check * for efficiency. */ long lastModificationCheck = System.currentTimeMillis(); /** * Timestamp of the modification time of the configuration file when we * generated the state. */ long lastModified; /** * Whether a thread is currently checking if the configuration file has * been modified and potentially reloading it and therefore others * shouldn't attempt the same till it's done. */ boolean checking = false; Map decorators = new HashMap(); PathMapper pathMapper = new PathMapper(); } /** * Mark volatile so that the installation of new versions is guaranteed to * be visible across threads. */ private volatile State state; private File configFile = null; private String configFileName = null; private Config config = null; /** * Create new ConfigLoader using supplied File. */ public ConfigLoader(File configFile) throws ServletException { this.configFile = configFile; this.configFileName = configFile.getName(); state = loadConfig(); } /** * Create new ConfigLoader using supplied filename and config. */ public ConfigLoader(String configFileName, Config config) throws ServletException { this.config = config; this.configFileName = configFileName; if (config.getServletContext().getRealPath(configFileName) != null) { this.configFile = new File(config.getServletContext().getRealPath(configFileName)); } state = loadConfig(); } /** * Retrieve Decorator based on name specified in configuration file. */ public Decorator getDecoratorByName(String name) throws ServletException { return (Decorator) refresh().decorators.get(name); } /** Get name of Decorator mapped to given path. */ public String getMappedName(String path) throws ServletException { return refresh().pathMapper.get(path); } /** * Load configuration from file. */ private State loadConfig() throws ServletException { // The new state which we build up and atomically replace the old state // with atomically to avoid other threads seeing partial modifications. State newState = new State(); try { // Build a document from the file DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document; if (configFile != null && configFile.canRead()) { // Keep time we read the file to check if the file was modified newState.lastModified = configFile.lastModified(); document = builder.parse(configFile); } else { document = builder.parse(config.getServletContext().getResourceAsStream(configFileName)); } // Parse the configuration document parseConfig(newState, document); return newState; } catch (ParserConfigurationException e) { throw new ServletException("Could not get XML parser", e); } catch (IOException e) { throw new ServletException("Could not read the config file: " + configFileName, e); } catch (SAXException e) { throw new ServletException("Could not parse the config file: " + configFileName, e); } catch (IllegalArgumentException e) { throw new ServletException("Could not find the config file: " + configFileName, e); } } private void parseConfig(State newState, Document document) { Element root = document.getDocumentElement(); // get the default directory for the decorators String defaultDir = getAttribute(root, "defaultdir"); if (defaultDir == null) defaultDir = getAttribute(root, "defaultDir"); // Get decorators NodeList decoratorNodes = root.getElementsByTagName("decorator"); Element decoratorElement; for (int i = 0; i < decoratorNodes.getLength(); i++) { String name, page, uriPath = null, role = null; // get the current decorator element decoratorElement = (Element) decoratorNodes.item(i); if (getAttribute(decoratorElement, "name") != null) { // The new format is used name = getAttribute(decoratorElement, "name"); page = getAttribute(decoratorElement, "page"); uriPath = getAttribute(decoratorElement, "webapp"); role = getAttribute(decoratorElement, "role"); // Append the defaultDir if (defaultDir != null && page != null && page.length() > 0 && !page.startsWith("/")) { if (page.charAt(0) == '/') page = defaultDir + page; else page = defaultDir + '/' + page; } // The uriPath must begin with a slash if (uriPath != null && uriPath.length() > 0) { if (uriPath.charAt(0) != '/') uriPath = '/' + uriPath; } // Get all ... and ... nodes and add a mapping populatePathMapper(newState, decoratorElement.getElementsByTagName("pattern"), role, name); populatePathMapper(newState, decoratorElement.getElementsByTagName("url-pattern"), role, name); } else { // NOTE: Deprecated format name = getContainedText(decoratorNodes.item(i), "decorator-name"); page = getContainedText(decoratorNodes.item(i), "resource"); // We have this here because the use of jsp-file is deprecated, but we still want // it to work. if (page == null) page = getContainedText(decoratorNodes.item(i), "jsp-file"); } Map params = new HashMap(); NodeList paramNodes = decoratorElement.getElementsByTagName("init-param"); for (int ii = 0; ii < paramNodes.getLength(); ii++) { String paramName = getContainedText(paramNodes.item(ii), "param-name"); String paramValue = getContainedText(paramNodes.item(ii), "param-value"); params.put(paramName, paramValue); } storeDecorator(newState, new DefaultDecorator(name, page, uriPath, role, params)); } // Get (deprecated format) decorator-mappings NodeList mappingNodes = root.getElementsByTagName("decorator-mapping"); for (int i = 0; i < mappingNodes.getLength(); i++) { Element n = (Element) mappingNodes.item(i); String name = getContainedText(mappingNodes.item(i), "decorator-name"); // Get all ... nodes and add a mapping populatePathMapper(newState, n.getElementsByTagName("url-pattern"), null, name); } } private void populatePathMapper(State newState, NodeList patternNodes, String role, String name) { for (int j = 0; j < patternNodes.getLength(); j++) { Element p = (Element) patternNodes.item(j); Text patternText = (Text) p.getFirstChild(); if (patternText != null) { String pattern = patternText.getData().trim(); if (pattern != null) { if (role != null) { // concatenate name and role to allow more // than one decorator per role newState.pathMapper.put(name + role, pattern); } else { newState.pathMapper.put(name, pattern); } } } } } private static String getAttribute(Element element, String name) { if (element != null && element.getAttribute(name) != null && element.getAttribute(name).trim() != "") { return element.getAttribute(name).trim(); } else { return null; } } private static String getContainedText(Node parent, String childTagName) { try { Node tag = ((Element) parent).getElementsByTagName(childTagName).item(0); return ((Text) tag.getFirstChild()).getData(); } catch (Exception e) { return null; } } private void storeDecorator(State newState, Decorator d) { if (d.getRole() != null) { newState.decorators.put(d.getName() + d.getRole(), d); } else { newState.decorators.put(d.getName(), d); } } /** * Check if configuration file has been updated, and if so, reload. */ private State refresh() throws ServletException { // Read the current state just once since another thread can swap // another version in at any time. State currentState = state; if (configFile == null) { return currentState; } // Rate limit the stat'ing of the config file to find its // modification time to once every five seconds to reduce the // number of system calls made. We grab the monitor of currentState // so that we can safely read the values shared across threads and // so that only one thread is performing the modification check at // a time. long current = System.currentTimeMillis(); long oldLastModified; boolean check = false; synchronized (currentState) { oldLastModified = currentState.lastModified; if (!currentState.checking && current >= currentState.lastModificationCheck + DefaultFactory.configCheckMillis) { currentState.lastModificationCheck = current; currentState.checking = true; check = true; } } if (check) { // Perform the file stat'ing system call without holding a lock // on the current state. State newState = null; try { long currentLastModified = configFile.lastModified(); if (currentLastModified != oldLastModified) { // The configuration file has been modified since we last // read it so reload the configuration without holding a // lock on the current state and then slam down the new // state for other threads to see. The State.checking flag // being set on currentState will prevent other threads // from attempting to reload the state while we are and // the new state will have the flag cleared so that we can // continue checking if the configuration file is modified. newState = loadConfig(); state = newState; return newState; } } finally { // In the event of a failure of the modification time check, // or while reloading the configuration file, mark that we're no // longer checking if the modification time or reloading so that // we'll retry. if (newState == null) { synchronized (currentState) { currentState.checking = false; } } } } return currentState; } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/ParameterDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/ParameterDecoratorMapper.j0000644000175000017500000000553310162346630033715 0ustar twernertwerner/* * Title: ParameterDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * The ParameterDecoratorMapper will map a suitable decorator based on request * parameters. * *

    The ParameterDecoratorMapper is configured via three properties.

    * *

    decorator.parameter - the parameter which contains the name of the decorator which will be mapped. * The default is "decorator".

    * *

    For example if decorator.parameter is "foobar" then * myurl.jsp?foobar=mydecorator will map to the decorator named "mydecorator".

    * *

    You can also supply an optional 'confirmation parameter'. * The decorator will only be mapped if the parameter named parameter.name is * in the request URI and the value of that parameter is equal to the * parameter.value property.

    * *

    For example assuming parameter.name=confirm and parameter.value=true * the URI myurl.jsp?decorator=mydecorator&confirm=true will map the decorator mydecorator. * where as the URIs myurl.jsp?decorator=mydecorator and myurl.jsp?decorator=mydecorator&confirm=false will * not return any decorator.

    * * @author Mike Cannon-Brookes * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class ParameterDecoratorMapper extends AbstractDecoratorMapper { private String decoratorParameter = null, paramName = null, paramValue = null; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); decoratorParameter = properties.getProperty("decorator.parameter", "decorator"); paramName = properties.getProperty("parameter.name", null); paramValue = properties.getProperty("parameter.value", null); } public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; String decoratorParamValue = request.getParameter(decoratorParameter); if ((paramName == null || paramValue.equals(request.getParameter(paramName))) && decoratorParamValue != null && !decoratorParamValue.trim().equals("")) { result = getNamedDecorator(request, decoratorParamValue); } return result == null ? super.getDecorator(request, page) : result; } }././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/ConfigDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/ConfigDecoratorMapper.java0000644000175000017500000000710010264343650033664 0ustar twernertwerner/* * Title: ConfigDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * Default implementation of DecoratorMapper. Reads decorators and * mappings from the config property (default '/WEB-INF/decorators.xml'). * * @author Joe Walnes * @author Mike Cannon-Brookes * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper * @see com.opensymphony.module.sitemesh.mapper.DefaultDecorator * @see com.opensymphony.module.sitemesh.mapper.ConfigLoader */ public class ConfigDecoratorMapper extends AbstractDecoratorMapper { private ConfigLoader configLoader = null; /** Create new ConfigLoader using '/WEB-INF/decorators.xml' file. */ public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); try { String fileName = properties.getProperty("config", "/WEB-INF/decorators.xml"); configLoader = new ConfigLoader(fileName, config); } catch (Exception e) { throw new InstantiationException(e.toString()); } } /** Retrieve {@link com.opensymphony.module.sitemesh.Decorator} based on 'pattern' tag. */ public Decorator getDecorator(HttpServletRequest request, Page page) { String thisPath = request.getServletPath(); // getServletPath() returns null unless the mapping corresponds to a servlet if (thisPath == null) { String requestURI = request.getRequestURI(); if (request.getPathInfo() != null) { // strip the pathInfo from the requestURI thisPath = requestURI.substring(0, requestURI.indexOf(request.getPathInfo())); } else { thisPath = requestURI; } } else if ("".equals(thisPath)) { // in servlet 2.4, if a request is mapped to '/*', getServletPath returns null (SIM-130) thisPath = request.getPathInfo(); } String name = null; try { name = configLoader.getMappedName(thisPath); } catch (ServletException e) { e.printStackTrace(); } Decorator result = getNamedDecorator(request, name); return result == null ? super.getDecorator(request, page) : result; } /** Retrieve Decorator named in 'name' attribute. Checks the role if specified. */ public Decorator getNamedDecorator(HttpServletRequest request, String name) { Decorator result = null; try { result = configLoader.getDecoratorByName(name); } catch (ServletException e) { e.printStackTrace(); } if (result == null || (result.getRole() != null && !request.isUserInRole(result.getRole()))) { // if the result is null or the user is not in the role return super.getNamedDecorator(request, name); } else { return result; } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/InlineDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/InlineDecoratorMapper.java0000644000175000017500000000322107771770600033705 0ustar twernertwerner/* * Title: InlineDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.RequestConstants; import com.opensymphony.module.sitemesh.factory.FactoryException; import javax.servlet.http.HttpServletRequest; /** * The InlineDecoratorMapper is used to determine the correct Decorator when * using inline decorators. * *

    It will check the request attribute value defined by the key * {@link com.opensymphony.module.sitemesh.RequestConstants#DECORATOR} and use the appropriate named * Decorator. This is passed across from the page:applyDecorator tag.

    * * @author Joe Walnes * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class InlineDecoratorMapper extends AbstractDecoratorMapper implements RequestConstants { public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; if (request.getAttribute(DECORATOR) != null) { // Retrieve name of decorator to use from request String decoratorName = (String)request.getAttribute(DECORATOR); result = getNamedDecorator(request, decoratorName); if (result == null) throw new FactoryException("Cannot locate inline Decorator: " + decoratorName); } return result == null ? super.getDecorator(request, page) : result; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/CookieDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/CookieDecoratorMapper.java0000644000175000017500000000377110047520176033701 0ustar twernertwerner/* * Title: CookieDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.Cookie; import java.util.Properties; /** * The CookieDecoratorMapper will map a suitable decorator based on a cookie value. * *

    The CookieDecoratorMapper is configured via one properties. * cookie.name - the cookie which contains the name of the * decorator which will be mapped.

    * * @author Paul Hammant * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class CookieDecoratorMapper extends AbstractDecoratorMapper { private String cookieName; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); cookieName = properties.getProperty("cookie.name", null); if (cookieName == null) { throw new InstantiationException("'cookie.name' name parameter not set for this decorator mapper"); } } public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; if (cookie.getName().equals(cookieName)) { result = getNamedDecorator(request, cookie.getValue()); } } } return result == null ? super.getDecorator(request, page) : result; } }././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/SessionDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/SessionDecoratorMapper.jav0000644000175000017500000000305310162346630033742 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** *

    Will look at a session attribute to find the name of an appropriate decorator to use. If the * session attribute is present, the mapper will not do anything and allow the next mapper in the chain * to select a decorator.

    * *

    By default, it will look at the 'decorator' session attribute, however this can be overriden by * configuring the mapper with a 'decorator.parameter' property.

    * * @author Ricardo Lecheta */ public class SessionDecoratorMapper extends AbstractDecoratorMapper { private String decoratorParameter = null; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); decoratorParameter = properties.getProperty("decorator.parameter", "decorator"); } public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; String decorator = (String) request.getSession().getAttribute(decoratorParameter); //get decorator from HttpSession if (decorator != null) { result = getNamedDecorator(request, decorator); } return result == null ? super.getDecorator(request, page) : result; } }././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/EnvEntryDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/EnvEntryDecoratorMapper.ja0000644000175000017500000000555510244174464033721 0ustar twernertwerner/* * Title: EnvEntryDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Decorator; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.http.HttpServletRequest; /** * The EnvEntryDecoratorMapper allows the reference to a web-app environment entry for the * decorator name, and falls back to ConfigDecoratorMapper's behavior if no matching * environment entry is found. * *

    In some cases, it's desirable to allow a deployer, as opposed to a developer, * to specify a decorator. In a .WAR file, this can be very difficult, since * decorator mappings are specified in decorators.xml (more or less). * This mapper corrects that by allowing two types of mapping. If the decorator * name is found in an <env-entry>, the entry's value is used * as the decorator reference.

    * *

    Known Issues:

    *
      *
    1. It still uses the decorator path (from decorators.xml). This * needs to be corrected for full functionality. If anyone has a suggestion * on how...
    2. *
    * * @author Joseph B. Ottinger * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper */ public class EnvEntryDecoratorMapper extends ConfigDecoratorMapper { /** * Retrieves the {@link com.opensymphony.module.sitemesh.Decorator} * specified by the decorator name. If it's not in the environment * entries of the web application, assume it's a named decorator * from decorators.xml. */ public Decorator getNamedDecorator(HttpServletRequest request, String name) { String resourceValue = getStringResource(name); if (resourceValue == null) { return super.getNamedDecorator(request, name); } else { return new DefaultDecorator(name, resourceValue, null); } } /** * This pulls a value out of the web-app environment. * If the value isn't there, returns null. */ public static String getStringResource(String name) { String value = null; Context ctx = null; try { ctx = new InitialContext(); Object o = ctx.lookup("java:comp/env/" + name); if (o != null) { value = o.toString(); } } catch (NamingException ne) { } finally { try { if (ctx != null) ctx.close(); } catch (NamingException ne) { } } return value; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/PageDecoratorMapper.java0000644000175000017500000000536007764711666033362 0ustar twernertwerner/* * Title: PageDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * The PageDecoratorMapper allows the actual Page to determine the Decorator to be * used. * *

    The 'meta.decorator' and 'decorator' properties of the page are accessed * and if any of them contain the name of a valid Decorator, that Decorator shall * be applied.

    * *

    As an example, if HTML is being used, the Decorator could be chosen by using * a <html decorator="mydecorator"> root tag or by using a * <meta name="decorator" content="mydecorator"> tag in the header.

    * *

    The actual properties to query are specified by passing properties to the mapper using the * property.? prefix. As the properties are stored in a Map, each key has to be unique. * Example: property.1=decorator, property.2=meta.decorator .

    * * @author Joe Walnes * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class PageDecoratorMapper extends AbstractDecoratorMapper { private List pageProps = null; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); pageProps = new ArrayList(); Iterator i = properties.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); String key = (String) entry.getKey(); if (key.startsWith("property")) { pageProps.add(entry.getValue()); } } } public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; Iterator i = pageProps.iterator(); while (i.hasNext()) { String propName = (String)i.next(); result = getByProperty(request, page, propName); if (result != null) break; } return result == null ? super.getDecorator(request, page) : result; } private Decorator getByProperty(HttpServletRequest request, Page p, String name) { if (p.isPropertySet(name)) { return getNamedDecorator(request, p.getProperty(name)); } return null; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/FileDecoratorMapper.java0000644000175000017500000000456710274764356033367 0ustar twernertwerner/* * Title: FileDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Decorator; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import javax.servlet.http.HttpServletRequest; /** * The FileDecoratorMapper will treat the name of the decorator as a file-name to use * (in the context of the web-app). * * @author Joe Walnes * @author Mike Cannon-Brookes * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper * @see com.opensymphony.module.sitemesh.mapper.DefaultDecorator */ public class FileDecoratorMapper extends AbstractDecoratorMapper { private boolean pathNotAvailable = false; public Decorator getNamedDecorator(HttpServletRequest req, String name) { if (pathNotAvailable || name == null) { return super.getNamedDecorator(req, name); } URL resourcePath; // try to locate the resource (might be an unexpanded WAR) try { resourcePath = config.getServletContext().getResource('/' + name); } catch (MalformedURLException e) { return super.getNamedDecorator(req, name); } String filePath = config.getServletContext().getRealPath(name); if (filePath == null && resourcePath == null) { pathNotAvailable = true; return super.getNamedDecorator(req, name); } else if (filePath != null) { // do we really need this disk file check?! File file = new File(filePath); if (file.exists() && file.canRead() && file.isFile()) { // if filename exists with name of supplied decorator, return Decorator return new DefaultDecorator(name, name, null); } else { // otherwise delegate to parent mapper. return super.getNamedDecorator(req, name); } } else { // file path is null and resource path is not null - can't check file on disk return new DefaultDecorator(name, name, null); } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/PathMapper.java0000644000175000017500000002117010244174464031516 0ustar twernertwerner/* * Title: PathMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import java.util.HashMap; import java.util.Map; import java.util.Iterator; /** * The PathMapper is used to map file patterns to keys, and find an approriate * key for a given file path. The pattern rules are consistent with those defined * in the Servlet 2.3 API on the whole. Wildcard patterns are also supported, using * any combination of * and ?. * *

    Example

    * *
    * PathMapper pm = new PathMapper();
    *
    * pm.put("one","/");
    * pm.put("two","/mydir/*");
    * pm.put("three","*.xml");
    * pm.put("four","/myexactfile.html");
    * pm.put("five","/*\/admin/*.??ml");
    *
    * String result1 = pm.get("/mydir/myfile.xml"); // returns "two";
    * String result2 = pm.get("/mydir/otherdir/admin/myfile.html"); // returns "five";
    *
    * * @author Joe Walnes * @author Mike Cannon-Brookes * @author Hani Suleiman * @version $Revision: 1.3 $ */ public class PathMapper { private Map mappings = new HashMap(); /** Add a key and appropriate matching pattern. */ public void put(String key, String pattern) { if (key != null) { mappings.put(pattern, key); } } /** Retrieve appropriate key by matching patterns with supplied path. */ public String get(String path) { if (path == null) path = "/"; String mapped = findKey(path, mappings); if (mapped == null) return null; return (String) mappings.get(mapped); } /** Find exact key in mappings. */ private static String findKey(String path, Map mappings) { String result = findExactKey(path, mappings); if (result == null) result = findComplexKey(path, mappings); if (result == null) result = findDefaultKey(mappings); return result; } /** Check if path matches exact pattern ( /blah/blah.jsp ). */ private static String findExactKey(String path, Map mappings) { if (mappings.containsKey(path)) return path; return null; } private static String findComplexKey(String path, Map mappings) { Iterator i = mappings.keySet().iterator(); String result = null, key = null; while (i.hasNext()) { key = (String) i.next(); if (key.length() > 1 && (key.indexOf('?') != -1 || key.indexOf('*') != -1) && match(key, path, false)) { if (result == null || key.length() > result.length()) { // longest key wins result = key; } } } return result; } /** Look for root pattern ( / ). */ private static String findDefaultKey(Map mappings) { String[] defaultKeys = {"/", "*", "/*"}; for (int i = 0; i < defaultKeys.length; i++) { if (mappings.containsKey(defaultKeys[i])) return defaultKeys[i]; } return null; } private static boolean match(String pattern, String str, boolean isCaseSensitive) { char[] patArr = pattern.toCharArray(); char[] strArr = str.toCharArray(); int patIdxStart = 0; int patIdxEnd = patArr.length - 1; int strIdxStart = 0; int strIdxEnd = strArr.length - 1; char ch; boolean containsStar = false; for (int i = 0; i < patArr.length; i++) { if (patArr[i] == '*') { containsStar = true; break; } } if (!containsStar) { // No '*'s, so we make a shortcut if (patIdxEnd != strIdxEnd) { return false; // Pattern and string do not have the same size } for (int i = 0; i <= patIdxEnd; i++) { ch = patArr[i]; if (ch != '?') { if (isCaseSensitive && ch != strArr[i]) { return false; // Character mismatch } if (!isCaseSensitive && Character.toUpperCase(ch) != Character.toUpperCase(strArr[i])) { return false; // Character mismatch } } } return true; // String matches against pattern } if (patIdxEnd == 0) { return true; // Pattern contains only '*', which matches anything } // Process characters before first star while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { if (ch != '?') { if (isCaseSensitive && ch != strArr[strIdxStart]) { return false; // Character mismatch } if (!isCaseSensitive && Character.toUpperCase(ch) != Character.toUpperCase(strArr[strIdxStart])) { return false; // Character mismatch } } patIdxStart++; strIdxStart++; } if (strIdxStart > strIdxEnd) { // All characters in the string are used. Check if only '*'s are // left in the pattern. If so, we succeeded. Otherwise failure. for (int i = patIdxStart; i <= patIdxEnd; i++) { if (patArr[i] != '*') { return false; } } return true; } // Process characters after last star while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { if (ch != '?') { if (isCaseSensitive && ch != strArr[strIdxEnd]) { return false; // Character mismatch } if (!isCaseSensitive && Character.toUpperCase(ch) != Character.toUpperCase(strArr[strIdxEnd])) { return false; // Character mismatch } } patIdxEnd--; strIdxEnd--; } if (strIdxStart > strIdxEnd) { // All characters in the string are used. Check if only '*'s are // left in the pattern. If so, we succeeded. Otherwise failure. for (int i = patIdxStart; i <= patIdxEnd; i++) { if (patArr[i] != '*') { return false; } } return true; } // process pattern between stars. padIdxStart and patIdxEnd point // always to a '*'. while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { int patIdxTmp = -1; for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { if (patArr[i] == '*') { patIdxTmp = i; break; } } if (patIdxTmp == patIdxStart + 1) { // Two stars next to each other, skip the first one. patIdxStart++; continue; } // Find the pattern between padIdxStart & padIdxTmp in str between // strIdxStart & strIdxEnd int patLength = (patIdxTmp - patIdxStart - 1); int strLength = (strIdxEnd - strIdxStart + 1); int foundIdx = -1; strLoop: for (int i = 0; i <= strLength - patLength; i++) { for (int j = 0; j < patLength; j++) { ch = patArr[patIdxStart + j + 1]; if (ch != '?') { if (isCaseSensitive && ch != strArr[strIdxStart + i + j]) { continue strLoop; } if (!isCaseSensitive && Character.toUpperCase(ch) != Character.toUpperCase(strArr[strIdxStart + i + j])) { continue strLoop; } } } foundIdx = strIdxStart + i; break; } if (foundIdx == -1) { return false; } patIdxStart = patIdxTmp; strIdxStart = foundIdx + patLength; } // All characters in the string are used. Check if only '*'s are left // in the pattern. If so, we succeeded. Otherwise failure. for (int i = patIdxStart; i <= patIdxEnd; i++) { if (patArr[i] != '*') { return false; } } return true; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/RobotDecoratorMapper.java0000644000175000017500000002333010244174464033552 0ustar twernertwerner/* * Title: RobotDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.RequestConstants; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.Properties; /** * The RobotDecoratorMapper will use the specified decorator when the requester * is identified as a robot (also known as spider, crawler, ferret) of a search engine. * *

    The name of this decorator should be supplied in the decorator * property.

    * * @author Mathias Bogaert * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class RobotDecoratorMapper extends AbstractDecoratorMapper { private String decoratorName = null; /** All known robot hosts (list can be found here). */ private static final String[] botHosts = {"alltheweb.com", "alta-vista.net", "altavista.com", "atext.com", "euroseek.net", "excite.com", "fast-search.net", "google.com", "googlebot.com", "infoseek.co.jp", "infoseek.com", "inktomi.com", "inktomisearch.com", "linuxtoday.com.au", "lycos.com", "lycos.com", "northernlight.com", "pa-x.dec.com"}; /** * All known robot user-agent headers (list can be found * here). * *

    NOTE: To avoid bad detection:

    * *
      *
    • Robots with ID of 2 letters only were removed
    • *
    • Robot called "webs" were removed
    • *
    • directhit was changed in direct_hit (its real id)
    • *
    */ private static final String[] botAgents = { "acme.spider", "ahoythehomepagefinder", "alkaline", "appie", "arachnophilia", "architext", "aretha", "ariadne", "aspider", "atn.txt", "atomz", "auresys", "backrub", "bigbrother", "bjaaland", "blackwidow", "blindekuh", "bloodhound", "brightnet", "bspider", "cactvschemistryspider", "calif", "cassandra", "cgireader", "checkbot", "churl", "cmc", "collective", "combine", "conceptbot", "core", "cshkust", "cusco", "cyberspyder", "deweb", "dienstspider", "diibot", "direct_hit", "dnabot", "download_express", "dragonbot", "dwcp", "ebiness", "eit", "emacs", "emcspider", "esther", "evliyacelebi", "fdse", "felix", "ferret", "fetchrover", "fido", "finnish", "fireball", "fish", "fouineur", "francoroute", "freecrawl", "funnelweb", "gazz", "gcreep", "getbot", "geturl", "golem", "googlebot", "grapnel", "griffon", "gromit", "gulliver", "hambot", "harvest", "havindex", "hometown", "wired-digital", "htdig", "htmlgobble", "hyperdecontextualizer", "ibm", "iconoclast", "ilse", "imagelock", "incywincy", "informant", "infoseek", "infoseeksidewinder", "infospider", "inspectorwww", "intelliagent", "iron33", "israelisearch", "javabee", "jcrawler", "jeeves", "jobot", "joebot", "jubii", "jumpstation", "katipo", "kdd", "kilroy", "ko_yappo_robot", "labelgrabber.txt", "larbin", "legs", "linkscan", "linkwalker", "lockon", "logo_gif", "lycos", "macworm", "magpie", "mediafox", "merzscope", "meshexplorer", "mindcrawler", "moget", "momspider", "monster", "motor", "muscatferret", "mwdsearch", "myweb", "netcarta", "netmechanic", "netscoop", "newscan-online", "nhse", "nomad", "northstar", "nzexplorer", "occam", "octopus", "orb_search", "packrat", "pageboy", "parasite", "patric", "perignator", "perlcrawler", "phantom", "piltdownman", "pioneer", "pitkow", "pjspider", "pka", "plumtreewebaccessor", "poppi", "portalb", "puu", "python", "raven", "rbse", "resumerobot", "rhcs", "roadrunner", "robbie", "robi", "roverbot", "safetynetrobot", "scooter", "search_au", "searchprocess", "senrigan", "sgscout", "shaggy", "shaihulud", "sift", "simbot", "site-valet", "sitegrabber", "sitetech", "slurp", "smartspider", "snooper", "solbot", "spanner", "speedy", "spider_monkey", "spiderbot", "spiderman", "spry", "ssearcher", "suke", "sven", "tach_bw", "tarantula", "tarspider", "tcl", "techbot", "templeton", "titin", "titan", "tkwww", "tlspider", "ucsd", "udmsearch", "urlck", "valkyrie", "victoria", "visionsearch", "voyager", "vwbot", "w3index", "w3m2", "wanderer", "webbandit", "webcatcher", "webcopy", "webfetcher", "webfoot", "weblayers", "weblinker", "webmirror", "webmoose", "webquest", "webreader", "webreaper", "websnarf", "webspider", "webvac", "webwalk", "webwalker", "webwatch", "wget", "whowhere", "wmir", "wolp", "wombat", "worm", "wwwc", "wz101", "xget", "nederland.zoek" }; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); decoratorName = properties.getProperty("decorator"); } public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; if (decoratorName != null && isBot(request)) { result = getNamedDecorator(request, decoratorName); } return result == null ? super.getDecorator(request, page) : result; } /** Check if the current request came from a robot (also known as spider, crawler, ferret) */ private static boolean isBot(HttpServletRequest request) { if (request == null) return false; // force creation of a session HttpSession session = request.getSession(true); if (Boolean.FALSE.equals(session.getAttribute(RequestConstants.ROBOT))) { return false; } else if (Boolean.TRUE.equals(session.getAttribute(RequestConstants.ROBOT))) { // a key was found in the session indicating it is a robot return true; } else { if ("robots.txt".indexOf(request.getRequestURI()) != -1) { // there is a specific request for the robots.txt file, so we assume // it must be a robot (only robots request robots.txt) // set a key in the session, so the next time we don't have to manually // detect the robot again session.setAttribute(RequestConstants.ROBOT, Boolean.TRUE); return true; } else { String userAgent = request.getHeader("User-Agent"); if (userAgent != null && userAgent.trim().length() > 2) { // first check for common user-agent headers, so that we can speed // this thing up, hopefully clever spiders will not send a fake header if (userAgent.indexOf("MSIE") != -1 || userAgent.indexOf("Gecko") != -1 // MSIE and Mozilla || userAgent.indexOf("Opera") != -1 || userAgent.indexOf("iCab") != -1 // Opera and iCab (mac browser) || userAgent.indexOf("Konqueror") != -1 || userAgent.indexOf("KMeleon") != -1 // Konqueror and KMeleon || userAgent.indexOf("4.7") != -1 || userAgent.indexOf("Lynx") != -1) { // NS 4.78 and Lynx // indicate this session is not a robot session.setAttribute(RequestConstants.ROBOT, Boolean.FALSE); return false; } for (int i = 0; i < botAgents.length; i++) { if (userAgent.indexOf(botAgents[i]) != -1) { // set a key in the session, so the next time we don't have to manually // detect the robot again session.setAttribute(RequestConstants.ROBOT, Boolean.TRUE); return true; } } } // detect the robot from the host or user-agent String remoteHost = request.getRemoteHost(); // requires one DNS lookup // if the DNS server didn't return a hostname, getRemoteHost returns the // IP address, which is ignored here (the last char is checked, because some // remote hosts begin with the IP) if (remoteHost != null && remoteHost.length() > 0 && remoteHost.charAt(remoteHost.length() - 1) > 64) { for (int i = 0; i < botHosts.length; i++) { if (remoteHost.indexOf(botHosts[i]) != -1) { // set a key in the session, so the next time we don't have to manually // detect the robot again session.setAttribute(RequestConstants.ROBOT, Boolean.TRUE); return true; } } } // remote host and user agent are not in the predefined list, // so it must be an unknown robot or not a robot // indicate this session is not a robot session.setAttribute(RequestConstants.ROBOT, Boolean.FALSE); return false; } } } }././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/LanguageDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/LanguageDecoratorMapper.ja0000644000175000017500000001115210244174464033660 0ustar twernertwerner/* * Title: LanguageDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; /** * The LanguageDecoratorMapper can determine the preferred language set in the * browser requesting a page, and map to a suitable Decorator (using the * "Accept-Language" HTTP header). * *

    This can be useful for supplying different versions of the same content * for different languages.

    * *

    When LanguageDecoratorMapper is in the chain, it will request the appropriate Decorator * from its parent. It will then add an extention to the filename of the Decorator, and * if that file exists it shall be used as the Decorator instead. For example, if the * Decorator path is /blah.jsp and the detected preferred language is en, * the path /blah-en.jsp shall be used.

    * *

    The language mappings are configured by passing properties with match. as a prefix. * For example: 'match.en'=engl , 'match.nl'=dutch .

    * * @author Mathias Bogaert * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class LanguageDecoratorMapper extends AbstractDecoratorMapper { private Map map = null; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); map = new HashMap(); initMap(properties); } public Decorator getDecorator(HttpServletRequest request, Page page) { try { Decorator result = null; final Decorator d = super.getDecorator(request, page); String path = modifyPath(d.getPage(), getExt(request.getHeader("Accept-Language"))); File decFile = new File(config.getServletContext().getRealPath(path)); if (decFile.isFile()) { result = new DefaultDecorator(d.getName(), path, null) { public String getInitParameter(String paramName) { return d.getInitParameter(paramName); } }; } return result == null ? super.getDecorator(request, page) : result; } catch (NullPointerException e) { return super.getDecorator(request, page); } } /** Get extention for the language. */ private String getExt(String acceptLanguage) { Iterator i = map.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); // Get the first language (preferred one) in the header, and // only check the first two chars (the acceptLanguage could be en-gb, but // we don't support this for now). if (acceptLanguage.substring(0, 2).equals(entry.getKey())) { return (String) entry.getValue(); } // When the user-agent has multiple accept-languages (separated by ;), // these are ignored because the site creator may wish that if the // preferred language is not supported, the page uses the default // decorator (in the default language), and not in some other // language given by the browser (most of them are specified by // default at install). } return null; } /** Change /abc/def.jsp into /abc/def-XYZ.jsp */ private static String modifyPath(String path, String ext) { int dot = path.indexOf('.'); if (dot > -1) { return path.substring(0, dot) + '-' + ext + path.substring(dot); } else { return path + '-' + ext; } } /** Initialize language mappings. */ private void initMap(Properties props) { Iterator i = props.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); String key = (String) entry.getKey(); if (key.startsWith("match.")) { String match = key.substring(6); map.put(match, entry.getValue()); } } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/OSDecoratorMapper.java0000644000175000017500000000706110751610056033004 0ustar twernertwerner/* * Title: OSDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.Properties; /** * The OSDecoratorMapper will map a suitable decorator based on the operating system * of the remote client. * *

    OSDecoratorMapper works by checking to see if the "UA-OS" header * was sent with the HTTP request. If it was, the class will check the * value of the header with all the different os's the user has configured * the Decorator Mapper to identify and, if a match is found, routes the * request accordingly. Configuration is done using the sitemesh.xml file. * The param name is a string literal (operating system name) you would like * to match in the UA-OS header, and the value is what will be appended to the * decorator name if the user is using that operating system

    * * @author Adam P. Schepis * @version $Revision: 1.4 $ * * @see com.opensymphony.module.sitemesh.mapper.AbstractDecoratorMapper */ public class OSDecoratorMapper extends AbstractDecoratorMapper { /** * Properties holds the parameters that the object was initialized with. */ protected Properties properties; /** * Init initializes the OSDecoratorMapper object by setting the parent * DecoratorMapper, and loading the initialization properties. * * @param config The config file * @param properties An object containing intialization parameters * @param parent The parent DecoratorMapper object */ public void init(Config config, Properties properties, DecoratorMapper parent) throws java.lang.InstantiationException { this.properties = properties; this.parent = parent; } /** * Attempts to find the correct decorator for Page page based on * the UA-OS HTTP header in the request. * * @param request The HTTP request sent to the server * @param page The page SiteMesh is trying to find a decorator for * * @return A Decorator object that is either the decorator for the identified * OS, or the parent DecoratorMapper's decorator */ public Decorator getDecorator(HttpServletRequest request, Page page) { String osHeader = request.getHeader("UA-OS"); if (osHeader == null) return parent.getDecorator(request, page); // run through the list of operating systems the application developer listed // in sitemesh.xml to see if we have a match to the user's current OS for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { String os = (String) e.nextElement(); // see if the name matches the user's operating system name if (osHeader.toLowerCase().indexOf(os.toLowerCase()) != -1) { String decoratorName = parent.getDecorator(request, page).getName(); if (decoratorName != null) { decoratorName += '-' + properties.getProperty(os); } return getNamedDecorator(request, decoratorName); } } return parent.getDecorator(request, page); } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/PrintableDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/PrintableDecoratorMapper.j0000644000175000017500000000423010244174464033713 0ustar twernertwerner/* * Title: PrintableDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * The PrintableDecoratorMapper is a sample DecoratorMapper that will * check to see whether 'printable=true' is supplied as a request parameter * and if so, use the specified decorator instead. The name of this decorator * should be supplied in the decorator property. * *

    The exact 'printable=true' request criteria can be overriden with the * parameter.name and parameter.value properties.

    * *

    Although this DecoratorMapper was designed for creating printable versions * of a page, it can be used for much more imaginative purposes.

    * * @author Joe Walnes * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class PrintableDecoratorMapper extends AbstractDecoratorMapper { private String decorator, paramName, paramValue; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); decorator = properties.getProperty("decorator"); paramName = properties.getProperty("parameter.name", "printable"); paramValue = properties.getProperty("parameter.value", "true"); } public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator result = null; if (decorator != null && paramValue.equalsIgnoreCase(request.getParameter(paramName))) { result = getNamedDecorator(request, decorator); } return result == null ? super.getDecorator(request, page) : result; } }././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/AbstractDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/AbstractDecoratorMapper.ja0000644000175000017500000000336107751471036033707 0ustar twernertwerner/* * Title: AbstractDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * Abstract DecoratorMapper implementation for easy creation of new DecoratorMappers. * *

    Typically, an implementation would override getNamedDecorator() or getDecorator(). * If a Decorator cannot be returned from either of these, then they should delegate to their * superclass.

    * * @author Joe Walnes * @version $Revision: 1.1 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public abstract class AbstractDecoratorMapper implements DecoratorMapper { /** Parent DecoratorMapper. */ protected DecoratorMapper parent = null; protected Config config = null; /** Set parent. */ public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { this.parent = parent; this.config = config; } /** Delegate to parent. */ public Decorator getDecorator(HttpServletRequest request, Page page) { return parent.getDecorator(request, page); } /** Delegate to parent. */ public Decorator getNamedDecorator(HttpServletRequest request, String name) { return parent.getNamedDecorator(request, name); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/NullDecoratorMapper.java0000644000175000017500000000264107751471036033405 0ustar twernertwerner/* * Title: NullDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * The NullDecoratorMapper represents the top-level DecoratorMapper that * is finally delegated to if no other DecoratorMapper has intervened. * It is used so the parent property does not have to be checked by * other DecoratorMappers (null object pattern). * * @author Joe Walnes * @version $Revision: 1.1 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class NullDecoratorMapper implements DecoratorMapper { /** Does nothing. */ public void init(Config config, Properties properties, DecoratorMapper parent) { } /** Returns null. */ public Decorator getDecorator(HttpServletRequest request, Page page) { return null; } /** Returns null. */ public Decorator getNamedDecorator(HttpServletRequest request, String name) { return null; } }././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/FrameSetDecoratorMapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/FrameSetDecoratorMapper.ja0000644000175000017500000000342410244174464033646 0ustar twernertwerner/* * Title: FrameSetDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * The FrameSetDecoratorMapper will use the specified decorator when the Page * is an instance of {@link com.opensymphony.module.sitemesh.HTMLPage} and * isFrameSet() returns true. * *

    The name of this decorator should be supplied in the decorator * property - if no decorator property is supplied, no decorator is applied to * frame based pages. * * @author Joe Walnes * @version $Revision: 1.2 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class FrameSetDecoratorMapper extends AbstractDecoratorMapper { private String decorator = null; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); decorator = properties.getProperty("decorator"); } public Decorator getDecorator(HttpServletRequest request, Page page) { if (page instanceof HTMLPage && ((HTMLPage)page).isFrameSet()) { return getNamedDecorator(request, decorator); } else { return super.getDecorator(request, page); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/DefaultDecorator.java0000644000175000017500000000604207751471036032711 0ustar twernertwerner/* * Title: DefaultDecorator * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Decorator; import java.util.Map; import java.util.Iterator; import java.util.Collections; /** * Default implementation of Decorator. All properties are set by the * constructor. * * @author Joe Walnes * @version $Revision: 1.1 $ * * @see com.opensymphony.module.sitemesh.Decorator */ public class DefaultDecorator implements Decorator { /** @see #getPage() */ protected String page = null; /** @see #getName() */ protected String name = null; /** @see #getURIPath() */ protected String uriPath = null; /** @see #getRole() */ protected String role = null; /** @see #getInitParameter(java.lang.String) */ protected Map parameters = null; /** Constructor to set name, page and parameters. */ public DefaultDecorator(String name, String page, Map parameters) { this(name, page, null, null, parameters); } /** Constructor to set all properties. */ public DefaultDecorator(String name, String page, String uriPath, Map parameters) { this(name, page, uriPath, null, parameters); } /** Constructor to set all properties. */ public DefaultDecorator(String name, String page, String uriPath, String role, Map parameters) { this.name = name; this.page = page; this.uriPath = uriPath; this.role = role; this.parameters = parameters; } /** * URI of the Servlet/JSP to dispatch the request to (relative to the * web-app context). */ public String getPage() { return page; } /** Name of Decorator. For information purposes only. */ public String getName() { return name; } /** URI path of the Decorator. Enables support for decorators defined in seperate web-apps. */ public String getURIPath() { return uriPath; } /** Role the user has to be in to get this decorator applied. */ public String getRole() { return role; } /** * Returns a String containing the value of the named initialization parameter, * or null if the parameter does not exist. * * @param paramName Key of parameter. * @return Value of parameter or null if not found. */ public String getInitParameter(String paramName) { if (parameters == null || !parameters.containsKey(paramName)) { return null; } return (String) parameters.get(paramName); } /** * Returns the names of the Decorator's initialization parameters as an Iterator * of String objects, or an empty Iterator if the Decorator has no initialization parameters. */ public Iterator getInitParameterNames() { if (parameters == null) { // make sure we always return an empty iterator return Collections.EMPTY_MAP.keySet().iterator(); } return parameters.keySet().iterator(); } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/mapper/AgentDecoratorMapper.java0000644000175000017500000001037210244174462033523 0ustar twernertwerner/* * Title: AgentDecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.mapper; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; /** * The AgentDecoratorMapper can determine the user-agent (i.e. web-browser) * requesting a page, and map to a suitable Decorator. * *

    This can be useful for supplying different versions of the same content * for different browsers (e.g. vanilla HTML for Lynx, complex tables and frames * for Netscape, extra stuff for IE5, etc).

    * *

    This can also be used to enhance search-engine ratings by using a 'bait and * switch' system - this involves showing a search-engine friendly of the content * to spiders only.

    * *

    When AgentDecoratorMapper is in the chain, it will request the appropriate Decorator * from its parent. It will then add an extention to the filename of the Decorator, and * if that file exists it shall be used as the Decorator instead. For example, if the * Decorator path is /blah.jsp and the detected user-agent is ie, * the path /blah-ie.jsp shall be used.

    * *

    The agent mappings are configured by passing properties with match. as a prefix. * For example: 'match.MSIE'=ie , 'match.Lynx'=plain .

    * * @author Joe Walnes * @version $Revision: 1.3 $ * * @see com.opensymphony.module.sitemesh.DecoratorMapper */ public class AgentDecoratorMapper extends AbstractDecoratorMapper { private Map map = null; public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException { super.init(config, properties, parent); map = new HashMap(); initMap(properties); } public Decorator getDecorator(HttpServletRequest request, Page page) { try { Decorator result = null; final Decorator d = super.getDecorator(request, page); String path = modifyPath(d.getPage(), getExt(request.getHeader("User-Agent"))); File decFile = new File(config.getServletContext().getRealPath(path)); if (decFile.isFile()) { result = new DefaultDecorator(d.getName(), path, null) { public String getInitParameter(String paramName) { return d.getInitParameter(paramName); } }; } return result == null ? super.getDecorator(request, page) : result; } catch (NullPointerException e) { return super.getDecorator(request, page); } } /** Get extention for user-agent. */ private String getExt(String userAgent) { Iterator i = map.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); String curr = (String) entry.getKey(); if (userAgent.indexOf(curr) > -1) return (String) entry.getValue(); } return null; } /** Change /abc/def.jsp into /abc/def-XYZ.jsp */ private static String modifyPath(String path, String ext) { int dot = path.indexOf('.'); if (dot > -1) { return path.substring(0, dot) + '-' + ext + path.substring(dot); } else { return path + '-' + ext; } } /** Initialize user-agent mappings. */ private void initMap(Properties props) { Iterator i = props.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); String key = (String) entry.getKey(); if (key.startsWith("match.")) { String match = key.substring(6); String ext = (String) entry.getValue(); map.put(match, ext); } } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/Page.java0000644000175000017500000001111511157160460027036 0ustar twernertwerner/* * Title: Page * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.Writer; import java.util.Map; /** * The Page object wraps the contents of the original (undecorated) page. * *

    The original data in its entirity can be written using the writePage() * methods. It may also contain a set of properties - these vary among * different {@link com.opensymphony.module.sitemesh.PageParser} implementations.

    * *

    Typically a Page is no use to a {@link com.opensymphony.module.sitemesh.Decorator} as it needs * specific details relevant to the content-type of that page (e.g. HTML * pages). The appropriate {@link com.opensymphony.module.sitemesh.PageParser} is responsible * for returning extended implementations of pages such as {@link com.opensymphony.module.sitemesh.HTMLPage} * which are of more use to the Decorator. New media types (e.g. WML) could * be added to the system by extending Page and implementing an appropriate PageParser.

    * * @author Joe Walnes * @version $Revision: 1.5 $ */ public interface Page { /** * Write the entire contents of the Page, in the format before * it was parsed, to the Writer. * * @param out Writer to write to. * @exception java.io.IOException Rethrown if cannot write to writer. */ void writePage(Writer out) throws IOException; /** * Convenience method to return the contents of the Page in its original format. * * @since 2.1.1 * @see #writePage(java.io.Writer) */ String getPage(); /** * Write the contents of the <body> tag. */ void writeBody(Writer out) throws IOException; /** * Convenience method to return the contents of the <body> tag. * * @since 2.1.1 * @see #writeBody(java.io.Writer) */ String getBody(); /** * Get the Title of the document */ String getTitle(); /** * Length of the Page, in the format before * it was parsed. * * @return Length of page data (in number of bytes). */ int getContentLength(); /** * Get a property embedded into the Page as a String. * * @param name Name of property * @return Property value */ String getProperty(String name); /** * Get a property embedded into the Page as an int. * Returns 0 if property not specified or not valid number. * * @param name Name of property * @return Property value */ int getIntProperty(String name); /** * Get a property embedded into the Page as a long. * Returns 0L if property not specified or not valid number. * * @param name Name of property * @return Property value */ long getLongProperty(String name); /** * Get a property embedded into the Page as a boolean. * Returns true if value starts with '1', 't' or 'y' (case-insensitive) - * otherwise returns false. * * @param name Name of property * @return Property value */ boolean getBooleanProperty(String name); /** * Determine whether a property embedded into the Page has been set. * * @param name Name of property * @return Whether it has been set */ boolean isPropertySet(String name); /** * Get all available property keys for the Page. * * @return Property keys */ String[] getPropertyKeys(); /** * Get a Map representing all the properties in the Page. * * @return Properties map */ Map getProperties(); /** * Return the request of the original page. * * @deprecated Since Servlet 2.4 API, this is unnecessary - just use the stand HttpServletRequest instance. */ HttpServletRequest getRequest(); /** * Create snapshot of Request. Subsequent modifications to the request by * the servlet container will not be returned by {@link #getRequest()} */ void setRequest(HttpServletRequest request); /** * Manually add a property to page. */ void addProperty(String name, String value); }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/velocity/0000755000175000017500000000000011157130040027145 5ustar twernertwerner././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/velocity/VelocityDecoratorServlet.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/velocity/VelocityDecoratorServlet0000644000175000017500000000526710274764356034136 0ustar twernertwerner/* * Title: VelocityDecoratorServlet * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.velocity; import com.opensymphony.module.sitemesh.*; import com.opensymphony.module.sitemesh.util.OutputConverter; import org.apache.velocity.Template; import org.apache.velocity.context.Context; import org.apache.velocity.tools.view.servlet.VelocityViewServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.StringWriter; /** * Servlet that allows Velocity templates to be used as decorators. * * @author Joe Walnes * @version $Revision: 1.9 $ */ public class VelocityDecoratorServlet extends VelocityViewServlet { public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception { HTMLPage htmlPage = (HTMLPage) request.getAttribute(RequestConstants.PAGE); String template; context.put("base", request.getContextPath()); // For backwards compatability with apps that used the old VelocityDecoratorServlet // that extended VelocityServlet instead of VelocityViewServlet context.put("req", request); context.put("res", response); if (htmlPage == null) { context.put("title", "Title?"); context.put("body", "

    Body?

    "); context.put("head", ""); template = request.getServletPath(); } else { context.put("title", OutputConverter.convert(htmlPage.getTitle())); { StringWriter buffer = new StringWriter(); htmlPage.writeBody(OutputConverter.getWriter(buffer)); context.put("body", buffer.toString()); } { StringWriter buffer = new StringWriter(); htmlPage.writeHead(OutputConverter.getWriter(buffer)); context.put("head", buffer.toString()); } context.put("page", htmlPage); DecoratorMapper decoratorMapper = getDecoratorMapper(); Decorator decorator = decoratorMapper.getDecorator(request, htmlPage); template = decorator.getPage(); } return getTemplate(template); } private DecoratorMapper getDecoratorMapper() { Factory factory = Factory.getInstance(new Config(getServletConfig())); DecoratorMapper decoratorMapper = factory.getDecoratorMapper(); return decoratorMapper; } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/0000755000175000017500000000000011157130032026575 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/DebugResponseWrapper.java0000644000175000017500000001256210122022476033557 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.IOException; import java.io.PrintWriter; import java.util.Locale; /** * @author Joe Walnes * @version $Revision: 1.2 $ */ public class DebugResponseWrapper extends HttpServletResponseWrapper { private static int lastCount = 0; private int count = 0; public DebugResponseWrapper(HttpServletResponse response) { super(response); if (enabled()) { lastCount++; count = lastCount; debug("", null, null); } } public void addCookie(Cookie cookie) { if (enabled()) debug("addCookie", cookie.getName(), cookie.toString()); super.addCookie(cookie); } public void addDateHeader(String name, long date) { if (enabled()) debug("addDateHeader", name, String.valueOf(date)); super.addDateHeader(name, date); } public void addHeader(String name, String value) { if (enabled()) debug("addHeader", name, value); super.addHeader(name, value); } public void addIntHeader(String name, int value) { if (enabled()) debug("addIntHeader", name, String.valueOf(value)); super.addIntHeader(name, value); } public boolean containsHeader(String name) { return super.containsHeader(name); } public String encodeRedirectUrl(String url) { return super.encodeRedirectUrl(url); } public String encodeRedirectURL(String url) { return super.encodeRedirectURL(url); } public void sendError(int sc) throws IOException { if (enabled()) debug("sendError", String.valueOf(sc), null); super.sendError(sc); } public void sendError(int sc, String msg) throws IOException { if (enabled()) debug("sendError", String.valueOf(sc), msg); super.sendError(sc, msg); } public void sendRedirect(String location) throws IOException { if (enabled()) debug("sendRedirect", location, null); super.sendRedirect(location); } public void setDateHeader(String name, long date) { if (enabled()) debug("setDateHeader", name, String.valueOf(date)); super.setDateHeader(name, date); } public void setHeader(String name, String value) { if (enabled()) debug("setHeader", name, value); super.setHeader(name, value); } public void setIntHeader(String name, int value) { if (enabled()) debug("setIntHeader", name, String.valueOf(value)); super.setIntHeader(name, value); } public void setStatus(int sc) { if (enabled()) debug("setStatus", String.valueOf(sc), null); super.setStatus(sc); } public void setStatus(int sc, String msg) { if (enabled()) debug("setStatus", String.valueOf(sc), msg); super.setStatus(sc, msg); } public void flushBuffer() throws IOException { if (enabled()) debug("flushBuffer", null, null); super.flushBuffer(); } public int getBufferSize() { // return super.getBufferSize(); } public String getCharacterEncoding() { // return super.getCharacterEncoding(); } public Locale getLocale() { // return super.getLocale(); } public ServletOutputStream getOutputStream() throws IOException { if (enabled()) debug("getOutputStream", null, null); return super.getOutputStream(); } public PrintWriter getWriter() throws IOException { if (enabled()) debug("getWriter", null, null); return super.getWriter(); } public boolean isCommitted() { // return super.isCommitted(); } public void reset() { if (enabled()) debug("reset", null, null); super.reset(); } /*public void resetBuffer() { super.resetBuffer(); }*/ public void setBufferSize(int size) { if (enabled()) debug("setBufferSize", String.valueOf(size), null); super.setBufferSize(size); } public void setContentLength(int len) { if (enabled()) debug("setContentLength", String.valueOf(len), null); super.setContentLength(len); } public void setContentType(String type) { if (enabled()) debug("setContentType", type, null); super.setContentType(type); } public void setLocale(Locale locale) { if (enabled()) debug("setBufferSize", locale.getDisplayName(), null); super.setLocale(locale); } private boolean enabled() { return true; } private void debug(String methodName, String arg1, String arg2) { StringBuffer s = new StringBuffer(); s.append("[debug "); s.append(count); s.append("] "); s.append(methodName); s.append("()"); if (arg1 != null) { s.append(" : '"); s.append(arg1); s.append("'"); } if (arg2 != null) { s.append(" = '"); s.append(arg2); s.append("'"); } System.out.println(s); } }././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/RoutableServletOutputStream.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/RoutableServletOutputStrea0000644000175000017500000000635610122022500034063 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import javax.servlet.ServletOutputStream; import java.io.IOException; /** * Provides a ServletOutputStream that routes through to another ServletOutputStream, however the destination * can be changed at any point. The destination can be passed in using a factory, so it will not be created * until it's actually needed. * * @author Joe Walnes * @version $Revision: 1.1 $ */ public class RoutableServletOutputStream extends ServletOutputStream { private ServletOutputStream destination; private DestinationFactory factory; /** * Factory to lazily instantiate the destination. */ public static interface DestinationFactory { ServletOutputStream create() throws IOException; } public RoutableServletOutputStream(DestinationFactory factory) { this.factory = factory; } private ServletOutputStream getDestination() throws IOException { if (destination == null) { destination = factory.create(); } return destination; } public void updateDestination(DestinationFactory factory) { destination = null; this.factory = factory; } public void close() throws IOException { getDestination().close(); } public void write(int b) throws IOException { getDestination().write(b); } public void print(String s) throws IOException { getDestination().print(s); } public void print(boolean b) throws IOException { getDestination().print(b); } public void print(char c) throws IOException { getDestination().print(c); } public void print(int i) throws IOException { getDestination().print(i); } public void print(long l) throws IOException { getDestination().print(l); } public void print(float v) throws IOException { getDestination().print(v); } public void print(double v) throws IOException { getDestination().print(v); } public void println() throws IOException { getDestination().println(); } public void println(String s) throws IOException { getDestination().println(s); } public void println(boolean b) throws IOException { getDestination().println(b); } public void println(char c) throws IOException { getDestination().println(c); } public void println(int i) throws IOException { getDestination().println(i); } public void println(long l) throws IOException { getDestination().println(l); } public void println(float v) throws IOException { getDestination().println(v); } public void println(double v) throws IOException { getDestination().println(v); } public void write(byte b[]) throws IOException { getDestination().write(b); } public void write(byte b[], int off, int len) throws IOException { getDestination().write(b, off, len); } public void flush() throws IOException { getDestination().flush(); } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/TextEncoder.java0000644000175000017500000000641110122022500031655 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import java.io.ByteArrayInputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * Converts text stored in byte[] to char[] using specified encoding. * * @author Scott Farquhar * @author Hani Suleiman * @author Joe Walnes * @version $Revision: 1.1 $ */ public class TextEncoder { private static final String DEFAULT_ENCODING = System.getProperty("file.encoding"); private static final boolean JDK14 = System.getProperty("java.version").startsWith("1.4") || System.getProperty("java.version").startsWith("1.5"); public char[] encode(byte[] data, String encoding) throws IOException { if (encoding == null) { encoding = DEFAULT_ENCODING; } if (JDK14) { return get14Buffer(data, encoding); } else { return get13Buffer(data, encoding); } } private char[] get13Buffer(byte[] data, String encoding) throws IOException { CharArrayWriter out = null; // Why all this indirection? Because we are being given bytes, and we have to then write // them to characters. We need to know the encoding of the characterset that we are creating. // The test that verifies this is InlineDecoratorTest (inline/page6.jsp). InputStreamReader reader; out = new CharArrayWriter(); if (encoding != null) { reader = new InputStreamReader(new ByteArrayInputStream(data), encoding); } else { reader = new InputStreamReader(new ByteArrayInputStream(data)); } int i; while ((i = reader.read()) != -1) { out.write(i); } return out.toCharArray(); } private char[] get14Buffer(byte[] data, String encoding) throws IOException { if (!Charset.isSupported(encoding)) throw new IOException("Unsupported encoding " + encoding); Charset charset = Charset.forName(encoding); CharsetDecoder cd = charset.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); int en = (int) (cd.maxCharsPerByte() * data.length); char[] ca = new char[en]; ByteBuffer bb = ByteBuffer.wrap(data); CharBuffer cb = CharBuffer.wrap(ca); CoderResult cr = cd.decode(bb, cb, true); if (!cr.isUnderflow()) { cr.throwException(); } cr = cd.flush(cb); if (!cr.isUnderflow()) { cr.throwException(); } return trim(ca, cb.position()); } private char[] trim(char[] ca, int len) { if (len == ca.length) { return ca; } char[] tca = new char[len]; System.arraycopy(ca, 0, tca, 0, len); return tca; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootsitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/RequestDispatcherWrapper.javasitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/RequestDispatcherWrapper.j0000644000175000017500000000316510122022500033744 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; /** * Special request dispatcher that will include when an inline decorator includes * a resource that uses an internal forward. * * @see com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag * * @author Joseph B. Ottinger * @version $Revision: 1.2 $ */ public class RequestDispatcherWrapper implements RequestDispatcher { private RequestDispatcher rd = null; private boolean done = false; public RequestDispatcherWrapper(RequestDispatcher rd) { this.rd = rd; } public void forward(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { if (!done) { include(servletRequest, servletResponse); done = true; } else { throw new IllegalStateException("Response has already been committed"); } } public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { if (!done) { rd.include(servletRequest, servletResponse); } else { throw new IllegalStateException("Response has already been committed"); } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/HttpContentType.java0000644000175000017500000000364110277153000032562 0ustar twernertwernerpackage com.opensymphony.module.sitemesh.filter; /** * Extracts the type and encoding from an HTTP Content-Type header. * * @author Scott Farquhar */ public class HttpContentType { private final String type; private final String encoding; public HttpContentType(String fullValue) { // this is the content type + charset. eg: text/html;charset=UTF-8 int offset = fullValue.lastIndexOf("charset="); encoding = offset != -1 ? extractContentTypeValue(fullValue, offset + 8) : null; type = extractContentTypeValue(fullValue, 0); } private String extractContentTypeValue(String type, int startIndex) { if (startIndex < 0) return null; // Skip over any leading spaces while (startIndex < type.length() && type.charAt(startIndex) == ' ') startIndex++; if (startIndex >= type.length()) { return null; } int endIndex = startIndex; if (type.charAt(startIndex) == '"') { startIndex++; endIndex = type.indexOf('"', startIndex); if (endIndex == -1) endIndex = type.length(); } else { // Scan through until we hit either the end of the string or a // special character (as defined in RFC-2045). Note that we ignore '/' // since we want to capture it as part of the value. char ch; while (endIndex < type.length() && (ch = type.charAt(endIndex)) != ' ' && ch != ';' && ch != '(' && ch != ')' && ch != '[' && ch != ']' && ch != '<' && ch != '>' && ch != ':' && ch != ',' && ch != '=' && ch != '?' && ch != '@' && ch != '"' && ch != '\\') endIndex++; } return type.substring(startIndex, endIndex); } public String getType() { return type; } public String getEncoding() { return encoding; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/Buffer.java0000644000175000017500000000524410276712100030661 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import com.opensymphony.module.sitemesh.util.FastByteArrayOutputStream; import javax.servlet.ServletOutputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; /** * When SiteMesh is activated for a request, the contents of the response are stored in this buffer, where they can * later be accessed as a parsed Page object. * * @author Joe Walnes * @version $Revision: 1.3 $ */ public class Buffer { private final PageParser pageParser; private final String encoding; private final static TextEncoder TEXT_ENCODER = new TextEncoder(); private CharArrayWriter bufferedWriter; private FastByteArrayOutputStream bufferedStream; private PrintWriter exposedWriter; private ServletOutputStream exposedStream; public Buffer(PageParser pageParser, String encoding) { this.pageParser = pageParser; this.encoding = encoding; } public char[] getContents() throws IOException { if (bufferedWriter != null) { return bufferedWriter.toCharArray(); } else if (bufferedStream != null) { return TEXT_ENCODER.encode(bufferedStream.toByteArray(), encoding); } else { return new char[0]; } } public Page parse() throws IOException { return pageParser.parse(getContents()); } public PrintWriter getWriter() { if (bufferedWriter == null) { if (bufferedStream != null) { throw new IllegalStateException("response.getWriter() called after response.getOutputStream()"); } bufferedWriter = new CharArrayWriter(128); exposedWriter = new PrintWriter(bufferedWriter); } return exposedWriter; } public ServletOutputStream getOutputStream() { if (bufferedStream == null) { if (bufferedWriter != null) { throw new IllegalStateException("response.getOutputStream() called after response.getWriter()"); } bufferedStream = new FastByteArrayOutputStream(); exposedStream = new ServletOutputStream() { public void write(int b) { bufferedStream.write(b); } }; } return exposedStream; } public boolean isUsingStream() { return bufferedStream != null; } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/PageRequestWrapper.java0000644000175000017500000000243210264336704033243 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * Will wrap a request for the {@link RequestDispatcherWrapper}. * * @author Joseph B. Ottinger * @version $Revision: 1.4 $ */ public class PageRequestWrapper extends HttpServletRequestWrapper { private static final boolean SUPPRESS_IF_MODIFIED_HEADER = true; //todo - pull this from a config file public PageRequestWrapper(HttpServletRequest request) { super(request); } public RequestDispatcher getRequestDispatcher(String s) { return new RequestDispatcherWrapper(super.getRequestDispatcher(s)); } public String getHeader(String string) { // suppress 'if-modified-since' header, so that decorators can modify the response. if (SUPPRESS_IF_MODIFIED_HEADER && "IF-MODIFIED-SINCE".equalsIgnoreCase(string)) { return ""; } else { return super.getHeader(string); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/RoutablePrintWriter.java0000644000175000017500000001016510122022500033421 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import java.io.PrintWriter; import java.io.IOException; import java.io.Writer; /** * Provides a PrintWriter that routes through to another PrintWriter, however the destination * can be changed at any point. The destination can be passed in using a factory, so it will not be created * until it's actually needed. * * @author Joe Walnes * @version $Revision: 1.1 $ */ public class RoutablePrintWriter extends PrintWriter { private PrintWriter destination; private DestinationFactory factory; /** * Factory to lazily instantiate the destination. */ public static interface DestinationFactory { PrintWriter activateDestination() throws IOException; } public RoutablePrintWriter(DestinationFactory factory) { super(new NullWriter()); this.factory = factory; } private PrintWriter getDestination() { if (destination == null) { try { destination = factory.activateDestination(); } catch (IOException e) { setError(); } } return destination; } public void updateDestination(DestinationFactory factory) { destination = null; this.factory = factory; } public void close() { getDestination().close(); } public void println(Object x) { getDestination().println(x); } public void println(String x) { getDestination().println(x); } public void println(char x[]) { getDestination().println(x); } public void println(double x) { getDestination().println(x); } public void println(float x) { getDestination().println(x); } public void println(long x) { getDestination().println(x); } public void println(int x) { getDestination().println(x); } public void println(char x) { getDestination().println(x); } public void println(boolean x) { getDestination().println(x); } public void println() { getDestination().println(); } public void print(Object obj) { getDestination().print(obj); } public void print(String s) { getDestination().print(s); } public void print(char s[]) { getDestination().print(s); } public void print(double d) { getDestination().print(d); } public void print(float f) { getDestination().print(f); } public void print(long l) { getDestination().print(l); } public void print(int i) { getDestination().print(i); } public void print(char c) { getDestination().print(c); } public void print(boolean b) { getDestination().print(b); } public void write(String s) { getDestination().write(s); } public void write(String s, int off, int len) { getDestination().write(s, off, len); } public void write(char buf[]) { getDestination().write(buf); } public void write(char buf[], int off, int len) { getDestination().write(buf, off, len); } public void write(int c) { getDestination().write(c); } public boolean checkError() { return getDestination().checkError(); } public void flush() { getDestination().flush(); } /** * Just to keep super constructor for PrintWriter happy - it's never actually used. */ private static class NullWriter extends Writer { protected NullWriter() { super(); } public void write(char cbuf[], int off, int len) throws IOException { throw new UnsupportedOperationException(); } public void flush() throws IOException { throw new UnsupportedOperationException(); } public void close() throws IOException { throw new UnsupportedOperationException(); } } } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/PageFilter.java0000644000175000017500000000111110550354754031473 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import com.opensymphony.sitemesh.webapp.SiteMeshFilter; /** * @deprecated Use {@link com.opensymphony.sitemesh.webapp.SiteMeshFilter} instead. * * @author Joe Walnes * @author Scott Farquhar * @version $Revision: 1.17 $ */ public class PageFilter extends SiteMeshFilter { } sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/filter/PageResponseWrapper.java0000644000175000017500000001503010372637722033413 0ustar twernertwerner/* This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh.filter; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParserSelector; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.IOException; import java.io.PrintWriter; /** * Implementation of HttpServletResponseWrapper that captures page data instead of * sending to the writer. *

    *

    Should be used in filter-chains or when forwarding/including pages * using a RequestDispatcher.

    * * @author Joe Walnes * @author Scott Farquhar * @version $Revision: 1.17 $ */ public class PageResponseWrapper extends HttpServletResponseWrapper { private final RoutablePrintWriter routablePrintWriter; private final RoutableServletOutputStream routableServletOutputStream; private final PageParserSelector parserSelector; private Buffer buffer; private boolean aborted = false; private boolean parseablePage = false; public PageResponseWrapper(final HttpServletResponse response, PageParserSelector parserSelector) { super(response); this.parserSelector = parserSelector; routablePrintWriter = new RoutablePrintWriter(new RoutablePrintWriter.DestinationFactory() { public PrintWriter activateDestination() throws IOException { return response.getWriter(); } }); routableServletOutputStream = new RoutableServletOutputStream(new RoutableServletOutputStream.DestinationFactory() { public ServletOutputStream create() throws IOException { return response.getOutputStream(); } }); } /** * Set the content-type of the request and store it so it can * be passed to the {@link com.opensymphony.module.sitemesh.PageParser}. */ public void setContentType(String type) { super.setContentType(type); if (type != null) { HttpContentType httpContentType = new HttpContentType(type); if (parserSelector.shouldParsePage(httpContentType.getType())) { activateSiteMesh(httpContentType.getType(), httpContentType.getEncoding()); } else { deactivateSiteMesh(); } } } public void activateSiteMesh(String contentType, String encoding) { if (parseablePage) { return; // already activated } buffer = new Buffer(parserSelector.getPageParser(contentType), encoding); routablePrintWriter.updateDestination(new RoutablePrintWriter.DestinationFactory() { public PrintWriter activateDestination() { return buffer.getWriter(); } }); routableServletOutputStream.updateDestination(new RoutableServletOutputStream.DestinationFactory() { public ServletOutputStream create() { return buffer.getOutputStream(); } }); parseablePage = true; } private void deactivateSiteMesh() { parseablePage = false; buffer = null; routablePrintWriter.updateDestination(new RoutablePrintWriter.DestinationFactory() { public PrintWriter activateDestination() throws IOException { return getResponse().getWriter(); } }); routableServletOutputStream.updateDestination(new RoutableServletOutputStream.DestinationFactory() { public ServletOutputStream create() throws IOException { return getResponse().getOutputStream(); } }); } /** * Prevent content-length being set if page is parseable. */ public void setContentLength(int contentLength) { if (!parseablePage) super.setContentLength(contentLength); } /** * Prevent buffer from being flushed if this is a page being parsed. */ public void flushBuffer() throws IOException { if (!parseablePage) super.flushBuffer(); } /** * Prevent content-length being set if page is parseable. */ public void setHeader(String name, String value) { if (name.toLowerCase().equals("content-type")) { // ensure ContentType is always set through setContentType() setContentType(value); } else if (!parseablePage || !name.toLowerCase().equals("content-length")) { super.setHeader(name, value); } } /** * Prevent content-length being set if page is parseable. */ public void addHeader(String name, String value) { if (name.toLowerCase().equals("content-type")) { // ensure ContentType is always set through setContentType() setContentType(value); } else if (!parseablePage || !name.toLowerCase().equals("content-length")) { super.addHeader(name, value); } } /** * If 'not modified' (304) HTTP status is being sent - then abort parsing, as there shouldn't be any body */ public void setStatus(int sc) { if (sc == HttpServletResponse.SC_NOT_MODIFIED) { aborted = true; // route any content back to the original writer. There shouldn't be any content, but just to be safe deactivateSiteMesh(); } super.setStatus(sc); } public ServletOutputStream getOutputStream() { return routableServletOutputStream; } public PrintWriter getWriter() { return routablePrintWriter; } public Page getPage() throws IOException { if (aborted || !parseablePage) { return null; } else { return buffer.parse(); } } public void sendError(int sc) throws IOException { aborted = true; super.sendError(sc); } public void sendError(int sc, String msg) throws IOException { aborted = true; super.sendError(sc, msg); } public void sendRedirect(String location) throws IOException { aborted = true; super.sendRedirect(location); } public boolean isUsingStream() { return buffer != null && buffer.isUsingStream(); } public char[] getContents() throws IOException { if (aborted || !parseablePage) { return null; } else { return buffer.getContents(); } } }sitemesh-2.4.1+dfsg.orig/src/java/com/opensymphony/module/sitemesh/DecoratorMapper.java0000644000175000017500000000357010060331354031251 0ustar twernertwerner/* * Title: DecoratorMapper * Description: * * This software is published under the terms of the OpenSymphony Software * License version 1.1, of which a copy has been included with this * distribution in the LICENSE.txt file. */ package com.opensymphony.module.sitemesh; import javax.servlet.http.HttpServletRequest; import java.util.Properties; /** * The DecoratorMapper is responsible for determining which * {@link com.opensymphony.module.sitemesh.Decorator} should be used for a * {@link com.opensymphony.module.sitemesh.Page}. * *

    Implementations of this are returned by the {@link com.opensymphony.module.sitemesh.Factory}, * and should be thread-safe.

    * * @author Joe Walnes * @version $Revision: 1.2 $ */ public interface DecoratorMapper { /** * Initialize the mapper. This is always called before the other methods. * * @param config Config supplied by Servlet or Filter. * @param properties Any initialization properties (specific to implementation). * @exception java.lang.InstantiationException should be thrown if the implementation * cannot be initialized properly. */ void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException; /** * Return appropriate {@link com.opensymphony.module.sitemesh.Decorator} for a certain Page. * *

    The implementation can determine the result based on the actual request * or the data of the parsed page. Typically this would call getNamedDecorator() * which would delegate to a parent DecoratorMapper.

    * */ Decorator getDecorator(HttpServletRequest request, Page page); /** Return a {@link com.opensymphony.module.sitemesh.Decorator} with given name. */ Decorator getNamedDecorator(HttpServletRequest request, String name); }sitemesh-2.4.1+dfsg.orig/src/example-webapp/0000755000175000017500000000000011157130032020642 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/example-webapp/inline.jsp0000644000175000017500000000124710051427526022653 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %> Inline decorator example

    This is a sample of an inline decorator.

    Inline content Some inline stuff. Some more inline stuff.

    This is a sample of an inline decorator accessing external content.

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/freemarker.html0000644000175000017500000000031010045376354023663 0ustar twernertwerner Freemarker Test

    This page is decorated by the FreemarkerDecoratorServlet.

    Go back.

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/velocity.html0000644000175000017500000000030410036472056023375 0ustar twernertwerner Velocity Test

    This page is decorated by the VelocityDecoratorServlet.

    Go back.

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/meta.html0000644000175000017500000000030107751471036022471 0ustar twernertwerner META Test

    You shouldn't be seeing this page for long.

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/toggledecorator.jsp0000644000175000017500000000150607751471036024567 0ustar twernertwerner<%! boolean toggle; %> Toggled Decorator "> <% toggle = !toggle; %>

    This page is an example of how a Decorator can be chosen by the actual page itself.

    Within the HTML is a <meta> tag that states which Decorator to use. A bit of JSP alternates the value of this tag on each request.

    The top of the page looks like this:

    <%! boolean toggle; %>
    <html>
      <head>
        <title>Toggled Decorator</title>
        <meta name="decorator" content="<%= toggle ? "black" : "main" %>">
        <% toggle = !toggle; %>
      </head>
      ...
    		

    Refresh this page! (and again and again)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/agent.jsp0000644000175000017500000000027307751471036022501 0ustar twernertwerner Agent Test

    This page will have a different decorator applied depending on the browser being used to access it.

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/WEB-INF/0000755000175000017500000000000011157130032021671 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/example-webapp/WEB-INF/decorators.xml0000644000175000017500000000172410076770024024576 0ustar twernertwerner /exclude.jsp /exclude/* /* /velocity.html /freemarker.html /agent.jsp sitemesh-2.4.1+dfsg.orig/src/example-webapp/WEB-INF/web.xml0000644000175000017500000000332410550354752023207 0ustar twernertwerner sitemesh com.opensymphony.sitemesh.webapp.SiteMeshFilter sitemesh /* sitemesh-velocity com.opensymphony.module.sitemesh.velocity.VelocityDecoratorServlet 10 sitemesh-freemarker com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet TemplatePath / default_encoding ISO-8859-1 1 sitemesh-velocity *.vm sitemesh-freemarker *.ftl sitemesh-page /WEB-INF/lib/sitemesh-page.tld sitemesh-decorator /WEB-INF/lib/sitemesh-decorator.tld sitemesh-2.4.1+dfsg.orig/src/example-webapp/WEB-INF/sitemesh.xml0000644000175000017500000000333610520674306024253 0ustar twernertwerner sitemesh-2.4.1+dfsg.orig/src/example-webapp/index.html0000644000175000017500000000161710045376354022662 0ustar twernertwerner SiteMesh Sample Site

    Welcome to the SiteMesh sample...

    Samples

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/counter-syntaxerror.jsp0000644000175000017500000000043107751471036025454 0ustar twernertwerner<%! int count=0; %> JSP counter The current count is... <%= ++count %> <% int foo=((Sttring)request.getAttribute("foo")).length(); %> sitemesh-2.4.1+dfsg.orig/src/example-webapp/badpanel.html0000644000175000017500000000135007751471036023316 0ustar twernertwerner SiteMesh Sample Site

    Welcome to the SiteMesh sample...

    Samples

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/badsource.html0000644000175000017500000000135007751471036023517 0ustar twernertwerner SiteMesh Sample Site

    Welcome to the SiteMesh sample...

    Samples

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/meta2.html0000644000175000017500000000017607751471036022565 0ustar twernertwerner META Test

    This page is where you were redirected!

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/0000755000175000017500000000000011157156474023031 5ustar twernertwernersitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/test-ns.jsp0000644000175000017500000000042210051427526025131 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Mysterious page..." />

    (Netscape version)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/badpanelsource.jsp0000644000175000017500000000323611157160306026527 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %> <decorator:title default="Mysterious page..." />

    You shouldn't see this page.
    <%--page:applyDecorator page="/random.pl" name="panel" /--%>
    <%-- Construct URL from page request and append 'printable=true' param --%> <% StringBuffer printUrl = new StringBuffer(); printUrl.append(request.getRequestURI()); printUrl.append("?printable=true"); if (request.getQueryString()!=null) { printUrl.append('&'); printUrl.append(request.getQueryString()); } %>

    [ printable version ]

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/printable.jsp0000644000175000017500000000045310051427526025520 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title />

    (printable version)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/test-opera.jsp0000644000175000017500000000041710051427526025623 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Mysterious page..." />

    (Opera version)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/test-ie.jsp0000644000175000017500000000041410051427526025107 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Mysterious page..." />

    (IE version)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/test-lynx.jsp0000644000175000017500000000041610051427526025506 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Mysterious page..." />

    (Lynx version)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/black.jsp0000644000175000017500000000055410051427524024614 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Mysterious page..." />


    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/velocity.vm0000644000175000017500000000063210036457440025224 0ustar twernertwerner Velocity Decorator - $title $head
    $title

    $body sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/nopanelsource.jsp0000644000175000017500000000323511157160306026414 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %> <decorator:title default="Mysterious page..." />

    You shouldn't be seeing this page.

    <%--page:applyDecorator page="/random.pl" name="panel" /--%>
    <%-- Construct URL from page request and append 'printable=true' param --%> <% StringBuffer printUrl = new StringBuffer(); printUrl.append(request.getRequestURI()); printUrl.append("?printable=true"); if (request.getQueryString()!=null) { printUrl.append('&'); printUrl.append(request.getQueryString()); } %>

    [ printable version ]

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/freemarker.ftl0000644000175000017500000000063110053076554025655 0ustar twernertwerner Freemarker Decorator - ${title} ${head}
    ${title}

    ${body} sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/main.css0000644000175000017500000000144607751471036024473 0ustar twernertwernerbody, td, p { font: normal x-small verdana, arial, helvetica, sans-serif; } .panelTitle { background-color: #003399; color:#eeeeee; font-weight: bold; border-color: #3366ff #000033 #000033 #3366ff; border-width: 1; border-style: solid; padding: 1; } .panelBody { background-color: #eeeeee; border-color: black; border-width: 0 1 1 1; border-style: solid; padding: 2; } #pageTitle { background-color: #003399; color:#eeeeee; font-weight: bold; font-size: large; border-color: #3366ff #000033 #000033 #3366ff; border-width: 1; border-style: solid; padding: 1; text-align: center; } #footer { background-color:#999999; font-size: xx-small; text-align: center; color: white; border-color: #666666 #cccccc #cccccc #666666; border-width: 1; border-style: solid; padding: 1; } sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/test.jsp0000644000175000017500000000042110051427526024512 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <decorator:title default="Mysterious page..." />

    (Default version)

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/main.jsp0000644000175000017500000000316611157157730024475 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %> <decorator:title default="Mysterious page..." />
    <%--page:applyDecorator page="/random.pl" name="panel" /--%>
    <%-- Construct URL from page request and append 'printable=true' param --%> <% StringBuffer printUrl = new StringBuffer(); printUrl.append(request.getRequestURI()); printUrl.append("?printable=true"); if (request.getQueryString()!=null) { printUrl.append('&'); printUrl.append(request.getQueryString()); } %>

    [ printable version ]

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/decorators/panel.jsp0000644000175000017500000000051710051427524024636 0ustar twernertwerner<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>

    sitemesh-2.4.1+dfsg.orig/src/example-webapp/tiny-panel.html0000644000175000017500000000016007751471036023626 0ustar twernertwerner I'm a panel Hello, I'm a tiny little panel. sitemesh-2.4.1+dfsg.orig/src/example-webapp/counter.jsp0000644000175000017500000000023107751471036023054 0ustar twernertwerner<%! int count=0; %> JSP counter The current count is... <%= ++count %> sitemesh-2.4.1+dfsg.orig/src/example-webapp/random.pl0000644000175000017500000000071707751471036022505 0ustar twernertwerner#!perl $n = int (rand 1000) + 1; $hour = (localtime)[2]; if ($hour > 3 && $hour < 12) { $t = "morning"; } elsif ($hour < 19) { $t = "afternoon"; } elsif ($hour < 21) { $t = "evening"; } else { $t = "night"; } print <<"EOF"; Content-type: text/html Random number $n The full power of Perl is being harnessed to generate the number of $n!

    Have a nice $t. EOF sitemesh-2.4.1+dfsg.orig/src/example-webapp/google.html0000644000175000017500000000057107751471036023030 0ustar twernertwerner Google search

    Google
    sitemesh-2.4.1+dfsg.orig/src/example-webapp/mandelbrot.pl0000644000175000017500000000141107751471036023344 0ustar twernertwerner#!perl sub mandelbrot { $Cols=79; $Lines=30; $MaxIter=16; $MinRe=-2.0; $MaxRe=1.0; $MinIm=-1.0; $MaxIm=1.0; @chars=(' ','.',',','-',':','/','=','H','O','A','M','%','&','$','#','@','_'); my $result = "\n"; for($Im=$MinIm;$Im<=$MaxIm;$Im+=($MaxIm-$MinIm)/$Lines) { for($Re=$MinRe;$Re<=$MaxRe;$Re+=($MaxRe-$MinRe)/$Cols) { $zr=$Re; $zi=$Im; for($n=0;$n<$MaxIter;$n++) { $a=$zr*$zr; $b=$zi*$zi; if($a+$b>4.0) { last; } $zi=2*$zr*$zi+$Im; $zr=$a-$b+$Re; } $result .= $chars[$n]; } $result .= "\n"; } $result; } my $m = mandelbrot(); print "Content-type: text/html\n\n"; print <<"EOF"; Perl Mandelbrot

    I am a Perl CGI

    			$m
    		
    EOF