Author: maschmid
Date: 2012-04-02 03:53:34 -0400 (Mon, 02 Apr 2012)
New Revision: 14457
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/
branches/community/Seam_2_3/examples-ee6/seamspace/pom.xml
branches/community/Seam_2_3/examples-ee6/seamspace/readme.txt
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/pom.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-deployment-structure.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-seam-space-ds.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/resources/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/resources/jboss-seam-space-ds.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/pom.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AccountPermission.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AuthenticationEvents.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogComment.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/CommentAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentServlet.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendComment.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Hash.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/HashGenerator.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ImagePermission.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Member.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberAccount.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberBlog.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberFriend.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberImage.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberRole.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureSearch.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ProfileAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/RegisterAction.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/ejb-jar.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/orm.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/persistence.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/security-rules.drl
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/import.sql
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/seam.properties
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/pom.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/BlogTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/RegisterTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/BlogTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/FriendRequestTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/LoginTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/RoleTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/SeleniumSeamSpaceTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/UserTest.java
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-ftest/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-ftest/testng.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-integration/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-integration/testng.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/WEB-INF/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/WEB-INF/components.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/seam.properties
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/pom.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/resources/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/resources/messages.properties
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/components.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/faces-config.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/pages.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/web.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blog.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blogentry.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/comment.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/createBlog.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendcomment.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendrequest.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/hashgen.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/home.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.page.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.page.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/bg_button.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/checkmark.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/cross.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/ellipsis.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/no_image.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/index.html
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/builder.js
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/bullet.gif
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/close.gif
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/closelabel.gif
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/effects.js
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.css
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.js
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/loading.gif
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/nextlabel.gif
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prevlabel.gif
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prototype.js
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/scriptaculous.js
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictures.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictureupload.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/profile.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register2.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.page.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.page.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security_error.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/advertising.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newpermission.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newrole.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newuser.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/cal-next.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/cal-prev.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/date.css
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/divider.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/manage_roles.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/manage_users.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/padlock.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.css
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/security.css
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/table_header.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/trash.png
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/template.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.page.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.page.xml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.xhtml
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/welcome.xhtml
Log:
add seamspace to the ee6 examples
Added: branches/community/Seam_2_3/examples-ee6/seamspace/pom.xml
===================================================================
--- branches/community/Seam_2_3/examples-ee6/seamspace/pom.xml
(rev 0)
+++ branches/community/Seam_2_3/examples-ee6/seamspace/pom.xml 2012-04-02 07:53:34 UTC
(rev 14457)
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.jboss.seam.examples-ee6</groupId>
+ <artifactId>seamspace</artifactId>
+ <parent>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>examples-ee6</artifactId>
+ <version>2.3.0.Beta2-SNAPSHOT</version>
+ </parent>
+ <packaging>pom</packaging>
+ <name>SeamSpace Example (EE6)</name>
+
+ <properties>
+ <example.name>seamspace</example.name>
+ </properties>
+
+ <modules>
+ <module>seamspace-ear</module>
+ <module>seamspace-ejb</module>
+ <module>seamspace-web</module>
+ <module>seamspace-tests</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+ <version>${project.version}</version>
+ <type>ejb</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-web</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ear</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
Added: branches/community/Seam_2_3/examples-ee6/seamspace/readme.txt
===================================================================
--- branches/community/Seam_2_3/examples-ee6/seamspace/readme.txt
(rev 0)
+++ branches/community/Seam_2_3/examples-ee6/seamspace/readme.txt 2012-04-02 07:53:34 UTC
(rev 14457)
@@ -0,0 +1,29 @@
+Seam Seamspace Example
+======================
+
+This example demonstrates Seam Security. It runs on JBoss AS as an EAR and
+Tomcat with Embedded JBoss as a WAR.
+
+To deploy the example to JBoss AS, follow these steps:
+
+* In the example root directory, run:
+
+ mvn clean package
+
+* Set JBOSS_HOME environment property.
+
+* In the seamspace-ear directory, run:
+
+ mvn jboss:hard-deploy
+
+* Open this URL in a web browser:
http://localhost:8080/seam-seamspace
+
+To deploy the example to Tomcat with Embedded JBoss, follow these steps:
+
+* In the example root directory, run:
+
+ mvn clean package -Ptomcat
+
+* Deploy the resulting war from seamspace-web/target directory to Tomcat manually.
+
+* Open this URL in a web browser:
http://localhost:8080/jboss-seam-seamspace
Added: branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/pom.xml
===================================================================
--- branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/pom.xml
(rev 0)
+++ branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/pom.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>seamspace</artifactId>
+ <groupId>org.jboss.seam.examples-ee6</groupId>
+ <version>2.3.0.Beta2-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ear</artifactId>
+ <packaging>ear</packaging>
+ <name>SeamSpace EAR Module (EE6)</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-web</artifactId>
+ <type>war</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+ <type>ejb</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam</artifactId>
+ <type>ejb</type>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xpp3</groupId>
+ <artifactId>xpp3_min</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>commons-digester</groupId>
+ <artifactId>commons-digester</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-core</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-compiler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-decisiontables</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-templates</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.jexcelapi</groupId>
+ <artifactId>jxl</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <finalName>seam-seamspace</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <version>6</version>
+ <defaultLibBundleDir>lib</defaultLibBundleDir>
+ <!-- Exclude eclipse generated application.xml and manually
modified jboss-app.xml during mvn build -->
+ <earSourceExcludes>**/application.xml,
**/jboss-app.xml</earSourceExcludes>
+ <!-- use maven generated application.xml instead -->
+ <generateApplicationXml>true</generateApplicationXml>
+ <filtering>true</filtering>
+ <modules>
+ <webModule>
+
<groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-web</artifactId>
+ <contextRoot>/seam-seamspace</contextRoot>
+
<bundleFileName>seamspace-web.war</bundleFileName>
+ </webModule>
+ <ejbModule>
+
<groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+
<bundleFileName>seamspace-ejb.jar</bundleFileName>
+ </ejbModule>
+ </modules>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>exploded</id>
+ <properties>
+ <example.name>seamspace</example.name>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <phase>package</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+
<groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+
<artifactId>seamspace-ear</artifactId>
+ <type>ear</type>
+ <overWrite>true</overWrite>
+
<outputDirectory>${project.build.directory}/${project.build.finalName}-exploded/${project.build.finalName}.ear</outputDirectory>
+ </artifactItem>
+ <artifactItem>
+
<groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+
<artifactId>seamspace-web</artifactId>
+ <type>war</type>
+ <overWrite>true</overWrite>
+
<outputDirectory>${project.build.directory}/${project.build.finalName}-exploded/${project.build.finalName}.ear/${example.name}-web.war</outputDirectory>
+ </artifactItem>
+ <artifactItem>
+
<groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+
<artifactId>seamspace-ejb</artifactId>
+ <type>jar</type>
+ <overWrite>true</overWrite>
+
<outputDirectory>${project.build.directory}/${project.build.finalName}-exploded/${project.build.finalName}.ear/${example.name}-ejb.jar</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-deployment-structure.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-deployment-structure.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-deployment-structure.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,10 @@
+<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
+ <deployment>
+ <dependencies>
+ <module name="org.antlr" export="true"/>
+ <module name="org.dom4j" export="true"/>
+ <module name="javax.faces.api" export="true"/>
+ <module name="com.sun.jsf-impl" export="true"/>
+ </dependencies>
+ </deployment>
+</jboss-deployment-structure>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-seam-space-ds.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-seam-space-ds.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/application/META-INF/jboss-seam-space-ds.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<datasources
xmlns="http://www.jboss.org/ironjacamar/schema">
+ <datasource
+ jndi-name="java:/seamspaceDatasource"
+ enabled="true"
+ use-java-context="true" pool-name="seamspacedb">
+
<connection-url>jdbc:h2:mem:seamspacedb;DB_CLOSE_DELAY=-1</connection-url>
+ <driver>h2</driver>
+ <security>
+ <user-name>sa</user-name>
+ <password>sa</password>
+ </security>
+ </datasource>
+</datasources>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/resources/jboss-seam-space-ds.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/resources/jboss-seam-space-ds.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ear/src/main/resources/jboss-seam-space-ds.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE datasources
+ PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
+ "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
+
+<datasources>
+ <local-tx-datasource>
+ <jndi-name>seamspaceDatasource</jndi-name>
+ <connection-url>jdbc:hsqldb:.</connection-url>
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ </local-tx-datasource>
+</datasources>
+
Added: branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/pom.xml
===================================================================
--- branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/pom.xml
(rev 0)
+++ branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/pom.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>seamspace</artifactId>
+ <groupId>org.jboss.seam.examples-ee6</groupId>
+ <version>2.3.0.Beta2-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+ <packaging>ejb</packaging>
+ <name>SeamSpace EJB Module (EE6)</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam</artifactId>
+ <type>ejb</type>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>ejb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-core</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-compiler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-decisiontables</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-templates</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.jexcelapi</groupId>
+ <artifactId>jxl</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AccountPermission.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AccountPermission.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AccountPermission.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,81 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.jboss.seam.annotations.security.permission.PermissionAction;
+import org.jboss.seam.annotations.security.permission.PermissionDiscriminator;
+import org.jboss.seam.annotations.security.permission.PermissionRole;
+import org.jboss.seam.annotations.security.permission.PermissionTarget;
+import org.jboss.seam.annotations.security.permission.PermissionUser;
+
+@Entity
+public class AccountPermission implements Serializable
+{
+ private static final long serialVersionUID = -5628863031792429938L;
+
+ private Integer permissionId;
+ private String recipient;
+ private String target;
+ private String action;
+ private String discriminator;
+
+ @Id @GeneratedValue
+ public Integer getPermissionId()
+ {
+ return permissionId;
+ }
+
+ public void setPermissionId(Integer permissionId)
+ {
+ this.permissionId = permissionId;
+ }
+
+ @PermissionUser
+ @PermissionRole
+ public String getRecipient()
+ {
+ return recipient;
+ }
+
+ public void setRecipient(String recipient)
+ {
+ this.recipient = recipient;
+ }
+
+ @PermissionTarget
+ public String getTarget()
+ {
+ return target;
+ }
+
+ public void setTarget(String target)
+ {
+ this.target = target;
+ }
+
+ @PermissionAction
+ public String getAction()
+ {
+ return action;
+ }
+
+ public void setAction(String action)
+ {
+ this.action = action;
+ }
+
+ @PermissionDiscriminator
+ public String getDiscriminator()
+ {
+ return discriminator;
+ }
+
+ public void setDiscriminator(String discriminator)
+ {
+ this.discriminator = discriminator;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AuthenticationEvents.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AuthenticationEvents.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/AuthenticationEvents.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,16 @@
+package org.jboss.seam.example.seamspace;
+
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Observer;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.security.management.JpaIdentityStore;
+
+@Name("authenticationEvents")
+public class AuthenticationEvents
+{
+ @Observer(JpaIdentityStore.EVENT_USER_AUTHENTICATED)
+ public void loginSuccessful(MemberAccount account)
+ {
+ Contexts.getSessionContext().set("authenticatedMember",
account.getMember());
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,88 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+
+import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.End;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Out;
+import org.jboss.seam.annotations.Scope;
+
+@Scope(CONVERSATION)
+@Name("blog")
+public class BlogAction
+{
+ private String name;
+ private Integer blogId;
+
+ @In
+ private EntityManager entityManager;
+
+ @In(required = false) @Out(required = false)
+ private MemberBlog selectedBlog;
+
+ @In(required = false)
+ private Member authenticatedMember;
+
+ /**
+ * Used to read a single blog entry for a member
+ */
+ @Factory("selectedBlog")
+ @Begin(join=true)
+ public void getBlog()
+ {
+ try
+ {
+ selectedBlog = (MemberBlog) entityManager.createQuery(
+ "from MemberBlog b where b.blogId = :blogId and b.member.memberName =
:memberName")
+ .setParameter("blogId", blogId)
+ .setParameter("memberName", name)
+ .getSingleResult();
+ }
+ catch (NoResultException ex) { }
+ }
+
+ @Begin
+ public void createEntry()
+ {
+ selectedBlog = new MemberBlog();
+ }
+
+ @End
+ public void saveEntry()
+ {
+ selectedBlog.setMember(authenticatedMember);
+ selectedBlog.setEntryDate(new Date());
+ selectedBlog.setComments(new ArrayList<BlogComment>());
+
+ entityManager.persist(selectedBlog);
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public Integer getBlogId()
+ {
+ return blogId;
+ }
+
+ public void setBlogId(Integer blogId)
+ {
+ this.blogId = blogId;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogComment.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogComment.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/BlogComment.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,96 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.Transient;
+
+import javax.validation.constraints.NotNull;
+import org.jboss.seam.annotations.Name;
+
+@Entity
+@Name("blogComment")
+public class BlogComment implements Serializable
+{
+ private static final long serialVersionUID = 5495139096911872039L;
+
+ private static SimpleDateFormat df = new SimpleDateFormat("EEEE, MMMM d, yyyy
'at' hh:mm a");
+
+ private Integer commentId;
+ private MemberBlog blog;
+ private Member commentor;
+ private Date commentDate;
+ private String comment;
+
+ @Id @GeneratedValue
+ public Integer getCommentId()
+ {
+ return commentId;
+ }
+
+ public void setCommentId(Integer commentId)
+ {
+ this.commentId = commentId;
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "BLOG_ID")
+ public MemberBlog getBlog()
+ {
+ return blog;
+ }
+
+ public void setBlog(MemberBlog blog)
+ {
+ this.blog = blog;
+ }
+
+ @NotNull
+ @Lob
+ public String getComment()
+ {
+ return comment;
+ }
+ public void setComment(String comment)
+ {
+ this.comment = comment;
+ }
+
+ @NotNull
+ public Date getCommentDate()
+ {
+ return commentDate;
+ }
+
+ public void setCommentDate(Date commentDate)
+ {
+ this.commentDate = commentDate;
+ }
+
+ @Transient
+ public String getFormattedCommentDate()
+ {
+ return df.format(commentDate);
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "COMMENTOR_ID")
+ public Member getCommentor()
+ {
+ return commentor;
+ }
+
+ public void setCommentor(Member commentor)
+ {
+ this.commentor = commentor;
+ }
+
+
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/CommentAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/CommentAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/CommentAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,55 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.Transactional;
+import org.jboss.seam.annotations.security.Insert;
+import org.jboss.seam.core.Conversation;
+
+@Scope(CONVERSATION)
+@Name("commentAction")
+@Transactional
+public class CommentAction
+{
+ @In
+ private EntityManager entityManager;
+
+ private BlogComment comment;
+
+ @In(required = false)
+ private Member authenticatedMember;
+
+ @In(required = false)
+ private MemberBlog selectedBlog;
+
+ @Begin(nested = true) @Insert(BlogComment.class)
+ public void createComment()
+ {
+ comment = new BlogComment();
+ comment.setCommentor(authenticatedMember);
+ comment.setBlog(selectedBlog);
+ }
+
+ public void saveComment()
+ {
+ comment.setCommentDate(new Date());
+ entityManager.persist(comment);
+
+ entityManager.refresh(selectedBlog);
+
+ Conversation.instance().end();
+ }
+
+ public BlogComment getComment()
+ {
+ return comment;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,27 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.STATELESS;
+
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.security.Identity;
+
+@Scope(STATELESS)
+@Name("contentAction")
+public class ContentAction
+{
+ @In EntityManager entityManager;
+
+ public MemberImage getImage(int imageId)
+ {
+ MemberImage img = entityManager.find(MemberImage.class, imageId);
+
+ if (img == null || !Identity.instance().hasPermission(img, "view"))
+ return null;
+ else
+ return img;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentServlet.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentServlet.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ContentServlet.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,137 @@
+package org.jboss.seam.example.seamspace;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.swing.ImageIcon;
+
+import org.jboss.seam.Component;
+
+/**
+ * Serves images and other member content
+ *
+ * @author Shane Bryzak
+ */
+public class ContentServlet extends HttpServlet
+{
+ private static final long serialVersionUID = -8461940507242022217L;
+
+ private static final String IMAGES_PATH = "/images";
+
+ /**
+ * The maximum width allowed for image rescaling
+ */
+ private static final int MAX_IMAGE_WIDTH = 1024;
+
+ private byte[] noImage;
+
+ public ContentServlet()
+ {
+ InputStream in = getClass().getResourceAsStream("/images/no_image.png");
+ if (in != null)
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buffer = new byte[512];
+ try
+ {
+ int read = in.read(buffer);
+ while (read != -1)
+ {
+ out.write(buffer, 0, read);
+ read = in.read(buffer);
+ }
+
+ noImage = out.toByteArray();
+ }
+ catch (IOException e) { }
+ }
+
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ if (IMAGES_PATH.equals(request.getPathInfo()))
+ {
+ ContentAction contentAction = (ContentAction)
Component.getInstance(ContentAction.class);
+
+ String id = request.getParameter("id");
+ MemberImage mi = (id != null && !"".equals(id)) ?
+ contentAction.getImage(Integer.parseInt(id)) : null;
+
+ String contentType = null;
+ byte[] data = null;
+
+ if (mi != null && mi.getData() != null && mi.getData().length
> 0)
+ {
+ contentType = mi.getContentType();
+ data = mi.getData();
+ }
+ else if (noImage != null)
+ {
+ contentType = "image/png";
+ data = noImage;
+ }
+
+ if (data != null)
+ {
+ response.setContentType(contentType);
+
+ boolean rescale = false;
+ int width = 0;
+ ImageIcon icon = null;
+
+ // Check if the image needs to be rescaled
+ if (request.getParameter("width") != null)
+ {
+ width = Math.min(MAX_IMAGE_WIDTH, Integer.parseInt(request
+ .getParameter("width")));
+ icon = new ImageIcon(data);
+ if (width > 0 && width != icon.getIconWidth())
+ rescale = true;
+ }
+
+ // Rescale the image if required
+ if (rescale)
+ {
+ double ratio = (double) width / icon.getIconWidth();
+ int height = (int) (icon.getIconHeight() * ratio);
+
+ int imageType = "image/png".equals(contentType) ?
+ BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
+ BufferedImage bImg = new BufferedImage(width, height, imageType);
+ Graphics2D g2d = bImg.createGraphics();
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ g2d.drawImage(icon.getImage(), 0, 0, width, height, null);
+ g2d.dispose();
+
+ String formatName = "";
+ if (contentType != null && contentType.indexOf("png") !=
-1)
+ formatName = "png";
+ else if (contentType != null &&
(contentType.indexOf("jpg") != -1) ||
+ contentType.indexOf("jpeg") != -1)
+ formatName = "jpeg";
+
+ ImageIO.write(bImg, formatName, response.getOutputStream());
+ }
+ else
+ {
+ response.getOutputStream().write(data);
+ }
+ }
+
+ response.getOutputStream().flush();
+ }
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,109 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.ejb.Remove;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+
+import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.Destroy;
+import org.jboss.seam.annotations.End;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Out;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.faces.FacesMessages;
+import org.jboss.seam.security.Identity;
+
+@Scope(CONVERSATION)
+@Name("friendAction")
+public class FriendAction implements Serializable
+{
+ private static final long serialVersionUID = 4565339001481077911L;
+
+ @RequestParameter("name")
+ private String name;
+
+ @Out(required = false)
+ private FriendComment friendComment;
+
+ @Out(required = false)
+ private MemberFriend friendRequest;
+
+ @In(required = false)
+ private Member authenticatedMember;
+
+ @In
+ private EntityManager entityManager;
+
+ @Factory("friendComment") @Begin
+ public void createComment()
+ {
+ try
+ {
+ Member member = (Member) entityManager.createQuery(
+ "from Member where memberName = :memberName")
+ .setParameter("memberName", name)
+ .getSingleResult();
+
+ Contexts.getMethodContext().set("friends", member.getFriends());
+ Identity.instance().checkPermission(member, "createFriendComment");
+
+ friendComment = new FriendComment();
+ friendComment.setFriend(authenticatedMember);
+ friendComment.setMember(member);
+ }
+ catch (NoResultException ex)
+ {
+ FacesMessages.instance().add("Member not found.");
+ }
+ }
+
+ @End
+ public void saveComment()
+ {
+ friendComment.setCommentDate(new Date());
+ entityManager.persist(friendComment);
+ }
+
+ @Begin
+ public void createRequest()
+ {
+ try
+ {
+ Member member = (Member) entityManager.createQuery(
+ "from Member where memberName = :memberName")
+ .setParameter("memberName", name)
+ .getSingleResult();
+
+ Contexts.getMethodContext().set("friends", member.getFriends());
+ Identity.instance().checkPermission(member, "createFriendRequest");
+
+ friendRequest = new MemberFriend();
+ friendRequest.setFriend(authenticatedMember);
+ friendRequest.setMember(member);
+ }
+ catch (NoResultException ex)
+ {
+ FacesMessages.instance().add("Member not found.");
+ }
+ }
+
+ @End
+ public void saveRequest()
+ {
+ friendRequest.getMember().getFriends().add(friendRequest);
+ entityManager.persist(friendRequest);
+ FacesMessages.instance().add("Friend request sent");
+ }
+
+ @Remove @Destroy
+ public void destroy() { }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendComment.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendComment.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/FriendComment.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,91 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Transient;
+
+import org.jboss.seam.annotations.Name;
+
+@Entity
+@Name("friendComment")
+public class FriendComment implements Serializable
+{
+ private static final long serialVersionUID = -288494386341008371L;
+
+ private static SimpleDateFormat df = new SimpleDateFormat("d MMMM yyyy hh:mm
a");
+
+ private Integer id;
+ private Member member;
+ private Member friend;
+ private Date commentDate;
+ private String comment;
+
+ @Id @GeneratedValue
+ public Integer getId()
+ {
+ return id;
+ }
+
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+ public String getComment()
+ {
+ return comment;
+ }
+
+ public void setComment(String comment)
+ {
+ this.comment = comment;
+ }
+
+ public Date getCommentDate()
+ {
+ return commentDate;
+ }
+
+ public void setCommentDate(Date commentDate)
+ {
+ this.commentDate = commentDate;
+ }
+
+ @Transient
+ public String getFormattedCommentDate()
+ {
+ return df.format(commentDate);
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "FRIEND_ID")
+ public Member getFriend()
+ {
+ return friend;
+ }
+
+ public void setFriend(Member friend)
+ {
+ this.friend = friend;
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "MEMBER_ID")
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public void setMember(Member member)
+ {
+ this.member = member;
+ }
+
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Hash.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Hash.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Hash.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,45 @@
+package org.jboss.seam.example.seamspace;
+
+import java.security.MessageDigest;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.util.Hex;
+
+@Name("hash")
+public class Hash {
+ String hashFunction = "MD5";
+ String charset = "UTF-8";
+
+ public String hash(String password) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(hashFunction);
+ md.update(password.getBytes(charset));
+ byte[] raw = md.digest();
+ return new String(Hex.encodeHex(raw));
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getCharset() {
+ return charset;
+ }
+
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+ public String getHashFunction() {
+ return hashFunction;
+ }
+
+ public void setHashFunction(String hashFunction) {
+ this.hashFunction = hashFunction;
+ }
+
+ public static Hash instance() {
+ return (Hash) Component.getInstance(Hash.class);
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/HashGenerator.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/HashGenerator.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/HashGenerator.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,78 @@
+package org.jboss.seam.example.seamspace;
+
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.security.crypto.BinTools;
+import org.jboss.seam.security.management.JpaIdentityStore;
+import org.jboss.seam.security.management.PasswordHash;
+
+(a)Scope(ScopeType.EVENT)
+@Name("hashgenerator")
+public class HashGenerator
+{
+ @In JpaIdentityStore identityStore;
+
+ private String password;
+ private String passwordHash;
+ private String passwordSalt;
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getPasswordHash()
+ {
+ return passwordHash;
+ }
+
+ public void setPasswordHash(String passwordHash)
+ {
+ this.passwordHash = passwordHash;
+ }
+
+ public String getPasswordSalt()
+ {
+ return passwordSalt;
+ }
+
+ public void setPasswordSalt(String passwordSalt)
+ {
+ this.passwordSalt = passwordSalt;
+ }
+
+ public void generate()
+ {
+ byte[] salt;
+
+ if (passwordSalt == null || "".equals(passwordSalt.trim()))
+ {
+ salt = PasswordHash.instance().generateRandomSalt();
+ passwordSalt = BinTools.bin2hex(salt);
+ }
+ else
+ {
+ salt = BinTools.hex2bin(passwordSalt);
+ }
+
+ passwordHash = identityStore.generatePasswordHash(password, salt);
+ }
+
+ public String getSql()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("INSERT INTO USER_ACCOUNT (username, password_hash, password_salt)
values ('johnsmith', '");
+ sb.append(passwordHash);
+ sb.append("', '");
+ sb.append(passwordSalt);
+ sb.append("');");
+ return sb.toString();
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ImagePermission.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ImagePermission.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ImagePermission.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,200 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.core.Conversation;
+import org.jboss.seam.faces.FacesMessages;
+import org.jboss.seam.security.Role;
+import org.jboss.seam.security.SimplePrincipal;
+import org.jboss.seam.security.management.IdentityManager;
+import org.jboss.seam.security.permission.Permission;
+import org.jboss.seam.security.permission.PermissionManager;
+import org.jboss.seam.security.permission.action.PermissionSearch;
+
+@Name("imagePermission")
+@Scope(CONVERSATION)
+public class ImagePermission implements Serializable
+{
+ private static final long serialVersionUID = -4943654157860780587L;
+
+ private List<String> selectedRoles;
+ private List<Member> selectedFriends;
+ private List<String> selectedActions;
+
+ private List<String> originalActions;
+
+ private List<Member> availableFriends;
+
+ @In IdentityManager identityManager;
+ @In PermissionManager permissionManager;
+
+ @In EntityManager entityManager;
+
+ @In PermissionSearch permissionSearch;
+
+ private MemberImage target;
+
+ private Principal recipient;
+
+ @SuppressWarnings("unchecked")
+ @Begin(nested = true)
+ public void createPermission()
+ {
+ target = (MemberImage) permissionSearch.getTarget();
+
+ selectedFriends = new ArrayList<Member>();
+
+ availableFriends = entityManager.createQuery(
+ "select f.friend from MemberFriend f where f.member = :member and
f.authorized = true")
+ .setParameter("member", target.getMember())
+ .getResultList();
+ }
+
+ @Begin(nested = true)
+ public void editPermission()
+ {
+ target = (MemberImage) permissionSearch.getTarget();
+ recipient = permissionSearch.getSelectedRecipient();
+
+ List<Permission> permissions = permissionManager.listPermissions(target);
+
+ selectedActions = new ArrayList<String>();
+
+ for (Permission permission : permissions)
+ {
+ if (permission.getRecipient().equals(recipient))
+ {
+ if (!selectedActions.contains(permission.getAction()))
+ {
+ selectedActions.add(permission.getAction());
+ }
+ }
+ }
+
+ originalActions = new ArrayList<String>(selectedActions);
+ }
+
+ public List<String> getSelectedRoles()
+ {
+ return selectedRoles;
+ }
+
+ public void setSelectedRoles(List<String> selectedRoles)
+ {
+ this.selectedRoles = selectedRoles;
+ }
+
+ public List<Member> getSelectedFriends()
+ {
+ return selectedFriends;
+ }
+
+ public void setSelectedFriends(List<Member> selectedFriends)
+ {
+ this.selectedFriends = selectedFriends;
+ }
+
+ public List<String> getSelectedActions()
+ {
+ return selectedActions;
+ }
+
+ public void setSelectedActions(List<String> selectedActions)
+ {
+ this.selectedActions = selectedActions;
+ }
+
+ public String applyPermissions()
+ {
+ // If the recipient isn't null, it means we're editing existing
permissions
+ if (recipient != null)
+ {
+ List<Permission> grantedPermissions = new ArrayList<Permission>();
+ List<Permission> revokedPermissions = new ArrayList<Permission>();
+
+ for (String action : selectedActions)
+ {
+ if (!originalActions.contains(action))
+ {
+ grantedPermissions.add(new Permission(target, action, recipient));
+ }
+ }
+
+ for (String action : originalActions)
+ {
+ if (!selectedActions.contains(action))
+ {
+ revokedPermissions.add(new Permission(target, action, recipient));
+ }
+ }
+
+ if (!grantedPermissions.isEmpty())
permissionManager.grantPermissions(grantedPermissions);
+ if (!revokedPermissions.isEmpty())
permissionManager.revokePermissions(revokedPermissions);
+ }
+ // otherwise this is a set of new permissions
+ else
+ {
+ if (selectedActions.size() == 0)
+ {
+ FacesMessages.instance().add("You must select at least one
action");
+ return "failure";
+ }
+
+ List<Permission> permissions = new ArrayList<Permission>();
+
+ for (String role : selectedRoles)
+ {
+ Principal r = new Role(role);
+ for (String action : selectedActions)
+ {
+ permissions.add(new Permission(target, action, r));
+ }
+ }
+
+ for (Member friend : selectedFriends)
+ {
+ MemberAccount acct = (MemberAccount) entityManager.createQuery(
+ "select a from MemberAccount a where a.member = :member")
+ .setParameter("member", friend)
+ .getSingleResult();
+
+ Principal p = new SimplePrincipal(acct.getUsername());
+
+ for (String action : selectedActions)
+ {
+ permissions.add(new Permission(target, action, p));
+ }
+ }
+
+ permissionManager.grantPermissions(permissions);
+ }
+ Conversation.instance().endBeforeRedirect();
+ return "success";
+ }
+
+ public List<Member> getAvailableFriends()
+ {
+ return availableFriends;
+ }
+
+ public MemberImage getTarget()
+ {
+ return target;
+ }
+
+ public Principal getRecipient()
+ {
+ return recipient;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Member.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Member.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/Member.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,253 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.validator.constraints.Email;
+import javax.validation.constraints.Size;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+import org.jboss.seam.annotations.Name;
+
+/**
+ * A member account
+ *
+ * @author Shane Bryzak
+ */
+@Entity
+@Name("member")
+@Table(uniqueConstraints = @UniqueConstraint(columnNames = "membername"))
+public class Member implements Serializable
+{
+ private static final long serialVersionUID = 5179242727836683375L;
+
+ public enum Gender {
+ male("Male", "his"),
+ female("Female", "her");
+
+ private String descr;
+ private String possessive;
+
+ Gender(String descr, String possessive) {
+ this.descr = descr;
+ this.possessive = possessive;
+ }
+ public String getDescr() {
+ return descr;
+ }
+
+ public String getPossessive() {
+ return possessive;
+ }
+ };
+
+ private Integer memberId;
+ private String memberName;
+ private String firstName;
+ private String lastName;
+ private String email;
+ private MemberImage picture;
+
+ private String tagline;
+ private Gender gender;
+ private Date dob;
+ private String location;
+ private Date memberSince;
+
+ private Set<MemberImage> images;
+ private Set<MemberFriend> friends;
+
+ @Id @GeneratedValue
+ public Integer getMemberId()
+ {
+ return memberId;
+ }
+
+ public void setMemberId(Integer memberId)
+ {
+ this.memberId = memberId;
+ }
+
+ @NotNull
+ @Size(min = 3, max = 40)
+ @Pattern(regexp="[a-zA-Z]?[a-zA-Z0-9_]+",
+ message="Member name must start with a letter, and only contain letters,
numbers or underscores")
+ public String getMemberName()
+ {
+ return memberName;
+ }
+
+ public void setMemberName(String memberName)
+ {
+ this.memberName = memberName;
+ }
+
+ @NotNull
+ @Size(min = 3, max = 40)
+ @Pattern(regexp="[a-zA-Z]+", message="First name must only contain
letters")
+ public String getFirstName()
+ {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName)
+ {
+ this.firstName = firstName;
+ }
+
+ @NotNull
+ @Size(min = 3, max = 40)
+ @Pattern(regexp="[a-zA-Z]+", message="Last name must only contain
letters")
+ public String getLastName()
+ {
+ return lastName;
+ }
+
+ public void setLastName(String lastName)
+ {
+ this.lastName = lastName;
+ }
+
+ @NotNull @Email
+ public String getEmail()
+ {
+ return email;
+ }
+
+ public void setEmail(String email)
+ {
+ this.email = email;
+ }
+
+ @OneToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "PICTURE_ID")
+ public MemberImage getPicture()
+ {
+ return picture;
+ }
+
+ public void setPicture(MemberImage picture)
+ {
+ this.picture = picture;
+ }
+
+ @NotNull
+ public Date getDob()
+ {
+ return dob;
+ }
+
+ public void setDob(Date dob)
+ {
+ this.dob = dob;
+ }
+
+ @NotNull
+ public Gender getGender()
+ {
+ return gender;
+ }
+
+ public void setGender(Gender gender)
+ {
+ this.gender = gender;
+ }
+
+ public String getLocation()
+ {
+ return location;
+ }
+
+ public void setLocation(String location)
+ {
+ this.location = location;
+ }
+
+ @NotNull
+ public Date getMemberSince()
+ {
+ return memberSince;
+ }
+
+ public void setMemberSince(Date memberSince)
+ {
+ this.memberSince = memberSince;
+ }
+
+ public String getTagline()
+ {
+ return tagline;
+ }
+
+ public void setTagline(String tagline)
+ {
+ this.tagline = tagline;
+ }
+
+ @OneToMany(mappedBy = "member", fetch = FetchType.LAZY)
+ public Set<MemberImage> getImages()
+ {
+ return images;
+ }
+
+ public void setImages(Set<MemberImage> images)
+ {
+ this.images = images;
+ }
+
+ @OneToMany(mappedBy = "member")
+ public Set<MemberFriend> getFriends()
+ {
+ return friends;
+ }
+
+ public void setFriends(Set<MemberFriend> friends)
+ {
+ this.friends = friends;
+ }
+
+ @Transient
+ public boolean isFriend(Member member)
+ {
+ for (MemberFriend f : friends)
+ {
+ if (f.getFriend().getMemberId().equals(member.getMemberId())) return true;
+ }
+
+ return false;
+ }
+
+ @Transient
+ public String getAge()
+ {
+ Calendar birthday = new GregorianCalendar();
+ birthday.setTime(dob);
+ int by = birthday.get(Calendar.YEAR);
+ int bm = birthday.get(Calendar.MONTH);
+ int bd = birthday.get(Calendar.DATE);
+
+ Calendar now = new GregorianCalendar();
+ now.setTimeInMillis(System.currentTimeMillis());
+ int ny = now.get(Calendar.YEAR);
+ int nm = now.get(Calendar.MONTH);
+ int nd = now.get(Calendar.DATE);
+
+ int age = ny - by + (nm > bm || (nm == bm && nd >= bd) ? 0 : -1);
+ return String.format("%d years old", age);
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberAccount.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberAccount.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberAccount.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,121 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import javax.validation.constraints.NotNull;
+
+import org.jboss.seam.annotations.security.management.PasswordSalt;
+import org.jboss.seam.annotations.security.management.UserEnabled;
+import org.jboss.seam.annotations.security.management.UserPassword;
+import org.jboss.seam.annotations.security.management.UserPrincipal;
+import org.jboss.seam.annotations.security.management.UserRoles;
+
+@Entity
+@Table(uniqueConstraints = @UniqueConstraint(columnNames = "username"))
+public class MemberAccount implements Serializable
+{
+ private static final long serialVersionUID = 6368734442192368866L;
+
+ private Integer accountId;
+ private String username;
+ private String passwordHash;
+ private String passwordSalt;
+ private boolean enabled;
+
+ private Set<MemberRole> roles;
+ private Member member;
+
+ @Id @GeneratedValue
+ public Integer getAccountId()
+ {
+ return accountId;
+ }
+
+ public void setAccountId(Integer accountId)
+ {
+ this.accountId = accountId;
+ }
+
+ @NotNull @UserPrincipal
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ @UserPassword
+ public String getPasswordHash()
+ {
+ return passwordHash;
+ }
+
+ public void setPasswordHash(String passwordHash)
+ {
+ this.passwordHash = passwordHash;
+ }
+
+ @PasswordSalt
+ public String getPasswordSalt()
+ {
+ return passwordSalt;
+ }
+
+ public void setPasswordSalt(String passwordSalt)
+ {
+ this.passwordSalt = passwordSalt;
+ }
+
+ @UserEnabled
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+ @UserRoles
+ @ManyToMany(targetEntity = MemberRole.class)
+ @JoinTable(name = "AccountMembership",
+ joinColumns = @JoinColumn(name = "AccountId"),
+ inverseJoinColumns = @JoinColumn(name = "MemberOf")
+ )
+ public Set<MemberRole> getRoles()
+ {
+ return roles;
+ }
+
+ public void setRoles(Set<MemberRole> roles)
+ {
+ this.roles = roles;
+ }
+
+ @OneToOne
+ @JoinColumn(name = "MEMBER_ID")
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public void setMember(Member member)
+ {
+ this.member = member;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberBlog.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberBlog.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberBlog.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,136 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.PrePersist;
+import javax.persistence.Transient;
+
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.security.Restrict;
+
+@Entity
+@Name("memberBlog")
+public class MemberBlog implements Serializable
+{
+ private static final long serialVersionUID = 7824113911888715595L;
+
+ private static SimpleDateFormat df = new SimpleDateFormat("EEEE, MMMM d, yyyy -
hh:mm a");
+
+ private Integer blogId;
+ private Member member;
+ private Date entryDate;
+ private String title;
+ private String text;
+
+ private List<BlogComment> comments;
+
+ /**
+ * This is an example of a security restriction. Any attempts to persist a
+ * new memberBlog instance requires the user to pass a permission check. In
+ * this case, because the method is annotated with
<code>@PrePersist</code>
+ * the required permission is memberBlog:insert
+ */
+ @PrePersist @Restrict
+ public void prePersist() {}
+
+ @Id @GeneratedValue
+ public Integer getBlogId()
+ {
+ return blogId;
+ }
+
+ public void setBlogId(Integer blogId)
+ {
+ this.blogId = blogId;
+ }
+
+ public Date getEntryDate()
+ {
+ return entryDate;
+ }
+
+ public void setEntryDate(Date entryDate)
+ {
+ this.entryDate = entryDate;
+ }
+
+ @Transient
+ public String getFormattedEntryDate()
+ {
+ return df.format(entryDate);
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "MEMBER_ID")
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public void setMember(Member member)
+ {
+ this.member = member;
+ }
+
+ @Lob
+ public String getText()
+ {
+ return text;
+ }
+
+ public void setText(String text)
+ {
+ this.text = text;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ @OneToMany(mappedBy = "blog")
+ public List<BlogComment> getComments()
+ {
+ return comments;
+ }
+
+ public void setComments(List<BlogComment> comments)
+ {
+ this.comments = comments;
+ }
+
+ @Transient
+ public List<BlogComment> getSortedComments()
+ {
+ Collections.sort(comments, new Comparator<BlogComment>() {
+ public int compare(BlogComment o1, BlogComment o2) {
+ return (int) (o1.getCommentDate().getTime() -
o2.getCommentDate().getTime());
+ }
+ });
+
+ return comments;
+ }
+
+ @Transient
+ public int getCommentCount()
+ {
+ return comments.size();
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberFriend.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberFriend.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberFriend.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,92 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+import org.jboss.seam.annotations.Name;
+
+@Entity
+@Name("memberFriend")
+public class MemberFriend implements Serializable
+{
+ private static final long serialVersionUID = -167586088947004386L;
+
+ private Integer id;
+ private Member member;
+ private Member friend;
+
+ private String introduction;
+ private String response;
+
+ private boolean authorized;
+
+ @Id @GeneratedValue
+ public Integer getId()
+ {
+ return id;
+ }
+
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+ public boolean isAuthorized()
+ {
+ return authorized;
+ }
+
+ public void setAuthorized(boolean authorized)
+ {
+ this.authorized = authorized;
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "FRIEND_ID")
+ public Member getFriend()
+ {
+ return friend;
+ }
+
+ public void setFriend(Member friend)
+ {
+ this.friend = friend;
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "MEMBER_ID")
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public void setMember(Member member)
+ {
+ this.member = member;
+ }
+
+ public String getIntroduction()
+ {
+ return introduction;
+ }
+
+ public void setIntroduction(String introduction)
+ {
+ this.introduction = introduction;
+ }
+
+ public String getResponse()
+ {
+ return response;
+ }
+
+ public void setResponse(String response)
+ {
+ this.response = response;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberImage.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberImage.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberImage.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,84 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+
+import org.jboss.seam.annotations.security.permission.Permission;
+import org.jboss.seam.annotations.security.permission.Permissions;
+
+@Permissions({
+ @Permission(action = "view"),
+ @Permission(action = "comment")
+})
+@Entity
+public class MemberImage implements Serializable
+{
+ private static final long serialVersionUID = -8088455267213832920L;
+
+ private Integer imageId;
+ private Member member;
+ private byte[] data;
+ private String contentType;
+ private String caption;
+
+ @Id @GeneratedValue
+ public Integer getImageId()
+ {
+ return imageId;
+ }
+
+ public void setImageId(Integer imageId)
+ {
+ this.imageId = imageId;
+ }
+
+ @ManyToOne
+ @JoinColumn(name = "MEMBER_ID")
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public void setMember(Member member)
+ {
+ this.member = member;
+ }
+
+ public String getContentType()
+ {
+ return contentType;
+ }
+
+ public void setContentType(String contentType)
+ {
+ this.contentType = contentType;
+ }
+
+ public String getCaption()
+ {
+ return caption;
+ }
+
+ public void setCaption(String caption)
+ {
+ this.caption = caption;
+ }
+
+ @Lob
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ public void setData(byte[] data)
+ {
+ this.data = data;
+ }
+
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberRole.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberRole.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/MemberRole.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,76 @@
+package org.jboss.seam.example.seamspace;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+
+import org.jboss.seam.annotations.security.management.RoleConditional;
+import org.jboss.seam.annotations.security.management.RoleGroups;
+import org.jboss.seam.annotations.security.management.RoleName;
+
+@Entity
+public class MemberRole implements Serializable
+{
+ private static final long serialVersionUID = 9177366120789064801L;
+
+ private Integer roleId;
+ private String name;
+ private boolean conditional;
+
+ private Set<MemberRole> groups;
+
+ @Id @GeneratedValue
+ public Integer getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Integer roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ @RoleName
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ @RoleGroups
+ @ManyToMany(targetEntity = MemberRole.class)
+ @JoinTable(name = "RoleGroup",
+ joinColumns = @JoinColumn(name = "RoleId"),
+ inverseJoinColumns = @JoinColumn(name = "MemberOf")
+ )
+ public Set<MemberRole> getGroups()
+ {
+ return groups;
+ }
+
+ public void setGroups(Set<MemberRole> groups)
+ {
+ this.groups = groups;
+ }
+
+ @RoleConditional
+ public boolean isConditional()
+ {
+ return conditional;
+ }
+
+ public void setConditional(boolean conditional)
+ {
+ this.conditional = conditional;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,41 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.core.Conversation;
+
+@Scope(CONVERSATION)
+@Name("pictureAction")
+public class PictureAction
+{
+ private MemberImage memberImage;
+
+ @In(required = false)
+ private Member authenticatedMember;
+
+ @In EntityManager entityManager;
+
+ @Begin
+ public void uploadPicture()
+ {
+ memberImage = new MemberImage();
+ }
+
+ public void savePicture()
+ {
+ memberImage.setMember(entityManager.find(Member.class,
authenticatedMember.getMemberId()));
+ entityManager.persist(memberImage);
+ Conversation.instance().end();
+ }
+
+ public MemberImage getMemberImage()
+ {
+ return memberImage;
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureSearch.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureSearch.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/PictureSearch.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,64 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.EVENT;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Out;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.security.Delete;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.jboss.seam.security.Identity;
+
+@Name("pictureSearch")
+@Scope(EVENT)
+public class PictureSearch implements Serializable
+{
+ private static final long serialVersionUID = -1868188969326866331L;
+
+ private String memberName;
+
+ @In
+ private EntityManager entityManager;
+
+ @Out(required = false)
+ private List<MemberImage> memberImages;
+
+ @RequestParameter
+ private Integer imageId;
+
+ public String getMemberName()
+ {
+ return memberName;
+ }
+
+ public void setMemberName(String memberName)
+ {
+ this.memberName = memberName;
+ }
+
+ public void delete(@Delete MemberImage image)
+ {
+ entityManager.remove(image);
+ }
+
+ public MemberImage lookupImage()
+ {
+ return entityManager.find(MemberImage.class, imageId);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void loadMemberPictures()
+ {
+ memberImages = (List<MemberImage>) entityManager.createQuery(
+ "select i from MemberImage i where i.member.memberName = :name and not i
= i.member.picture")
+ .setParameter("name", memberName)
+ .getResultList();
+ Identity.instance().filterByPermission(memberImages, "view");
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ProfileAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ProfileAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/ProfileAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,132 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+import static org.jboss.seam.ScopeType.EVENT;
+
+import java.util.List;
+import java.util.Random;
+
+import javax.ejb.Remove;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+
+import org.jboss.seam.annotations.Destroy;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Out;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.jboss.seam.annotations.Scope;
+
+@Name("profile")
+@Scope(EVENT)
+public class ProfileAction
+{
+ @RequestParameter
+ private String name;
+
+ @In(required = false) @Out(required = false, scope = CONVERSATION)
+ private Member selectedMember;
+
+ @In(required = false)
+ private Member authenticatedMember;
+
+ @Out(required = false)
+ List<Member> newMembers;
+
+ @Out(required = false)
+ List<MemberBlog> memberBlogs;
+
+ @In
+ private EntityManager entityManager;
+
+ @Factory("selectedMember")
+ public void display()
+ {
+ if (name == null && authenticatedMember != null)
+ {
+ selectedMember = (Member) entityManager.find(Member.class,
+ authenticatedMember.getMemberId());
+ }
+ else if (name != null)
+ {
+ try
+ {
+ selectedMember = (Member) entityManager.createQuery(
+ "from Member where memberName = :memberName")
+ .setParameter("memberName", name)
+ .getSingleResult();
+ }
+ catch (NoResultException ex) { }
+ }
+ }
+
+ /**
+ * Returns the 5 latest blog entries for a member
+ */
+ @SuppressWarnings("unchecked")
+ public List<MemberBlog> getLatestBlogs()
+ {
+ return entityManager.createQuery(
+ "from MemberBlog b where b.member = :member order by b.entryDate
desc")
+ .setParameter("member", selectedMember)
+ .setMaxResults(5)
+ .getResultList();
+ }
+
+ /**
+ * Used to read all blog entries for a member
+ */
+ @SuppressWarnings("unchecked")
+ @Factory("memberBlogs")
+ public void getMemberBlogs()
+ {
+ if (name == null && authenticatedMember != null)
+ {
+ name = authenticatedMember.getMemberName();
+ }
+
+ memberBlogs = entityManager.createQuery(
+ "from MemberBlog b where b.member.memberName = :memberName order by
b.entryDate desc")
+ .setParameter("memberName", name)
+ .getResultList();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Factory("newMembers")
+ public void newMembers()
+ {
+ newMembers = entityManager.createQuery(
+ "from Member order by memberSince desc")
+ .setMaxResults(10)
+ .getResultList();
+
+ // Randomly select 3 of the latest 10 members
+ Random rnd = new Random(System.currentTimeMillis());
+ while (newMembers.size() > 3)
+ {
+ newMembers.remove(rnd.nextInt(newMembers.size()));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<Member> getFriends()
+ {
+ return entityManager.createQuery(
+ "select f.friend from MemberFriend f where f.member = :member and
authorized = true")
+ .setParameter("member", selectedMember)
+ .getResultList();
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<FriendComment> getFriendComments()
+ {
+ return entityManager.createQuery(
+ "from FriendComment c where c.member = :member order by commentDate
desc")
+ .setParameter("member", selectedMember)
+ .getResultList();
+ }
+
+ @Remove @Destroy
+ public void destroy() { }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/RegisterAction.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/RegisterAction.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/java/org/jboss/seam/example/seamspace/RegisterAction.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,203 @@
+package org.jboss.seam.example.seamspace;
+
+import static org.jboss.seam.ScopeType.CONVERSATION;
+
+import java.util.Date;
+
+import javax.ejb.Remove;
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.annotations.Begin;
+import org.jboss.seam.annotations.Destroy;
+import org.jboss.seam.annotations.End;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Observer;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.faces.FacesMessages;
+import org.jboss.seam.security.Identity;
+import org.jboss.seam.security.RunAsOperation;
+import org.jboss.seam.security.management.IdentityManager;
+import org.jboss.seam.security.management.JpaIdentityStore;
+
+@Scope(CONVERSATION)
+@Name("register")
+public class RegisterAction
+{
+ private Member member;
+
+ @In
+ private EntityManager entityManager;
+
+ @In
+ private Identity identity;
+
+ @In
+ private IdentityManager identityManager;
+
+ private MemberAccount newAccount;
+
+ private String username;
+
+ /**
+ * Password confirmation
+ */
+ private String password;
+ private String confirm;
+
+ private String gender;
+
+ private byte[] picture;
+ private String pictureContentType;
+
+ private boolean verified;
+
+ @Begin
+ public void start()
+ {
+ member = new Member();
+ }
+
+ public void next()
+ {
+ member.setGender(Member.Gender.valueOf(gender.toLowerCase()));
+
+ verified = (confirm != null && confirm.equals(password));
+
+ if (!verified)
+ {
+ FacesMessages.instance().addToControl("confirmPassword",
"Passwords do not match");
+ }
+ }
+
+ @Observer(JpaIdentityStore.EVENT_USER_CREATED)
+ public void accountCreated(MemberAccount account)
+ {
+ // The user *may* have been created from the user manager screen. In that
+ // case, create a dummy Member record just for the purpose of demonstrating the
+ // identity management API
+ if (member == null)
+ {
+ member = new Member();
+ member.setMemberName(account.getUsername());
+ member.setGender(Member.Gender.male);
+ member.setFirstName("John");
+ member.setLastName("Doe");
+ member.setEmail(account.getUsername() + "(a)nowhere.com");
+ member.setDob(new Date());
+ member.setMemberSince(new Date());
+ entityManager.persist(member);
+ }
+
+ account.setMember(member);
+ this.newAccount = account;
+ }
+
+ @End
+ public void uploadPicture()
+ {
+ member.setMemberSince(new Date());
+ entityManager.persist(member);
+
+ new RunAsOperation() {
+ public void execute() {
+ identityManager.createUser(username, password);
+ identityManager.grantRole(username, "user");
+ }
+ }.addRole("admin")
+ .run();
+
+ newAccount.setMember(member);
+ newAccount = entityManager.merge(newAccount);
+
+ if (picture != null && picture.length > 0)
+ {
+ MemberImage img = new MemberImage();
+ img.setData(picture);
+ img.setMember(member);
+ img.setContentType(pictureContentType);
+ entityManager.persist(img);
+ member.setPicture(img);
+
+ member = entityManager.merge(member);
+ }
+
+ // Login the user
+ identity.getCredentials().setUsername(username);
+ identity.getCredentials().setPassword(password);
+ identity.login();
+ }
+
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getConfirm()
+ {
+ return confirm;
+ }
+
+ public void setConfirm(String confirm)
+ {
+ this.confirm = confirm;
+ }
+
+ public String getGender()
+ {
+ return gender;
+ }
+
+ public void setGender(String gender)
+ {
+ this.gender = gender;
+ }
+
+ public void setPicture(byte[] picture)
+ {
+ this.picture = picture;
+ }
+
+ public byte[] getPicture()
+ {
+ return picture;
+ }
+
+ public String getPictureContentType()
+ {
+ return pictureContentType;
+ }
+
+ public void setPictureContentType(String contentType)
+ {
+ this.pictureContentType = contentType;
+ }
+
+ public boolean isVerified()
+ {
+ return verified;
+ }
+
+ @Destroy @Remove
+ public void destroy() {}
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/ejb-jar.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/ejb-jar.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/ejb-jar.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
+ version="3.0">
+
+ <interceptors>
+ <interceptor>
+
<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
+ </interceptor>
+ </interceptors>
+
+ <assembly-descriptor>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+
<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
+ </interceptor-binding>
+ </assembly-descriptor>
+
+</ejb-jar>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/orm.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/orm.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/orm.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings
xmlns="http://java.sun.com/xml/ns/persistence/orm"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
+ version="1.0">
+
+ <persistence-unit-metadata>
+ <persistence-unit-defaults>
+ <entity-listeners>
+ <entity-listener
class="org.jboss.seam.security.EntitySecurityListener"/>
+ </entity-listeners>
+ </persistence-unit-defaults>
+ </persistence-unit-metadata>
+
+</entity-mappings>
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/persistence.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/persistence.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/persistence.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+ version="1.0">
+ <persistence-unit name="seamspaceDatabase">
+ <provider>org.hibernate.ejb.HibernatePersistence</provider>
+ <jta-data-source>java:/seamspaceDatasource</jta-data-source>
+ <properties>
+ <property name="hibernate.hbm2ddl.auto"
value="create-drop"/>
+ <property name="hibernate.show_sql" value="false"/>
+ <!-- These are the default for JBoss EJB3, but not for HEM: -->
+ <property name="hibernate.cache.provider_class"
value="org.hibernate.cache.HashtableCacheProvider"/>
+ <property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
+ <property name="jboss.entity.manager.factory.jndi.name"
value="java:/seamspaceEntityManagerFactory"/>
+ </properties>
+ </persistence-unit>
+</persistence>
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/security-rules.drl
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/security-rules.drl
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/META-INF/security-rules.drl 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,247 @@
+package SeamSpacePermissions;
+
+dialect 'mvel'
+
+import java.security.Principal;
+
+import org.jboss.seam.security.permission.PermissionCheck;
+import org.jboss.seam.security.permission.RoleCheck;
+import org.jboss.seam.security.Role;
+
+import org.jboss.seam.example.seamspace.BlogComment;
+import org.jboss.seam.example.seamspace.Member;
+import org.jboss.seam.example.seamspace.MemberAccount;
+import org.jboss.seam.example.seamspace.MemberBlog;
+import org.jboss.seam.example.seamspace.MemberFriend;
+import org.jboss.seam.example.seamspace.MemberImage;
+
+# These rules allow members to manage permissions on their own images
+
+rule ManageImagePermissions
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
+ check: PermissionCheck(target == image, action == "seam.read-permissions",
granted == false)
+then
+ check.grant();
+end
+
+rule GrantImagePermissions
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
+ check: PermissionCheck(target == image, action == "seam.grant-permission",
granted == false)
+then
+ check.grant();
+end
+
+# Allow all users to read the available roles
+
+rule ReadRoles
+ no-loop
+ activation-group "permissions"
+when
+ check: PermissionCheck(target == "seam.role", action == "read",
granted == false)
+ Role(name == "user")
+then
+ check.grant();
+end
+
+# This rule allows a member to delete their own images
+
+rule DeleteImage
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
+ check: PermissionCheck(target == image, action == "delete", granted ==
false)
+then
+ check.grant();
+end
+
+# This rule allows members to revoke permissions on their images to other users/roles
+
+rule RevokeImagePermissions
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
+ check: PermissionCheck(target == image, action == "seam.revoke-permission",
granted == false)
+then
+ check.grant();
+end
+
+rule ViewProfileImage
+ no-loop
+ activation-group "permissions"
+when
+ image: MemberImage()
+ check: PermissionCheck(target == image, action == "view", granted == false)
+ eval( image.getMember().getPicture() == image )
+then
+ check.grant();
+end
+
+rule FriendViewImage
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ image: MemberImage(mbr : member -> (mbr.isFriend(acct.member)))
+ PermissionCheck(target == image, action == "view")
+ role: RoleCheck(name == "friends")
+then
+ role.grant();
+end
+
+rule GuestViewImage
+ no-loop
+ activation-group "permissions"
+when
+ image: MemberImage()
+ PermissionCheck(target == image, action == "view")
+ role: RoleCheck(name == "guest")
+then
+ role.grant();
+end
+
+rule ViewMyImages
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
+ check: PermissionCheck(target == image, action == "view")
+then
+ check.grant();
+end
+
+rule RestrictCommentPage
+ no-loop
+ activation-group "permissions"
+when
+ check: PermissionCheck(target == "/comment.xhtml", granted == false)
+ Role(name == "user")
+then
+ check.grant();
+end
+
+rule CanCreateBlogComment
+ no-loop
+ activation-group "permissions"
+when
+ blog: MemberBlog()
+ check: PermissionCheck(target == blog, action == "create", granted == false)
+ Role(name == "user")
+then
+ check.grant();
+end
+
+rule CreateBlogComment
+ no-loop
+ activation-group "permissions"
+when
+ check: PermissionCheck(target == "blogComment", action == "insert",
granted == false)
+ Role(name == "user")
+then
+ check.grant();
+end
+
+# This rule grants permission for users to create their own blog entries
+rule CreateBlog
+ no-loop
+ activation-group "permissions"
+when
+ mbr: Member()
+ acct: MemberAccount(member.memberId == mbr.memberId)
+ check: PermissionCheck(target.memberId == mbr.memberId, action ==
"createBlog", granted == false)
+then
+ check.grant();
+end
+
+# This rule grants permission for users to upload pictures to their profile
+rule UploadImage
+ no-loop
+ activation-group "permissions"
+when
+ mbr: Member()
+ acct: MemberAccount(member.memberId == mbr.memberId)
+ check: PermissionCheck(target.memberId == mbr.memberId, action ==
"uploadImage", granted == false)
+then
+ check.grant();
+end
+
+rule InsertMemberBlog
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ blog: MemberBlog(member == acct.member)
+ check: PermissionCheck(target == blog, action == "insert", granted == false)
+then
+ check.grant();
+end
+
+rule CreateFriendComment
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ member: Member() //friends contains acct.member)
+ check: PermissionCheck(target == member, action == "createFriendComment",
granted == false)
+then
+ check.grant();
+end
+
+rule CreateFriendRequest
+ no-loop
+ activation-group "permissions"
+when
+ acct: MemberAccount()
+ member: Member() //friends not contains acct.member)
+ check: PermissionCheck(target == member, action == "createFriendRequest",
granted == false)
+then
+ check.grant();
+end
+
+rule CreateAccount
+ no-loop
+ activation-group "permissions"
+when
+ check: PermissionCheck(target == "seam.account", action ==
"create", granted == false)
+ Role(name == "admin")
+then
+ check.grant();
+end
+
+/*****************************************************************************************
+
+ The Following Rules are for Identity Management
+
+******************************************************************************************/
+
+rule ManageUsers
+ no-loop
+ activation-group "permissions"
+when
+ check: PermissionCheck(target == "seam.user", granted == false)
+ Role(name == "admin")
+then
+ check.grant();
+end
+
+rule ManageRoles
+ no-loop
+ activation-group "permissions"
+when
+ check: PermissionCheck(target == "seam.role", granted == false)
+ Role(name == "admin")
+then
+ check.grant();
+end
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/import.sql
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/import.sql
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/import.sql 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,52 @@
+insert into Member (memberid, membername, firstname, lastname, email, tagline, gender,
dob, location, membersince) values (-1, 'Mr_Smiley', 'Mr',
'Smiley', 'smiley(a)nowhere.com', 'I smile because I care', 0,
'1953-03-10', '', '2007-01-02')
+insert into Member (memberid, membername, firstname, lastname, email, tagline, gender,
dob, location, membersince) values (-2, 'duke', 'duke', 'McDuke',
'duke(a)sun.com', 'I love the smell of coffee', 0, '1995-01-01',
'', '2007-01-04')
+insert into Member (memberid, membername, firstname, lastname, email, tagline, gender,
dob, location, membersince) values (-3, 'shadowman', 'shadow',
'man', 'shadowman(a)redhat.com', 'I''m wearing a hat', 0,
'1999-01-01', '', '2007-01-05')
+insert into Member (memberid, membername, firstname, lastname, email, tagline, gender,
dob, location, membersince) values (-4, 'mona', 'mona', 'lisa',
'monalisa(a)louvre.fr', 'Some describe me as enigmatic', 1,
'1503-07-01', '', '2007-01-06')
+
+insert into MemberRole (roleid, name, conditional) values (-1, 'user', false);
+insert into MemberRole (roleid, name, conditional) values (-2, 'admin', false);
+insert into MemberRole (roleid, name, conditional) values (-3, 'friends', true);
+
+insert into MemberAccount (accountid, username, passwordhash, passwordsalt, enabled,
member_id) values (-1, 'demo', '70D33A98C7E76C7365A7C58F88CA8A89373B6EB5',
'C0FA5E59FC18E1E1', 1, -1);
+insert into MemberAccount (accountid, username, passwordhash, passwordsalt, enabled,
member_id) values (-2, 'duke', '8D18E5D7DB472FF8AA3E3984F16BFDDA2B265598',
'576EF3D383B00897', 1, -2);
+insert into MemberAccount (accountid, username, passwordhash, passwordsalt, enabled,
member_id) values (-3, 'shadowman',
'1D70EA4F262D46525F38DA0C1A130FFF1CA02149', '727D5C9995088913', 1, -3);
+insert into MemberAccount (accountid, username, passwordhash, passwordsalt, enabled,
member_id) values (-4, 'mona', 'CDF580AB2AFC6F7FBCF5A1F114E383DB0DF9E309',
'7D804DD05067750C', 1, -4);
+
+insert into AccountMembership (accountid, memberof) values (-1, -2);
+insert into AccountMembership (accountid, memberof) values (-2, -1);
+insert into AccountMembership (accountid, memberof) values (-3, -1);
+insert into AccountMembership (accountid, memberof) values (-4, -1);
+
+insert into RoleGroup (roleid, memberof) values (-2, -1);
+
+insert into MemberImage (imageid, member_id, contentType, data) values (-1, -1,
'image/png',
'89504E470D0A1A0A0000000D49484452000000AA000000990803000000884651B30000000467414D410000AFC837058AE90000001974455874536F6674776172650041646F626520496D616765526561647971C9653C00000300504C5445F6E555F5E664F8F9D8615D0B020101F3E433DAB920F7E874F8F8C8F8F270F7E984F8F4B8F8F398F8F3A0939218F2C903F8F8E8F8F380F8F4A8F8F168F8F390F8F378F1D615E9D368F8F388F8F160F8F4B05D5A45F7EA93F3F224F3D824F8F9D0F5E325F8F9B8F8F250F8F158E8C703E7E544FFFFFFF8F4C8F8F9C0F4E614DCCD2BF8F9B0E7E653F3F214F8F248E4C323F2DA33F0F100D2CB88E4C2137A782A808080E7E436B0AD6B8E894FF8F8A0EEDB7FF8F9A8E8E564A9A545E3D825F0D100E7D944F0F140D0CFC7E7DA342D2903A9A98BF6EAA3F8F998E5D516CCC9B0F8F140F0F148E3DA52B0AFA8E7D202E1C444CECE45DEC032F0EA00F0DA43908F73D4D16DE7E8D2F8FA90F0EA49F8F038E8E393F0E200F0F138EFDA00E7E300EEC913E6E424E3C856F8F4C0C1BC86FCFDF0F8EB00DDBD0AF8F988F0D209F0F108F8F100F4EAB236332AF0F050C2BE4CF2DB58FEFFFCF0EA40FDFEF7F0F2D8F8F4D0F0F2!
80F8EA3EE6E6C6F8EB4CF8EB08F0F030F8E24AE5E4A2F8EF2EE8E575E8E6B3F0F078EFE249E7E984F0F088F8F108EFE13EF8F4D8474329F8F980F0F290F0EE70F0EE63F0F8E0F8E13EF0F2E0F0F268F0F2B0F0DA0AF8FA68F0F058F8FA58F0EB09F0F3B8F0F9C8F8FA50E7ED4595977AE7EAE2F8F8F0F8FA48F8FA401915019C9B52F8E208F8F978E5E917F8F970F0F3C8F8F938F2EBC596968EF8E200F0E109F0F098F0F2D0F0F2C0E7EE33E8EE54E8F185F0ECD5F0F8D8ECEE24E8EE71E8ED63F8DA00E8F2C2F0F2A0FBFAE7F8FA60F8D300F8DA0BF0F9E8F0F1E8F7FA29E8EEB3FCFEFDF0F858DAD8ACF0F0A8F8F3F0F8D30AF0F948F0F9C0F0ECE4E8EEA6ECCE23F0F9A8FCFAF0F0F9F0A3A06CF8FA00A09E91FBFEF70F0A09F8F8E0F8FCDFF8FCF0F8F8F8F9FCE8F8FCF8F8F4E0F8F4E8F0F890F0F8D0F0F898F0F888F0F570F0F878F0F868F0F560F0F8B8F0F800F0F8363E3D02E8F400F7FA11DDDF5EE8EED8DDDE37D9D9CB221F15F0F0F0BABBABDBDD94FDFDFEFEFEFFEBCC33F0FC50F0F8B0F0F8408D8D80908890FBFBF7F0F8A0B2AE1FB8BA3EEBCE46E9CD5BF068708C000027E94944415478DAD49D095C9357BAF04958B20BD9308440084B0904100A222188522DB160B16295A0288A2088524344CA52AC088892A2822B2D1AB54A5BD74ED599DA3A63B7D1DEB1!
4EA7032FA66A6B97A9B4D63AB676C6B9DE56EF73CEFB2679134001BDF37DF3!
80D4F90D
EADFE73CFB5974F3F88F11378FB1FF2182501F19B6184D2693D168FF5FD4CF08B546A7D5EB73728AB1E468351AB5D25A68323EF2306484A888CFF69377DF05F0422BF3B30F05121977D54A46CAD4AB5341AE4E65AC6471157C915C4914D2FE62FF7E54879808B646FFE586231D6113C3C29A9A2636855132695222485898D9CC9588D444A1F1FF21AA11E993A999BDFA785458E2FCC308ACBCBC3CAD1C8BA1BCB2D2332868FE94D4D46BD7A6A6B0B8FC02E68318C383A19A98AA37571C3F82109BCA6B6B838343AAAADC9030B0B8B9D5D6D6B602B0E7A44993264E9CE86696E9ACA67F2BEA4DDBC26B0EACBC1A1576B8A6A6B2B20AF0C4623183C3E2B0A4F0813E59247055556D6B5313D0CE9F3495912CEA19A1218C08F5A79B9833C75C060669A8AA0AF1F313031A97C51272B9128944C1B50B8B858901B7B2B27246ECA4D4494DE6151AA6F1DF6800856AFD179B126B7263824342FC182C1697AB5028F8200A457AFA018140C0E74B2480AAA080198CDAFAFAAA5ACFA08829A991E606F908EC6044A8C6C202052BAA2331062954CCE1482124A58B2891CBE5A2741162C5023A9671855C16074CA11699AE2772B430337FD89A1D01AAB150CD179A37D5971BFCC034A552215771E04D20E4F1542A1E8F575050B075EB3F376EFCE8A38F1039202B24106F916E198C656ECB5A63E!
747BC9C9AC850149C33FEDFA21A4FA8F52D9B320D864D7E2CAE502601752E91CB97204E159BADC45251111E1EAE561784871714F09600AE822F5120534866312028B4D6B64E9C7867991B4BC4040FBBF97F827A13DBE8AAE31D1DE586108654C6170844721E1081B0D96AB69249CA1AA5D2C15CC0E3C945D82014E90A6CB50CB765CB66CC884D9DB48C2BEA313D3254D8616AF584F68BB2C3873337B5B0C0D32165F2546AA4C9354CBAD840956C351680256905E948B7246DED8C496767DC59C6550F39740D0BD5C4E49B3B0E5F497B8F23E3233B0485224DF6D8C5091448552A20456650C05369343A64B9142CD8C18C198181917756EA08D3C3472DD473CC61619921EDB0F422B0CE82F08A8A35177A7C9010048199312A1B0B56EA871F6EDBB70F5B2ED832C0A60B8055C6C21E561B14E81B3929659DDAF49051C1F1A320B11BFC386B6507D2E54BC044D7ACB970E1A24F6767276665123D172ED050D978FD0FED43A805E8A7A0586406C02A447961597D6B5050606A64D46AA5E9A1A21AADFA6386CCE010B1542611E0A5672B7B488DFAD8967F0D928A0AA58D16FB1B5A7E64AD60AF28E4222380E02564B5B4B066B436C506A5A64EE4CA4D0F13D5AAFDAAACACCC0F481502E4F580C3ECA1833A504958C0A583CA4941A87ACCBA8AD5E2565F0F812035752A9777FBA1A19A8!
803C78E746CDAC041114A8E40C181887BA3B20743C56AE50A1B5829600448A!
F9153934
556E3C3412D545F3A1ED5F1DE06A91015F505C8EDC18FACCEA4242A4DA96CD7D5C7A4800A4D0DC08211AC34BBD53735C5A6463E9522B86F20180AAAD1AA5B71A4A3E3BDAF841250290F40C148AD202E4A6552A47663ED872AA250B5A83690281AB82D0C3082F249A99191299282DB0F8C5AA8D40A11E9DE6214F3514E420BDFDBDB6BA540095B4C2541696E5550E0B4FE544103AC5429038A45F5F724A860C008D4B7478E8ACDE77601D4A586CCCD400AEE04A068E13B9158298D1254F01F3A2A2E12157C015F281543E69AD11A943A2572E2E8825EE34851FF8A7EE5093E27AC3C66F3DEB5FC0F0A2A2AC048ADBD98F4CF7FFE3DA95382E8B1E57E27501BAA9D5423A2B1A6A32F9FCB567050290B790BB241E481AD85234535FD157EC85B0C31C17E1CA144C753123D84D5DADBDB498A8F5342453995F2A8F0704744A559AA4EA415690534D17E7E492694A2340B55ACAF6FEA538A7BF9D63D51DF353E62524ACC86603F944AE505CC1E2B22ED2503BF8FD519D49EFED934549E9D14D5005AAD0D351DA955FBF9BA7560AE52D06B6B6CA0EF94C8AB7CEB88DDCAA4BC6C2E8BF1E370D3C1A194E04E74549FFBA016B8A26A1DA8A4B97EFE395F815C0BAA9756CF4008B0A345A611A21A89CF8F676E0FE1C8043898621B75A0BA9232A970EA40E539913A50A966262707A280024CC0!
0FB1C6064E99326D6541E1C8500BB5C73BCE6C6E17F2450515B0FA9491FA386BB51F29890A75AA13AA8E4445B07C3BAA04E22B4401B11F84AC26B081C83B50C08E04B550732CAAE31FED6BF9221E9B69EDFDF4D3F3E7FBA3320746553B506D4AB5A1EAED1D221299700F87034DA25B7D6B60E0D9C8A912A669F8A826CD97473ACE7CBD562B023B257A7B8114B362CC8BF0E14CEA28FF86804A61CA8A8BD7AE5D2B944A39805ADB1A783A3F726AFA8961A31A89B5656967DEFB82AFE1852BB1523F25512FDA954A76002E5D0A955081D5851422004AFF7ABD83548648D70A85528E991105A881F9F991A335A69BC34335296586BCCC903D393A35CA5088D4D5528983CB99C48DA7ADCB8937989F7DA83C148E528093EBDB8B5414F7C9565BE210A858B0484138E61670AD19B181F967A70D6CAE2EA8B429E809BDB83C2F582CD3AAD888944475B252623964AAE56397FECBBA7C16C1FC1D7B1B0D954EAAA132942BAA0C2A41076A8BD95C5F3BE3CED9D3F963B84AE370B46A524BABAA6242A41211C4536B67EF7984EAEC50D0A27CBFDEEAEF6179723D2896B90DAD3CDB29F4D3122A8EFB22CAF9158818969FAED5960DE67A68B9037DF3CFDE51140E03D548F01906684F8402502A9451E7B14B394729D0E9F7BFE97DD5C3E3FA2756EB412662C54EA576562A46B5E5285B9C2251!
855C072AB01A507005B54E5F166E1C3A6AA1A6C5501E02995F04E9B4B7F3FC!
00A8B0F8
EBADEB7B6F747B78585EB52EFF1D53696BFD784EA436542D15FB257C72366403B5A38AABAA5A51703DBBE8E7D9D621A1E2BF1091B3292F4D2C940878EC1E1F1C5191F3BBE894580EA83F347B805EFFD5433C6B1B51A85C487524A9969A0FDA2C5528A4914AF77238E290AA4ACF58600D8DBC2BBF3954AD9A342D99B782A51201AA513ACFDBC2940395C0C204BD768205747B581E27BEFF0CA3AA5483A2920B5F5C2C9339BCDF8EBA97D3CEA8329437C59EF5CD8ABF33FBDCBD511D06625D77246DFB5B504EF12AD6F8748247F50E004A1C8418D0639DD50C26E0B1F409621F5E7E84AAA15B2AC45304AAD592594A02E9D449AB78F5F7022AC72F04A106FA9E0C8D1C5D601C22AAE658C78EF616BE08052AA84F7B517BE2E8A5AC881385FEEF97F780B93E761D6DD5F9FF406C53B20FA9551BD51A0D1A613AC5548C0A75BF40A7FBFC804E335BC05FB1B685868A45EC17526540E5A06FFC34857568A885FAE31DDBF7700572354A5314A8D54AD729CA51B3ACD6F5EB213CDC58EA6101D6279063A9792A15429593A80E52C8523A8540F3DCC25DEEEE4F3FFA9C40BF768F0B2966AD6D42AC6322193CE3506CD5A85C7524D30F2A3F2AFA53A4D61E1FBB43E1646AB53EF12F7FFFA5CDCD4B9109782CFD84493C7F48BD71A386522BADEFC3A80A9D6A61B3057DEFE4E65DDAE2142754B!
1186200781634DBB16721B6720B87826A151C2F7B4FCC47D5345DA9D61E6752A6F546B347B76DAF16C5AC170F32C3F16C0AB3DAFA3E448A52BF5EA05AD867FBFEC9BB246B6D2E8549DBC57B5B3688FDAA0C4DC8B3A6788DE699EE8F6A52AF8ACA7C4B2AE0152891A59E3F6F63B5A352F5D427CD24A203F769827988CD2351E5AEA85AD5A3FEF03DF817747B34CFCEA1A1EE1503EB1708B5CA505F0FCDCBA2E90AC2785F546B8EB9A36CAF4CA0C6CB0F71EA533AAA9DF48DE54BED94DD1EE49F7FFDE90AE5A18D83A00AE4FEB435983CB381A6544EBB582CDEB0C12F041CABBE2930B064D11846BAE9BE2940792C330D62AA4885961FA7A94FF180C26A5B7E8CFAC61BCB6F3C3E76AC7FF3D2A5D76D0016D0EB3EC85614AAC8195534CEE2615B06F8922492D1508154FCD5D780EA6730247AB695E47BDD492EBC1F6AA1EE481A38155FA76242A222532A0A5854870A0D3689BA7C790FB1E6D90B3DCFFEF0FE8D4F9EC6CC281724853FCF93BBA2625315F95BF0F253D22C90491DA60AEBDFBE01A1BA951912837CDB4AE2C72CB3DE07D5A8FE3271E75B29EB541BD9BFA172FFF997FED0D9EB3C9E224714E4FE4405DA9F40E5DFFBEF2FFC3829E9513519FA351AAA4A15680F48F412BDF651E733139647650E8DB68BFDDEF2030909090E8EF10456DFACD0E97264ACB707473569CD8!
733C45C81EA1D66EF1F9F1CEBFFDF8FA1A47AD1C74A9BF951ACB4490A359F6!
0B3972C2
950DBEA7EB2A00254BD44B24EAF48EAB61B2A3282EE717CC7DA8B11E75B146AB96790EF94ACD0318ADBF460DF1FB5501F9597C69188366E63BEE4DF0D0BB6F4BF5F3ADFBBDE3EA07041653BA1AAD94A352FDD814A157F5A40D5CD6EF6A0A37A78EC9238A1BE6547455A9D9295356634714F0330122BA2766472243A35F3FB66D25FBA3FF93B425DDFD36FF0E318FB535DCA92251BE5F225B666CA3E4AD34AF47CCD8F931D8BDF8D8C364926759052CB0FA458ABF3DBB2B2F2A7390D30FAA1424DD59159265568D8C4275414F2587AA3F70FBD50E8F747653B76280A70E7A746DB82FD50F5395A81E8D16E3AAA0742E57058B4F547A448A931699E4141BE255953A63B652C57542364AA0E4388F0808AFD7DB3FDF77DF5BC0F0DD5D14DD348312ADEBE947F400E2828543ED47EEB24FA03CF7DDCED4CEAB14B46B75458FF90CD58A93195E541C8AFF2E397297F1A1CD5A46E88CA0C16E7BCA952FE61290E2DD7E1C7AB1721AA5EB82F2A9B6275460569E0F3D3D393BAE9B60A1FE3644EEB8F4849D48CBABAF96DBE2525F9D3C1026E0E865AA85915B6BD7D8FFE4D35D1EB6FFB9DBB5FEDF4B960754CA7075A7F357D3C4992EAC81695AFD737E8214A2775BB062B899352914B6D47A43119954128B296788F519C78E4A7818B40E32385FC948E1D66A156A37EE1A5276D79F3FA0FBD!
BFB15A8959F6413AE553D4184D5DE0984E3B2A3F11B5C58EAAE9755AFE6CDEC72EB63A79B69044F5F373B8542648466E651D1800425DA01CCC008C46AB24AA63BB58A6DB788838FF03558D788CEDEC5D0F4A25683AA58D7CD56A1AA8F38822DD860A05A06A5CB7073DB0762728A40ED210EC523131409A96919BEB191441A26A8C838E2CD4C223E5C110AAB6FE8EF8F4FC63FE285A5D1FFB52AF0FEAF409D7DD693AEA00D31434EDB5CDD1F407340BBB693E854C552FE5F4737E121569151940FE34BE69305493AAA5232D44C8D7B03F7B01FAD4C75E05D6B1FFE5034A454309D7996FB87D8E36E034C53E4995481AF4EB44B3FB3CE8163079E5658E1D35C4867A26332D2D23C3A6D5FC31B470E58A2A3703AA4CB0914D587FFFE7CE4FCF836B8DEDEDF4C1A8CB07402537FC074525C713EB7264FA063E0A01B46A25E1F217AEA83148AB69C800EA00D517A1D24A1617D442D1F1F2186855FEF40EA0F6BED489A280FFED4E88AA3D4C07AAD28EEA389BD07F9AE218FA026A4E8344B7D042AF6D77151F17F7473D93798B440D3A0916101A7F7770544154798C5826DAF8CE0BD6DF5B7B3B5F5A8A9CAA132AEBF54C82795F54B90BAA6DE893232B9649F4E9FE1647A44A98B9E78858DC0F35ED565A5A6E0642C52120F40E315804202451E5C162AE46B58FE85DFFFB3F747602AAFF!
7F5D5C7FA1A767CD9A81B627703A752695EB6C731FDB7C4A0F3D7FB1AC41F7!
BC9DD592
F4DCE77B8FB4D34971F08FB995762B2FB7AB0E0C00E500EF45D389412A2BA3461A66F0934A043CA50FDEA000AD7637775EB46FF75628D1076DBFDF354ED9767C1D864ACD7C4124FAD949166C00CDE366E748DBE9A465C16586B22AC38E8C6BE55D010101757511BE274F8256A7CF2E1C18D5A46B3718F0A4AAE2E21F51ED0FC9D563E9DFF17C9AD9D37FB7AFDF26FA12397D6BD23EF0C7A442D96A9DEE63F7C97DCDE366EA73F66C309BC56206AD9ECACC0C36245EC9CCCBEB3A551710D116B1DBBBC43B7ECC6C621054ED061A2AA8F5CF807A7D161D55790FD425B4982AE0F7475D9103BDA062365756BC67438AF96B3F3F86D856F993A83BF20E6F7FEBBDB08E989D01735F8B383D2CD44E94B01EB3A1BA287580FDFE7EA48EF5170A65C50DAB5F6F6890154B41A35FBF2536D3332A8A53E5897967A29E1A3F6AFCAFE53BE764854E98E0ED3D26793054BDD9100CA822848AFCFEEFFE605A4F5EA412AAE350C2885085B29C9CE215ABA47BDB916C3033C4CEA8699BD3366FDAD507E63CD93DF254D1DC880910589395F740E560D40B3844F9A0EA6AAC1DD599B4DF263A6D179DEFB2FE78E603A02BD6AEDD7315946A361F3773C47452404DDC7E6494858A6541D15959A0D6C151738E3BA1FAFC752C9AF10D865A30F07EBFC8D9A71CA82B5614AF5DB96AAD740F47CCE16CE0EC7!
128350685D4B4C4F66726E36102945DBFD4B59106A01E18B530078A95BD08957D01321441A0497FF7F53FFAF4B876A834D47B28D59954283DF6E5DA632D6BA5D216F39E3D624694935233D2D262362590C9ECBA47F7A8405F52ABAA9B03A34AA290ADF2452AE505E8FB5F207A6FA05FFB848F750D41ACA9703A3F45D57E05BC7E47135C94EA20FD0284C3C1CD3FADA2A20C1564B3D99DAA13BBBBDD2B8310EAA2C10CA03007A1CA6CA86F10D6C7E02F08C66A5DC37CC5D1A050658AEB26BAA69F52157452A1948351A986DA964EC9E507D0BCB49876777B89981014814280D7E8C1508BE9A804A0BE84FC6AE92CA8AB9EBD2FAAEEDE4A15DAE7A8B6D41F624FA819081582EA28AA96E9B68CAA8B980BB6EA957C5F5436B3A7877881B0F622BFF278D24A9AAA0D55ED5CA6D04614FD2CD5BE91669B4FB58BDB6D650A454AA2E6E5E55DD97EB58F6275CFDF3D670ED26A327B6054AB332A41BCD0F924EE587C888304731FFB5EA8BAFBA2E22FF6593AB0DA490115486B026EED49C0152D0A00738AE66254E5105081F48D177A1F5B8A2CE007E6B344B8D3094ADA569A9C36A2100D98FD49A50A855C210DD59651915233F230EAE1E360ACDD7D7DEEBF7846CF29CA220DC03860C7EA8ABADCFAC7BFE316FB45029DA01C16AAA41FAAD449A9B4E5B7A176EDFCD502A4BFA6469FFA6E5!
ED6DCD0FBDBAAD06E00CBAD3EC858BB3DFC6711FB680995DCF453F5DBEFA7D!
5540E509
9C3525903E8142BB52B2F1750E7678EEA8630B5FDD45FB2E71415CDDD8F51072D57A20C55212C8940C546136B1F6BCF85F54FE250F7E41B4CF63636B9874EDF4477EA509D399D35CAA119A9CDFD81B3AC0CBAA92B353575B9359E79354750A7386AFE3771A5D5BBDBDE4661D54B3118AA2EA5BE2A84211368D44AC2A7F3C21A6239F104CECACD2FA00DFF7BEFF7F727E5923BBE529683943EA3B0A1E676D5D4E482DCFA05FE2CCBAFDF2D2EADAEDE7D12A17A7BCD660ED605A4D45756892502CD87A0559F0BB3A0F59B454ED99E243EDBB6ED3EFBFDFD952AECB78BE692A71069DACE1D79E55D753535FF70873FA8AFE3BBC571D5D573E6BE0DA4F15EE983740146D52A84CAC55A257AAC6B7AD6302F8C2527F7DF13BFDB76BFFD7EBA47C964F45314F4E577CC28C8663AAD3CA63CA36BFED1C3C761FDBB471DFE76F1E2EA2D805AE20D5A5D621A0455DD10E659259609742A650F3AF6BB1CBCEB89A598F5C5EFF1D9847BECF76BFB8529E140A84E839F331919187547D7FC53B7C65BBA3D263F15306F0BC81C94AB42E3A729076B039592B044D02A5FAB41A86B7A7E032DB5F55FB8DCB9FE38B1EDDEFBFD5A814B392D1C54A9F6E47F2B63275454319E3BF3F2765C434E9570E5DBB82D5B22B26DA817066BAE99024065C80095D9A354327F83C67ED61F96E220D0FCECB67BEFF7!
6BF9F753AA1329CEFEB73240D276D65C39BCE34C02DACFFCE55476292895445D94BF60B091C5BB26795462A59F50A2D754002AF12C5171F0E0724AAD1E370EDE7BBF5F3B408FD28FD451A66C870F841A9391D8752A60FEE6A7D0AE967B5D51766911851ABA68CC8241675646E5F144831B4B26D129994A2535A5B8F803B6D6EE66E521257B2B5BD56FBF5FE0DA4C0D86EA670B539BCAB0209F02D49A80E897CF5C45EE6FF9E5D4DCA2D2D2B8EC39A456BDB8E7061DB05B8F85190C52A14417CE24AFD18019ACB1BE4ACE449E561E52B3DF51FDA9FF7EBFE3A40FDF394B0D4C4A43455AED7AB9EB70C778F427B8474617815AE3905227784F58345D31E8D0F291C215516106B1542628A86023ADA21685C99CE58F4BB3EB8F33F7A9D9E86882EB7EFF1050D1869FDDF9112612849A917BF4D4D133BFF6A1DAEF97AE39A5A573E200B50D85AAF805A2C150DF859E1550191C9980C7B6A32A0F128F918DE4D227986C363AF0E1B2DF6F23D5BBD653B4FD7EA7804AA1A691A8353B3B9E72C74A4D3C95F597D2ECB8ECEC3925DE60AB5E33D5C641518D9A63D7CA21B5F2D1D95A1BEA67C4F7FF229B9EE66789F7B7F6DFEFA750F5FA7EEE6F476DA7B44A7A14897A2B0F0F5373CB83CD09B84C1DD5B53FBBB4B4318EF47FEF45D3934F18073DBB6254AF0A4B0CF6E3F245BCF00A8C0A61!
7FDFC183B3A8ED16FFF795CA77FAA1F29D510720E5D09C1F82D47B58A757F2!
6EA5E5E6
D6E56E372775A3D32F7DA9A7E635966683905175D1F425B7073F666324D685251A5C50C15CDFB871DD8237FCFD9F2D50F5DBEF1F022AA9555B3C2D3B83945A73250F4A9580DC1990A6D07992512F37663716656FF9761EA9D5F83BCCC17603FF4A0E83AF5586B014E8CC32690088F533E6F21BD4B983E647953CD7F57718C000962A75DA9DA6AA54A4D4BC2B355772EBEAEA70958AAABF2B718D8D73B2E31AE7D9A2EAE87337EF81FA88F58B6B95552C2E57AF2A40EA64E20B54E115AF54DCB0ED373C7E88ADFA001DF1D46A6DA7A7052EC31419AD45B5E77EDCABFA859405076F37844134ED4283F4A35DD77EE9C6EDB47B4744517563E3E2B8B83973779F0C0D9DB0689ADC742FAD3E6292D47B5631582C894E85EF50E2CB5EE1F0F1AC6D77F0FAC2E7D550F78B04DAFFA150F92E3D0AAA53B9745452A5246A704C624CB0A132F768DDCEBA9D5DF337FF6AC12EDB9778AAA8A8A871F162E45427013574D102A773AC4EA8EF6283D531122BDD185C894883D50AA8AF6054E513B65DF2EB8F2B79CF69340211757A9A3FE0DCC7D19F501E45C6AAE098AA8CEDDBD1156C58FBA0EDEDA3F0EF0A3D6A576351512990C66517CD3D791A50A727171AEF7D2044299BD80A6A55E06B75CA0A506AB8F295F0F043CA7D8FDBCED3343FAE66FFE947DB496FFD40633F29CDF9DBC5E8580238D!
466726FA232A3B2127554B9A906BF51D73D4897EACA8E2B2A8D03C9CE7E0D525556E8A2694B4CF73B66239AEA09D6AAC0D7D5C84329EC2505EC258794C48BD7A9CD9CEB4FEF63BFF3276CAEF8983712011D554AEBFB40A9B48309C05AEE990B71DFB3BCEAADA9EEDDE4886A54EE965288FD24EAEEB9732740A4BACBBCFFE125565379157A8542CE2359C3D95BD5EC021E7BDB672F4EB66DE6FBBFBF4DFD4F0A55824ECFF2D3F9039372C4B6FD8990CD642FBD236367578D674670D4332429E834F5BB6C52A738A962FF9FA6B87DF37E47C2CE290C89E5E81ABD6809C91ACE2E50ABE1F37925662565E98BDB3692A8F8902779D54BD67FF9D1C1349BF891B3B40CE8FBF2B66F9E3ADEE281775C2CEE8721F6CF2BA248E7B4B54DC85AE4759777FFD36B461123D153CCE24A04F8B62AB47D6CF5C68D3CD556F53B6AE5E38EF35FFE7F83D0AAC517FD30EC8001152B959A5231C4D854336EEDDC79F8BDF667126C5B83EE5DA7B2B38BFED248A1CE2D393D21347EFAA3177FBA2FEA4D421616E6C60213A02E7FA3B60F55D4D0556DDDBAD07EB0C76372D2F36ACDEC035ABD449693236B28465712D0F509A74405A0B0F666B319E22AA3AA2A66C78E1DB7B6771CF962BC6D77D8D2D711BDB8148AD438ECFEB8A89A10EAE5E254839CB4348952A0BC02B5F2D12DE0021B2A16F5D68563B!
B6DBBBA16FF8FDF57A974073ED7E75C5EBDA2780516A1935ED1618F4D9B422!
0526DDA5
4EF161C53595E6ED8F4F5D55F132C944E2DEE8947B7141551A8403AE7644949FE22AFE4577EBA3984F3AB4C4954981B34030A60E5915D3FC2E4A9E41FA8C064C7D1CE2D2E4D58A8D668D75DCEC9293E06BA85FF38400115A914BCA92CB32C78F3E6ED19B9199BDBF7AEBA9AD0673B6CD4DDF7CBCE80C510FBC150BF2151E79684FAC67B2D4877BD1E32F0B170936EE5D47A37066245AE85DB7E40DD28177DF08146B595FDB8EDFC05F6AF8485CF6974EB5E7FFDF5D50D4880942BC5AF8490C3A9CD219BB16C3264A4C56CDE9BF24C529F635BD87DEACE79DF940269751CD22AAEA930EA6C6248A782A1BE6AA80FABAA02D7C2B79679142ACAA650546DE46D7C22C1E2413B0EDAFCF18F1FE9F49FA391FAEA06590E6D8E4A4EFCCAA2A2369919511D6FED59F98CFB64C7B94CCBA8A853D18DB0F8800A76BA05934E28F106A5F6BF863DD8617B514A13AE0470C42251FF864FFBA291BFE639D52B9FF4398EA2200FF31FF79CE64D11A4AF75DCD5A05564A5B6911F8AFFE23D6B8552E1CC517D16C7AFB2B83F95990A9AC42E1517575ABA259B5653DF1C22AAB182D5E4099500A0A653A8BCBF913D152AFB342AF99227F02E343964463F2CCDFEE316FE28D069F539E85C2AA7BDBD9D3AEC09159554C89D397E57DF640BED4C605F42C7D1E8EFD0781207A9D2A2EA2DA8510D0D05D469!
0AD3D02F8648A6267A5621567425186BF543D50768F9E53A0D3A412357172C6CB67878381D9EB2F425248D7B7436BEA92E5C4B4D2C64B28699E313DC275BBA699CDD1E7DBFFEE3E5EFBE9907E9F43BF0288C5A847CCA1B0A15AFBB153787AA55C8AE978FA456B62E63488B256FE2774A541F6EA56A69F22AA248B4759B937BD9B69C2C93FDFD1392767D3C7EDCC7E3762525F9BB374FB6D0BF8D3C6435EADAAD97179399F41BFC01CE3F6F7F1B74D4D0FDDFAD18CE25A6C28F8E5F4B6CAD65985735E8D1F31A1A95FA6F24AAFD82E79B1B55EF274D763A9166B3876EDAF96B5B58A27D575F4264C7A9E86FE34A31E8B7DFD882FFDC9212DC52259FBF399CFB56CAD7AF4E0AAA724B61ADC8811A4B839EA2A06B15E5FC033A8DEAC78F9B9DF4752F21FF2296C9A39E0AFE47CDCB5B1A17DB504170F047738AD078AFD1E9A6615DB82BFCE78A899E9EF528C1CAA01AE09177289CBA29EDA5D5AB3FD2FD38CE7DB26520B0817EDE3DD97D7C7D484C5740F4962D8D5B16236DE2E5C7B39F93132640F107D17FCDCD61A11AAD1A46FDA449F50CD64A21BAC62CD7E944F67713C80665B55EABBFA4D7EA3E9ABD30C9DF39780D483EB92F61FC5351C13BEA8EBE1CDD185D3D07A12EC63E1557BA65FFFEB6D3135045B52079E0E783EE7539D4AA654C9C545FC55886328168097ABAC63E4F!
C3A850553534404A6DC8D1EBB43F8EDBD5D76719D00E502C85E0307E668ADF!
D7656935
0101D18D8D1173AAA31793A8A89C2A02D292B74FA38A7A36F3E6F0AFDC5A0529133D5B6B97A14C802EC98B68CF51E02B7E02AD645D31AA52D616E7E45C7AF37F9E5B382EC1BDCF6271BA8161B1F4B98FFAF5AAF9EB4DDB77EC4CCBCB3BD5151111702A7A4B3519A470DD9FFDDA7EBCFDEF1D3F6D80EB4B43B9C8CCE44E9D14DB8A330148BAB356C96A5A9253BCEACB55202B5614E75CBA7CE9D281D9AB1F1D377E57524242425252D2AE5DE366CE5C756CC386E0CC5B69878F8246038E469C8A8EA86EACDEDD8851172FAECE2E7AEDB5B9E49062FA82F4774774E7FA26A19878D613B1E2B7B504A27411FE24515D36A685C2155FAEFA72C59797E1F3F20AD9E575AF7F79ECABAFBEFCEA8BAFCCE64D86AACCAAF25B57AED45C01D8E8882D5BB62CAE2649B75457BFF6DA9CB9AFFD7642E8E9455EA3E5E7467AE9BE8035313608589162F9E9F88227A555DA7CC23EF6E170BEE0D0C614EF6141CD5F157ED0EC56DE953C8C6AB351845A1D510D6D1FEE51A19F1A30A20EEDD98DDBF2959352A11A80EA15BDB5C417902768495474C7CF7679166DFCD04769A84C316FB29D4BCDC05D7F571AD66A7434E54CDF9496562352B4FA592469C503BC10522858762D28A8B2CA6D192A5F25E8CE9CC0F9EA240857662F52ED4728ECBB1308B5B2120DA772F36A6C4AC52A2D2D6DACAEDE1D819!
53A370BDAA99482DB37478E7A93A9989A3A29A8B516B10A65946629535DE7B83B0D0AB5F77EF6A16FB05B885B485515B9FC9575E8B41FA9D4C5B662AA7AF7EEDD27116A567CFCF499A2113FBB811F0633A9210C04C67AD6BA315A56715743630036ABA050D7AD73907238B6D6DF861A5C85AD34A40A0F547273EB024E1D8D8E8EFE962A53E2A0F8DFBDFBB7BFFD2D4A52F15E91CFA4171A1F0015BD0A58C15D163B05C52CC64A564B03F9C61E46BD74E9D2E5CBC532C7C01F38F7D2B6FCF0F1296AC31F16BF068C20C066A7C8A18A204861D2ACD04563EEDCE5163EF8C33B4AC9B249939A5AEBDD520056C85550A439924BE45304F6A68FBE3F05B818358624A550A3031A4BFF42AE7E7575F61C207DFBEDB7A198F29A962C62FEF4E0CF19190BE5C91353DB82EA97A1A8C5422F150269710E5E7B8C483B432166D8372882494C24680FBDAEE6E8D1E8C5A0D6461034469F370FA5A8B7BD4F43D7AFB8EFBB81437C24AA50B47262EA7CCFDADA5AE45CC08AA613329A99726CDECF4143143F3B6AA61D14A3824F21CE4628F8A1E8DBDF968548BD17C5DF492E78488F44A13BF8AC89918181ADAD6E5011AC6A20071332050EFFF695670DB0897E2B8D3C928E04152A688E829AE93920BB21F0A3419AD70285AAF0A1BD12662244C9137FCE0F84A01595D2D202391F2D790399AAA4F!
65B73039CF3BF959647911E4581EA5B0C5A04A914652844EAE5355AC11CC21!
37C43453
59A4EF01477CE9E4D8DADF49CE8C64861B500D4AA55A8C973A855ECBCE3439E9F855A2AB70640036A0290A19275D46B18D4DB1B55D2D3466B86F456E0305EB433128A657722A704050595A358C0309BCDA05D21582B8B0AAA78EC43230D8ED991792B039306D405603B8DC3BB52A0D2096F232B8596EFA995835728237E27D0D823624D4D9DD2B63B088A58B77A831BB0B6403CA0C23F57BA971C4F23D4EDC1F6235428F423D080886A88A4E04CFBDBDADA26204E6FC85077930B86F8FEE2B05E5F3416AAB85323A7F80605C6B6B6D6D6BBB99951ECA22629A055A7AB3358A924298AFC50F94557431EDD8F494B266052AF6977D395437D8975786F5A1A0B0901EBCECF67037D03CFC6B656CDA8A71E0506BE0DE20DF42A2538B88CD429891A5117111D1101E9BE0DFBD28409A731E9DD64F98921BF193BDC474D8D850502EE8C9FCF9E0D0C8A8D8D6D6D025A904DA4F8F931EC5B93E4A9340A3428222202D40984BF7D1BA551EFFCF8F8313FDF495E123E8C375847F054AC8948E7DEFD79CCD97CDFA0A0D8C0D8D87A30857A039210A0260B29AA9ACAADACF304370CDA1FB1BF6DFFDCB9E8A0375AF9D0F8455ED31770353DB787F376F4881EE035F5A48F5E30E6AC2F4850906713487D7D3DFAEA568B9E87AEA58ABECA204F0C1A848CB30D8AE7B92429ACFCF405C94BD6986E0E!
EB4F1D012A1A7C99948A94896723A74C99E21B084ED6143BA3A9B515CCA1094B6BAB67ABA727E284FFF364D0C9365FF02310D02A9A9D7A81DBA7FBDC1EAE8246FA02B389D0485853EF449E9D9235657F6020D8019619E47F3C01117D0682DE03DBD075A41274140502FEA2F8E977C09946F2C8F9033C176F62A673199013B2E6B6B5F90622390B9481A4A406228DFB96A00F2490404371F33C2D39BDC20426FAEEBBFF3E54FC2EA388CB98181939E5EC94FCFCD3F9A70116A218522510624892131D43098D8F8FC72B5F31D257E31FF0B97853A1559D9E7C17426D7EBE777E49BE6F7E49C9695FEF7CEF126FF8249D088750707908F7AF3CC87BF10FE1117E9355FD918CB5ECCECF6320DC8EC91F939F0FCCDEF0351FAB1294E935E6CE32165FAE3CF7D3833CC3FF30FEBD00A3D174EE62F82BE9E977172C98366DFAF4E963904090F79A3E7DDAB405A3472BD2D544E103FFEB060F03D5BE31C756C9450A8542865E0246CFC44BF8682F8938E14849C6FF4F508DF85F3A28F4F139015278EEDCB91327CEB9E8F28151FF73FEC590FF18F95F0106009BB82CA79ADF6F600000000049454E44AE426082');
+
+insert into MemberImage (imageid, member_id, contentType, data) values (-2, -2,
'image/jpeg',
'FFD8FFE000104A46494600010200006400640000FFEC00114475636B79000100040000003C0000FFEE000E41646F62650064C000000001FFDB0084000604040405040605050609060506090B080606080B0C0A0A0B0A0A0C100C0C0C0C0C0C100C0E0F100F0E0C1313141413131C1B1B1B1C1F1F1F1F1F1F1F1F1F1F010707070D0C0D181010181A1511151A1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1FFFC000110800CE00AA03011100021101031101FFC400AB00010002020301010000000000000000000007080506010304020901010101000301010000000000000000000001020305060407100001030301040606070504070900000001000203110405062131120741516122130871813242141591A16272822316B15292A233D1833425C1D253732435554363A354647456171811010002020102030703050100000000000001021103043112410506617181B1C1223221D142F05191E15214FFDA000C03010002110311003F00B52808080808080808083E2E278608249E6788E189A5F2C8E346B5AD157389EA0020A3FACF9C79EC97350EB2C55CBE38B1B3787!
86849219F0919A7039BD53ED2FF004F6234B91A2F56E3356E99B0CFE35D5B7BD8F88C676BA3906C922753DE638108CB368080808080808080808080808080808080808213F345CC2382D231E9BB3938725A803993169EF4766CFEA9FEF0F70765516150915377962E65FC83523B4B6425A62736F1F0A5C7BB15ED28DF4094774F6D11256ED104040404040404040404040404040404041D7737105B5BCB713BC45042C7492C8ED8D6B1A2AE713D400414179A1ADE7D6BADB239D7122D5EFF00071D19F72D6224443D2EF6CF69469AA20E5AF7B1CD7B1C58F610E63DA685AE06A083D8505E9E4973119ADF43DB5ECEF072F654B4CAB3A7C6634524A754ADA3BD35EA465BFA020202020202020202020202020202020847CD2F303E49A463D3367270E473F56CFC27BCCB267F50FF0078EA33D15458545457080824AE40F30BF46EBC83E2A5E0C365F86CF2153DD6171FC998FDC79DBF64942577D1910101010101010101010101010101075DC4F0DBC124F33C470C4D73E591C681AD68AB9C4F5008283734B5BCBAD35C64B3A49F857BFC1C7C6EF76D62EEC63B38B6BCF6946A1A9A02020115144177BCBFEBE1ABB405A8B9978F2D88A58E42A7BCEE06FE54A7EFB29EB0512525A20808080808080808080808080808219F341AF7E43A2060AD24E0C96A02613C2685968CA19DDF8!
AA19EB28B0A794A6C451010101049BE5F35E7E92E615AB2E64E1C566786C6F!
6A68D6B9
EEFC894FDD79A7A09425771191010101010101010101010101070E706B4924003692770414479D3AE4EB2E60E472313F8F1D6AEF82C60E8F02124718FF78FE27FAD1A868A8080808081EBA76A0BD5C8ED75FAC797B617D3BC3B25663E0B243A4CD08038CFFBC616BBD68CB7F4040404040404040404040404119F983D71FA539757BF0F27064F2FFE5F6343470F141F1641F722AEDEBA22C291014141B86E451010101010104CDE5775C7C8B5D3B0573270D86A16089A09EEB6EE2A984FE31C4CFA112570D1040404040404040404040402829BF99FD69F3DE609C3DBC9C563A7E3F87A0DC6E64A3A73E96F759EA45843C8A20FB8A09A5348D85DE80A65CFA78BB36FE159B7B9E96E26F8FB807A4853BA1D9D3C83953FC623DF30F97E32F982A6327D04157BA1C7B3C8F954FE19F7627EAF339AE69A38169EA3B157577A4D67168C4B8465DD697573677505DDABCC5736D23268241B0B648DC1CD23D0420FD03D01AB2DF5668FC567E0207C740D74CC1EE4CDEECACFC2F6908CB60404040404040404040404182D73A9EDB4B692CA67EE285B8FB77C91B0FBF29EEC4CFC4F2020FCF9BBBBB9BCBB9EF2E9E64B9B991F34F21DA5D248E2E79F5B8A34E941BDF2E794DA975A5D96E3EDC781111E3DCCC4B208B8B771B8024B8EFE16ED59CCF83BFE3F074F1EB1B795D67F1A78FC531B!
FCAAE4D9655873F01BB02AD88DBB9B157AB883DCEF5F0FA94ED7DFAFD4FAEBFA46BC53D931FB218CC622FF000F94BAC5E423F0AF6CE4314F1D6A0387511BC11B415997A8D3BABB6917AFE32F1A8E5754F6D0CEDE195A1C3AFA47AD5897CDC9E1EADF5EDD9113F3612FEC1F6CEA8ABA23B9DD5D856E272F09E69E537E2CE63EED73D27E92F22D3A8590F28BAD7827CA68DB993BB27F9863413EF0A32E183F95DF4A24ACCA2080808080808080808082B8F9BAD65C1698AD1F6EFEF5C3BE619003F7184B2061A75BB89DEA08B0AC88AF7626D84B3991E2AC8B6D3AC9DCB36977FE9FE0C6EDBDF6FC69F3F05D2E415CE0E4E5C63E1C7399F131193E651823C46DC39E6A5E37ED6D387B15AF47CFE7F5D9FF00AAD37CE27A7B9B7EA7D5B80D358E7DFE66F196B13012C6123C49081ECC6CF69CE3D8ACCBAEE371766FB76D233F2534D63A8A4D49AA3259C923F0BE3A632322DFC11801B1B49E9218D155C532FD3387C68D1AABAFFE618651F4883E658D92B1CC78AB5C2842B12E2DFA6BB6934B7EB12D66688C32BE376F69A7F62E487E61C9D13A765B5CF5ACE19AD0FAA2E34AEAEC56A082B5B0B86BE568D9C509EECACFC51B8855C0FD07B4BA82EED61BAB77892DEE18D96191BB9CC78E2691E9051976A02020202020202020E247B23639EF706B180B9CE3B000369250503E636A6B!
BD6DCC1CAE5ADE392E05DCE63C7C31B5D23FE1E11C1106B5A09DAC6F16C1D2!
8D30B94D
37A87130413E571975610DD170B692E627C4242D00B8378C0AD2A83D3856816AE774B9E6BF405C76EAF73E9AAC471E67FBD996B5BCBCB493C5B49E5B7948A19217BA3753AAAD20A8EFEF4ADA316889F7B8B9BABABA97C5BA9A4B894EF925739EEFA5C49516B48AC622310EA46840404182CBB40BD27ADA095C95E8F01EA2AC472A71E3586D1A9B95995C1682C16B37DC32E31F9C0D0620C2D740E91A5EC0F2490E0E0D345A746B35E59B57FCFB96B6F6533F8EF70521B096BBCC43BF038FE03C3EA4494B28820202020202020208CFCC36B1FD35CB3C80864E0BECB531D6943DE1E303E2B87DD883BD74421117947D1DF159DC9EAA9D9F938D8C59D913BBC69C56470FBB1803F122CB73F3718192F3446332F1B4BBE557B49BECC772CE0E2FE36B07AD08562C1CC2924277D789BFB0AC5A1EBFD31C98C5F5CF5FCA3EACAAC3D6880808080835EBC749777C5B002F7BDC2385A3DE713C2D03D2572C43F36F36E4C6EE45AD1D3A47C176353F2E45F7244E8E6B01BBB3C5C2DB5D9522EAD236BD94FBCF653D6ABAC56CE41F34ECB40EA3BB7E5DB37C9F271362BAF047198A58DD58E52CAED0D0E7034DBB516573B0F99C56671D064B15751DE585CB43E1B885C1CD703E8E91D20ED08CBD88080808080808315A9F53E134CE16E3339ABA6DAD85B0ABDEEF69CEF758C6EF73DDD0D0829!
6738B9BD91E6265A179B7F83C363CBC63AD2B590F1D38A494EEE37068D8360FAD1A885B0E4AE90FD29CB7C463646705E4B1FC65F6CA1F1EE3BEE07EE8219EA465B26A8D3B61A8F4FE4307906F159E4217412D37B788775E3B58EA3876A0A0BAA34DE6B47EA7BAC364A3F0EF6C64A076D0D9633EC48DEB63DBB54C3E9E3722DA6F1B2BD63FAC3D36B7715CC7C6CD847B4CE90571CC3F47E0F3F5F269DD5EBE31E30EF51F688080831D93C8363698623590EC711EE8FED5BAC3CDF9D79BC6BACEAD73F7CF5F67FB493E5AF96936A4D5ACD437D09F91E0A41287387766BC6D1D1462BBC47EDBBD43A56DE1E571BA1114239C3A5FF4CF3273B8C63382D8DC1BAB41D1E0DC8F15A07DDE22DF52350F4728F9A394D05A960B96CB24982B87866571E092C746ED86563770919BC11BF774A12BC587CCE2B338E83258ABA8EF2C2E5BC50DC44EE26387F68E90768465ED40404041C3DED634B9C435AD15738EC000DE4A0873985E66349E9F91F8DD3ACFD459BA98DAD809F86649B8074ADA990D7DD8EBE908B8576E6D6539A592C8D95E6BC8E7B537911B8C5D8BDA238638EBC2782104F03BAF8FBFBAA8B0F3727B49FEAAE63E1B14F671DA326F8ABD1D1E05B7E6381FBC406FAD095F608C8823EE6E727F0BCC2C531B23C59E6ED1A463F241B52DAEDF0A503DA8DC7A3A37845CA9CEAED13!
AB744E54D966ED1F692827C0B96F7A0980F7A293D970ECDE3A4239B46FBEAB!
77527B6C
F0C19B70004D1D7ED3767D4B1357A5E37A9ED118DB5CFB63F67A8662C88DEE1E90A76BB5AFA878B3E368F83E5F9AB403BA1CE3D54A7ED4ED71ECF5271E23ED8B5BE18786E72F71282D652261EADF4F4AD455D1733D41BB6C76D7ECAFB3AFF009485CA9E436A7D6F3C57B7B1C98AD375064BE95BC324CDE96DB31DBEBFBE7BA3B569D0CCAE3E9CD3B87D3B86B6C3E1EDDB6B8FB467043137E92E713B5CE71DA49DE8CB25D082B079BFD37E1E4B05A92266CB88E4B0B9701EF447C58ABE96B9FF00422C208D3382BACFEA2C6E12D4567C8DCC76EDEC0F7779C7B1ADA928AB0392D17CC4E48DECF9FD1F70FCE68B73B8F258A9B6BE360DEE7B5A3A3FDAB06CF78511134F2EF999A635DE1C5FE167FCF8C0F8CC7C8409E071E87B7A5A7DD70D8511B62020D735C6BFD31A2B10EC9E76EC42C3516F6CCEF4F3BC7B91475AB8F6EE1D25056EBFD4FCD8E7A65E5C560E2762B4AC6E0276F139B03195D86EA668ACCFA6DF0DBB3B3A51537F2CB91DA3F42451DC4317CC339C34972B70D05E0F48859B444DF46DEB2865A779BA8B0E74462E6B81FE6ADBF0CC73852BC0E8DC6707ECF0B5BEBA210C27940D2DC30E6F54CCCDB23998EB379FDD6D25988F5960425645104041E3CB61F1597B292C329670DED9CA2925BCEC6C8C3EA703F4A0887527951E5E649EF9B1335DE12579AF870B84D00A!
F5472D5C3D4F45CB4ABAF273950F3F09AA20733DD135A3C3A9DA5B211F52197AB1FE4E7BE0E4B5417301F66DAD43491E97C8EFD886525E91F2F3CB2D352C7731E3DD93BE8E85B7591709C870E96C746C43F851329283400000001B0008080822EF327A7C65F94F9395ADACF8A7C57F1506DA44EE193FF0DEE45842FE52F1389BCD7B7F7B75DEBFC7597898F8CD29595FE1CB27A5AD207E24256DDEC6BD85AE68735C28E69DA083B0821115939B7CAFCEF2E7383989CBC7BED2CA3717E42D22156DB711EF1F0F73EDDFEF34FB3E8DC54AFC9FE7361B9838E31B836CB50DAB01BEC713B08DDE2C04ED7464FADBD3D04848D5088A276D25FF003139AB6F6BADF2AFB292F6EDD6B3CAE151070BC816B0B7D98EAE1C0D2765769DA8D2ECE9DD3986D3B88B7C461ED5967616CDE18E160E9E9738EF739DD24EF465934152FCDCEA3375ACF198463EB062ACCCD2B2BB04D74EAFD3E1C6DFA51613E72534DFE9EE58602C5CCE09E5B76DDDC8E9F16EBF39D5ED1C607A9125BC2020202020202020202020F0E77170E5B0B7F8B980315FDBCB6CFAEEA4AC2CFF004A0A63C83CA4DA6F9C78CB5B8259E3CB3E2AE41D9DE7D5ADAFF7AC6A352BB88CBE268229E27C3330490CAD2C9237005AE6B850B483BC10828DF3170F77CB0E6CDCB34EDD1B775948CBDC63D86A638E71C62178E9036B483B!
DA8D265FFF00531FFA23BFE47F31F7BFC6FEEFFEDFEDA2611F7999E5DCDA73!
59FEA3B2
639B8BCF3CCC5EDD9E0DEB76C8DAF471FB6DEDAF52109DB90DCCF6EB8D20C6DE480E7F15C36F926F4C829F97381D5201B7ED02889350518D63249AE79E37904678D992CC476109DFF93148DB7FA38584A34BCB1451C51B228DBC2C8DA1AC68E80D1401197D20202020202020202020201414779C7692E93E75652E6DC787E15F4396B6A6EFCC2DB83FCFC48D2EDD85E437B656F7909AC37313268CFD991A1CDFA8A32D039E1CD26681D2A66B52C7E7B224C18B85FB434D3BF339BD2D8C7D2EA0458569E54F2CF3DCD2D573E432D34D262A39BC5CDE52424C933DDB7C18DC7DF7F4FEE8F50455BFFD11A4BFE916FF00E07E53EC0FF03FEC3EEA32E35C68DC56B0D337B80C9B6B05D37F2E502AF8A56ED8E5657DE63B6FD4828BE33506A7D09A8F223079236D7D099F1D3DD42016C8C6BCB1C40783D2DE269A541469BE72EBCC76B3D3F34B6B9EBB97338C9A39046F9FF32E2198B0F86F6C8685CDE3A7135DD1B90C3CDE59F0CFCBF36ACEEA66F18C6C3717F293B68F23C36BBF8E642574D19101010101010101010101010555F37F85106A8C1E658DA36F6D24B6948E975BC9C4DAFE19BEA4586B79EE7E6667E5B69ED2B83B8BBC75F58C22DF317CC2D8CCCC89BC11361918E2F00B76B8EC286115DC5E5D5DCCD92F6796E5D500BE57B9EFE1276D0B89457E8468ED3F86C069BB0C5!
E1ED85AD8430B0B231B492E682E7BDDEF3DC76B894659A402828B73CB43CBA479837D6E6764F6D9473F2566184F1B229E579E0901DC5AE040EB08D423F41653C9DE1766A3CE39BBCC1630BA9D038A57D0FADB544959544101010101010101010101010413E6F31826D0B8AC8D2AEB2C8B595EA6CF13C1FAD811615311590D3CDC5BB3D8D19698DBE2CDD43F1D306971640240647708DA7BA83F44ECE7B5B8B5867B47B64B59636BE092320B1D1B802C7348D94237232EE418ACCEABD31846D73196B4C7750B99E388EDEA0E20A0A5FCFED438FCFF003432390C6DE477D8EF06DA2B6B881E248C8644388348FB64D51A847682E7F95FC3FCBF94F6770E6D1F93B9B8BB27A482FF00099FCB1028929691040404040404040404040404114F99CB413F28726FA54DB4F6B337B293B5A7F95C51614B1144174BCB2E69F90E53E3A09A40F9AC259ED5ADA82E11B2425951BE94750224A57A844504E6AE97D4780D71958F3B0CBE25CDD4F35A5E49C4E64F0BE42E63A390FB5469A115D88D435141C38D1A4F5041FA0BCB3C48C4F2FB4EE3C0E13063EDF8DBD4E7461EEFE671465B2A02020202020202020202020208F79FF109393FA98104F0DBB5E29F665614214611A107B70CCCCCB93B7B7C2FC41C9CCF0CB58ED1CF133A43B833808354165BF44F99EFFE4CCFF94707F51BFD7FFCB!
FB3FE23FF0050889C751E96D3FA9718FC6676C62BFB27ED314A3711B9CC70A!
398EED69
051115E5BCA772D2EDFC7653E431849DAD8666C8DFA2664847D28B956CE61E96C560B98F90D358C7486C6D2E21B58E499C1F212F647C6E738068AF1B9DD08ABF36F136282389828D8DAD6B475068A0465F6808083C19AD4183C1D93AFB337F063ED1BBE6B891B1B6BD4388ED3D8104539DF355CB2C7BDF1D80BCCBBDBB9F6F0F8711F43E6319FE545C354BDF38D683FC169695E3A0DC5DB63FA991C9FB50C31A7CE266BC404699B6F0FDE06EA4AD7D3E1FF00A10C33388F3878791ED6E634E5C5B3491C52DACEC9C0EB3C2F6C250C24CD2FCF4E57EA2E08ED33715B5D3F75ADF56D64AF57E6518EFC2E28986F8D7B5ED0E690E6B855AE1B4107A8A0E501010681CFA95B1F28354171F6AD3807A5F231A3F6A10A73A4397BAAB5843927E9EB51792E2D8C96E2D83C3647364240F0C3A81C7BA7657D08D3BB03CADE60E6F303136782BC8EE8383677DCC2F822876ED74923C06803B36F520B75CA8E4A69CD0168276017FA826670DD65246ED15F6A381BFF0066CFACF4A339489C0D41CA020A3DCF88CE3F9D79B94B68D1736D74DED06189E7EB051A85DDB795935BC72B087324635ED70DC438541465D883A6F2F6D2CADA4BABC9E3B6B685A5D2CF338318D68E9739D4010401CCCF3538EB212E3743C6DBFBADAD7E5E607E198777E4B0D1D29ED346FA517086F0DA3F9AFCD9CA3B20!
7E23242A43F2D7CF2CB58F6ED6B091C3B3F7626A2A63D3BE50707146C7EA3CDDC5DCC477E0B16B608C1EC7C8247BBD3408996E565E5939416C07898C9EEC8F7A7BA9CFD218E60FA90CB27FFD01C9FA53F4D5BFF1CDFEBA1960737E56B9577EC77C1C1758A97DD7DB4EF7B6BDAC9FC51F4510CA2DD55E5235659B5F2E9EC95BE5E21ECDBDC0F869E9D8497C6EFA5A865A3D96A4E7072B320CB57C97B8815D96178D32D9CA07EEB5C5D111DB1945582E55F993D3DAAA487139F6330B9D9086444BBFE16E1DD0237BBD871FDD77A8944C2674410429E6BF3ECB0E5CC38A0EA4F98BC8D9C3FF00756FF9CF3FC4D60F5A2C317E50308F834BE7334F6D3E6178CB788F5B2D586BFCD29FA1094FF44410101010564F367CBEB8F8AB5D71671992DCC6DB2CB068AF01693E04AEFB278B80F6D1161E8E507995D3D8CD2F6D82D64F9E2BAC734436D908E27CED96068A461E19C4F0F60EEEEA1086194D5DE6DF4D5A44E8B4AE3A7CA5D1146DCDD036F6E0F5F0FF0055DE8A350C214C967F9B1CDCCC7C27FC4E548702CC7DB34C765057602E15F0DBF7A435ED454D1CB7F2A98BB074592D6B337257628E6E2A0245AB0EFF00CD7EC74BE8D8DF4A2653EDA5ADB5A5BC76D6B0B20B789A19143134318D68DC1AD6D00088ED4040404041E1CCE13119AB0971F96B386FACA51492DE7607B4F6EDDC!
7B46D415679D1E5C6E74E43367F49364BCC2B2AFBBC71AC93DB346D2F611B6!
489BD3EF
37B422E590E49799018C860D3BADA77C962C019619A755EF89BB84771BCB983A1FBC74ECDA86162A2D69A3A6B6F8A8B3B8F7DBF0F178A2EA1E1A52B52789115079F7CC06EBCD7B1DBE189BAC66380B1C670027C79A478F12460E9E37D1ADEB0075A350B63CB4D24CD25A1B1181D9E35AC00DD3853BD71212F94ECFB6E34EC465B3A020202020F0E6FE4DF28BCF9D783F29F05FF1DF13C3E0F834EFF89C5B2944153350695F2CD7B7B24D87D6D758989CE24DB7C0DE5D44DDBBA32E85AFA75778A2BBF4E69AF2BB6170C9731ABEEF32411485F697B6D01FBC23838A9E97A0B39A33F467C860FD21F07F26A7E57C070785EBE0F7BAF8B6A233C101010101010101070EA536EEE9AEE415239B9A7B90D7F98BCB8D3BAAA0C365DB2385E5936D6EE7B07C95EF18DF6F13DAC35DFC05CDEC08A8824C3631B216B73B8E91B5FEA06DF01F5DA03F522A68E4060794F63AAAC2EB23A9A0CAEA791DC388C7C76D7715BC5352BC5E2DC43135F2D2A195A7654A24AD78441010107FFFD9');
+
+insert into MemberImage (imageid, member_id, contentType, data) values (-3, -3,
'image/png',
'89504E470D0A1A0A0000000D494844520000009C0000009C08060000008AB8C24D000000097048597300002E2000002E2001D51C1E1B0000000774494D4507D20A0F061619FD8F7ED60000200049444154789CEDBD797C55D5BDFFFDDEF399429293309310669041A4A0828A8AA2A245AFB55A5B6B1F87F6D65FB5F76AEBD37B9FDBF65E6E1FAF5A156D7DEA80BE54AA16ADBD5A058B28A25026454108326A12022121643C39F3D9C37AFE38491A4C0219CE490EC8FBE5E6657272D65E67EFCF597BADEFFA0E921042F035C6B22C128904F1789C6030482C16231A8D128FC7711CA7DBED499284CBE5C2ED76A3EB3A5EAF178FC7836118A8AA9A864F7072F1B5BB028944828686060E1F3E4C797939870F1FA6A2A282DADA5ACACACAA8ABABA3BABA9AFAFA7A128944B7DB571485BCBC3C060F1E8CDFEF67D8B061141414306CD830860E1DCA9831631832640883060D42555524494AC3A7CC5CA4AFC308170804D8BD7B37C5C5C56CD9B2858A8A0A8E1E3D4A757535814080582CD6A3D1ACABC8B28CCBE5C2E3F1307CF870F2F3F3292C2C64DAB4699C73CE394C983001BFDF9FB6F36712A79CE01CC7211289505F5FCFB66DDB58B972259B376FE6E8D1A3!
442211A2D128B66DF77737511405C330F0F97C0C1C3890E9D3A7B370E142CE3EFB6C060E1C88DBED465194FEEE66CA3925042784A0B1B191F2F272F6ECD9C3BBEFBECBDAB56BA9A8A8C808717515599619366C18175C7001F3E7CFE7ACB3CEA2B0B0909C9C1C6459EEEFEEA584935A704208AAABAB59BF7E3DEFBDF71E5BB76E65DFBE7D442291FEEE5AAFD1348DC99327F38D6F7C830B2EB88079F3E63162C488937ECE77D20AEEC08103FCF9CF7FE69D77DE61DFBE7DD4D4D49C54A35957511485DCDC5CC68E1DCBD5575FCDB7BEF52DC68E1D7BD23E6E4F1AC1092168686860FFFEFDBCF1C61B2C5DBA94BABABAB44EF6330D5996F1FBFD2C5CB890BBEEBA8B51A346919D9D7D523D6E335E70420882C1209B376FE6F5D75F67E5CA9554565692E1DD4E3B0505055C79E5952C58B08079F3E6919595D5DF5DEA12192D38DBB6D9BE7D3B4B972EE59D77DEA1ACACEC6B35A29D08599619316204575D7515B7DC720B3366CCC87CE3B2C8404CD314070F1E14F7DC738F282C2C14BAAE0BE0F4D1C9A1699A282C2C14FFF22FFF2276EEDC294CD3ECEF5BD829192538C771C4C18307C592254BC4B469D3842449FD7E334FA643922451585828962C5922CACACA846559FD7D4BDB9131824B241262CD9A35E2DBDFFEB618306040BFDFBC93F9F0F97CE29A6BAE112B56AC10B158AC!
BF6FED316484E01A1B1BC5238F3C22264C98201445E9F71B762A1C8AA288A2!
A222B168
D122110C06FBFB16B7D2AF828BC7E3E2830F3E10575E79A570B95CFD7E934EC543D33471E185178A77DF7D57442291FEBCDD420821FA65952A9A6D6AAFBFFE3A0F3EF82065656569337348802249E8CD478BB9540096808470B0011B8123DABEABE5AFBA7E1ED1FCAF2A49A8486812E892842A49B458CA6CC016028BE4B94D91FC399D37419224468E1CC99D77DEC9EDB7DF4E6E6E6E1ACF7682BEF487E0CACACAF8C31FFEC04B2FBD444D4D4DDACEE39665466B1A67B90C86A82A59B28C2AB588031202428E43D071A8B76D6A6C9B2AD3A2CEB6093A493174450A52F3B986AA2A233595424D255751F0C9322E49469324D4E673DA084C01A6104484438D6573D8B428334D0E591671C7499BF87C3E1FB7DD761B77DD751763C78EED976DB23E159CE3386CDFBE9D5FFDEA57AC5BB72E2D7B9E12126E19CE300CAEF07A99EA32C85514342424E91F6317343F7384C02639DA9908628E43C071A8B26CBE4C2438649A54DB3601DB212E04961038800EE8B2845F5198A0EBCC74BB18A96964C93246F3482A4B129DDDD296679E25040921083B0EFB1309FE1E8EB02D1EA7C14E8EBCA4F8F6B85C2ECE3FFF7C7EFDEB5F3367CE9C3EB7DBF599E0C2E1301F7EF8213FFFF9CFD9BF7F7F5ACEA14A12859AC677B2B2B8C0EBC62BCB9DDEF0AEE2901464CC11441D8784488E522E59C6858!
45B96D08E23AC6ED12CFA12D3E49D509875E1080DB6D3A551B6BB141515F1C0030FB070E142BC5E6FCADBEF8C3E115C5353137FFAD39F58BC7831A5A5A56999AFA992C47497C177070C6086CB8592614E155FDD1F91E0B8220D390E1F8423BC1D0CF145C2C44E83E8860F1FCECF7FFE736EB9E5963E9BD7A55D709665F1C4134FF0D0430F5155559506B125479771BACE5DFE1CA61A3A4A06B8F0984270C4B2396026A8B593F344AB797120012E49225F5119A9AB0C57D50E47E38410EC8CC779A1A189CFE371441AC6BAC1830773F7DD77F3939FFC84010306A4B8F5F6A44D7042086A6A6A78FCF1C779F4D1478946A3E9380D20E193257E9697CB3CAF974CF19BA8B16D3E8AC428374D6A6D9B6ADBA2CEB209383666F3159749AE6287A82AB3DD2EBE99E565B0AAD2567A022837133C52DBC8E789384E1A6E97DBEDE6E69B6FE6BFFFFBBF19326448CADB6F4B5A042784A0A2A282C58B17F3DC73CF110A85527D8A6338D3E5E2C141F97833CC4D47004EB30924E438949B261B2351364562545A56F36895FC5741E21C8F8B3B727328D2B4766DED88C5595C574FB969A66515ABAA2AB7DE7A2BBFFCE52F292C2C4CDB0A5659B468D1A254375A5353C3830F3EC88B2FBE48535353AA9B3F0619896BB27CCC70BB5233714F2112C995AA2A49789ACD26530C03972CB32F9120DAE!
6BB2E801ADBC127CB4C368C76D302BFA220803DF104F1348C728EE3B07FFF7!
E9A9A9A9
832650AD9D9D969115DCA87846834CA030F3CC0F3CF3F4F636363AA9B6F87579638D365649CD83AC323256D833E59E6AB86E584E370C034893AED05A54B12E779DC4C36D2F75943A1102FBFFC32F7DF7F3FB5B5B56939474A05D7D4D4C4E38F3FCED34F3F4D381C4E65D39D3256D7199EE93E60CDD840A965B22214A2D2B2DABDEE9365C6E93A6EB963490D5555CEF3B8F1A5C0DCD319A15088E79F7F9EC58B17A7E5E994B23BD5D4D4C40B2FBCC0EF7EF73B62B158AA9A3D2E3230C9E8FC06651236B0351AE34F812676C5E358CD8F4519098F2C315455B9D0E3E132AF17BD934799044C77B918AEA9EC8D773F48BBCB7DB56D9E7CF249727272B8E38E3BC8C9C94959DB29119C6DDBFCF5AF7FE5D1471FA5BABA3A154D7609AF2C3346D7D0A5CC5A2C748410825ADBC62B271F8DBA249125CB0C5255062B0AC35595024D3BE1976798AAF00D978B7DF1445AF75F83C1208F3FFE38797979FCE0073FC0308C94B4DBEB55AAE3386CDEBC991B6FBC91C3870FF761AC81C4385DE317F97E26E87A1F9DB37798CD2B56A9CD2123214BDD9BDB949A26775655134EB3BBBD2449141515F1C8238F70CD35D7A42452AC57438310825DBB7671CF3DF7505151D1A7812D3282024D6390D27E90B6051C32AD762BC1FE469324DC92844B92309ABD57D46E8A0D60A4A6F10D97ABD9E49DBEE9!
841082B2B232FEEDDFFE8D1D3B76A4A4CD5E09EED0A1433CF2C823141717A7A433DD4193650A3595014AFB8F5069593CD9D0C843B5F5FCB52948228344970A1460AED783576EF17B492F252525DC77DF7D1C3870A0D76DF55870E17098975E7A89B7DE7A8B783CDEEB8E7417AF24315AD3E96890DF168BF14934C617099357024DBC150CA5FDF1D3D74CD27546F7D1544208C1BBEFBECBD34F3FDDEB956B8F160D420856AE5CC9430F3D9476C36E67F81585F1467B8BBC20B91A4C88A4C0028EE0D986463E8FC7F9A6CFC7683D6903530124A9D53D292A044DB64DAC7934744912D98A82A7D970DBF2F0CA94B172B0AA70AEDBC5178904D13EF8324522119E7BEE398A8A8AB8F5D65B7BBC88E891E0CACBCBB9FFFEFBFB4D6C00233495BC0E26B1B61054DBF631E28809C1BA70849DB138535C0623358D6C59462669AE08380E472C8B030993BAE674117E45618CAE51A8690C535506A90A43D5A4636526AC897549629A613058553890E89BD1BBAEAE8E279F7C9233CF3C93D9B367F7A88D6E0BAEB1B191C58B17F3F9E79FF7E884A96292A1637464AF922414E91FEEDE2D3840AD6DB32E1C4191243492ABB096BDCEAFBA79D7D949074C4D92F0C932036499A19ACAE55E2FE7379B35FA9BD1BAC6784DE760C26CE7FE940E5A16898B172F66E9D2A5F87CBE6EB7D1AD2FAB699A!
BCFEFAEBBCF6DA6B581D58CAFB0A05986AB83A7D6D82AE2377F2F06BF1B28D!
0A41C471
88357BF176F4D749377441BD6D73C034F9341A676B2C96312B5F9F2C739EC78DA7838553BA701C87952B57F2E28B2FF648035DEE698BBA9F7BEE398E1E3DDAED13A592018AC228ADE3C159022EF27818AA6AF4C60F5722E9D4E99124F21485D1BAC67CAF87853E1F5919E49532C3EDA2506D3F974D27D16894A79F7E9A4F3EF9A4DBA6B02E3F5263B1182FBCF0025BB76EED760753CD585DC3751C8BFC7843E75B037C2C0B04A973EC4EE202A4631EBA8A04D9B24CBEA290A7280C541506A92A7E59265B51C8571446686A46890D60802C33DBED664F3C911657F4CED8BF7F3F4B972E65ECD8B10C1C38B0CBEFEBB2E076EEDCC94B2FBDD4A344CBA9232992E423B373C1B96589053E2F862CF1526313D5964DDBF99C04F864897186CE384D67B8A6325453C896157C928C4B4E1A665D6D56A8998A049CE771F1976090A63ECC8F178FC759B16205575C7105D75C734D97538675696BABAEAE8E1B6EB8810F3EF8A0D71DED2D6E59E697F9795CE071774908074D933F3636B13D1EA7D17618A42A5CEEF57099CFCB1055CD8815676F89380EBFAB6FE4BD5098F4051976CCAC59B358BE7C79973D854F78BD85102C5FBE3C231EA5909C280F54952E8F3A859AC6CFF372B9C79FCBB7B2BCDCEDCFE1E6EC010C3B45C406E0926566B90C7CFDE035B375EB56962F5FDEE5B9DC09AF794!
94909AFBCF20AC160B0D79D4B050364194F374D129EE6D5DCEDB939CC72BB3322C82695C8C0584367A4AEF57970B3E3383CFBECB394969676E9EF8F2BB8783CCEDB6FBFCD471F7D94318900157AB65DDD122975AA8C6A5F65B8AA32CD3048AE57FB5674BB76EDE2E5975FEED2FCFEB8D7FFC08103BCFAEAAB1933BA01049B6D67A739165D9298E172E15714A43E9EC745A351DE7AEB2D76ECD871C247EB7105B76AD52AB66FDF9ED2CE9D987F788B75B43E6CB06D0E24D213B974B233C1D019A969FD726DF6EFDFCFEAD5AB4FE8EDDDA9E01289042FBEF862DA3C415AB21A69CD7E61862461C8125E59C2AFC8E42A0A6E39F93B434E9A27001208D646A2D8A715D78E2C59E66CB7AB5F92D484C361FEF6B7BF9D7053A0433B9C1082D75F7FBD574E7712128A24E191204751C85564F2149561AACA6055214751C89625BCCD8B005D965BE76772F3056BBBBFB93C186269630047C0E668940F2261E6793CAD423C4DF32E8BD7C3D24080603F7C23B76CD9C2F2E5CBF9E94F7FDAE9DF7428B8868606962D5BD6E3858221498CD274261A3A930C9D71BAC64045C527CBED727E74C5E5C701CADA0400DB42B02C1024575638CB659C165D1BF21485A986C1A648BA321D748E65592C5DBA941FFEF087B8DDEE0EFFA6C347EAC71F7F4C71717137F6C9FE71C3B31585EB0764F1F3BC5CE!
EC8CDE60A9F97B1BA4EB6D25E6CD035FFB288E3F065C23CE677E5A6C9F38D0!
1B64463A
D1150A749DED099FD98CC67D7AE5D6CDEBCB9D3D7DB092E168BF1FEFBEF535959D9AD136992CC54C3E0DFF3FDDC9C9DCD0443C793A2F8C9C39645E82BA3AD2D047BE2711EADAF67595313B5B67D5A78CD4C3474BCFD14C996482458B66C59A773FF76BDDABB772F6BD7AEED96EB8921495CE275F38B7C3F73DCEE94C789D65A367607627280A396CD0B8D4DFCFA682D6F0443EC4B2488A4318BE4C9408EAC304453FB650F5808C1C68D1B3B9DFF1F3387B36D9BE2E2E26E250C542489391E37B7E7E430584D4FC1B1F80972E0DA42B02B1EE7CB8449A1A632C36530DDE562BCAEE357E4536E67E144B86489818ACA17F48FA3454545059B366D62E6CC99ED36F58F115C2C1663EDDAB5DDCA763456D7F85E7656DAC406C91D82AEF86CC485C3178904074C930F23110A548DB35C2ECEF7B818A16919E1A5DB17E89244B62CF55B1046381C66CB962DD4D5D5B5735D3A4670B5B5B5AC58B1A26BAD4A304052B8362B8B311DA4974A252334154382AEEE77984270D4B2A9B16CB6C762BC169419ABEBCC72B998E13218A26AF8E4CC773DEA292AC9A439FD35AF1042F0F1C71FB377EFDEE30B6EDDBA75D4D5D575A95149C0485D6592A1A7DD2C31445519A169D476D3DF2B99351C9A6C876DD1383BA271F2D56412E8292E83319AC6283D1950A39D62A35F7F7F9CC3870FB36DDB36CE!
3DF75CB4360352ABE02CCBE2DD77DFEDB229442229047F1F148AD52589CB7D5E76C5E3983D5E8926C301AB2D8B6ACBE2E368B4D5757C9CAE738661305ED7C8CE90A8ACDED2DF8BA6783CCEFAF5EBB9EDB6DB3A165C7575351F7FFC71971B949AB7A2FA221437E9D5EAE6D3989B75E1684ACC1F7121A8B42C8E58169F466378649961AACA1497C1592E23693B94E5D6C76EFB6C6E998B808CD8FADBB06103A150E8985AAEAD82DBB87163B792D00901E166CF8D8E6DCAA9430039B2CC3FE7E4902D2BAC0B47A9B3531335E6908C5B8DD90E0D4E9C5DF138FFDB2431505198E63298A21B8CD63586692A39F2C9B1E2359B0B9EB4AD8F23D13E937ABA397AF428EBD7AFE7861B6E68FD9D0A4927BA6DDBB6752BF1B3008E5836B5B64D6E1FD55F1FAAAAFC5FD90398A0EBBC110C529230B1C45723507B8A688DB5B184A0CAB23812B2582B4518A8AA8CD575CE74194C6DF6C8E830263643480841A0D516998C3A9BE13668B06DF6274C9AEC7424E16F8F10820D1B3670FDF5D7B73A14A800F5F5F5ECDDBB17D3348FDBC0318D21386C5A7C993019AD779CE3231DF81585CB7C5E8A3495BF85C2AC8D4409DA2DDFDDD45E4601C40554982695A6C5A7D128C35495B3DD6EAE1BE0EB30F23F13880BD19A414042304AD7B83D271B04EC4B24D8188DB2251AA3B10F84F7E9A79F1289445A!
8B8FA89074B43C70E040B7630C838ECDAA50986986C1F04EE244538D20E9F5!
3BD13028
D274E67A3CFCA5A989CFE309224E3A02E50412120E829023D89F4850629A6C8BC5B835279B192E23E356B8F5B64DB56501024D929866E80C5255146088A632DBE3A6DCB458190AB13112A5DEB69B1763A937DC959797535555C5D8B16301908510949696525555D5EDC604F0793CCE3BA1706BED81BE2259504DE26CB78BFF273F8F5B72B25B3384A79AAFCAD81682BDF104CF3434B23BCD99287B42A9F98F0437398AC2791E77EB134822B915395ED7F8496E0EBFCCCFE39B3E1F23342D2DABF35028C4279F7CD2FAB36ADB36070F1EA4A1A1A1470D9A42B0321466BCA1715E3F05A8F815856F65F998E132D81C89F16E38C461D34AEB24D941506A9AAC8B449860E8B832649413C0E7B1042D4B86F3DD6E46756298D7A56406F831BAC6797137ABC261B644A20453B8171D8FC7D9BD7B77EBCF6A381CA6A4A4A45BF3B7AF5267DBBC1C08E29365A6BB5CCD793DFAF6066892C4585DA750D398E936782F1C667D244ABDED74B8F19F0A6C017BE309628EC09521C5BDC28EC38E781CA9F97AFC5396EFB8838044D2537896DBC5385D63ABDBCDF26088DDF104A6E87DB125D33429292921140AE1F3F95083C160AF331B0A605F3CC1530D01FE4F6EB2C85A7F184F5B1E176718061375836B7D26AB9A8577D4B2D2107C934C141D130E692879D123CA4D9306DB66B4A671476E3685B!
AD6A5999904E42A0A977A3DCC76BBF830126179304C79C224267A3EE2398E43555515B5B5B5F87C3EE454088EE6B2635F2412FCB1314069BFA68348224B3052D7B825279B5FE4F9B97EC000CE308C946FE0871DD18BDD8FD4A34B12B33D6E7E949BCD34C3E891C1DA2BCB2CF0FAF8BFF372B976808FC1AADAABC440757575ADB10E6A2010E8F2FEE9897084A03816E7B9C600FF273787024DEBF7CD71439298EA3218A7EB5CECF5F04934CADA4894D284D9A684504F052311719C8C49DF05C94C0377E5E632B0976E598A942CBA32445599A0EB2C6908341733E9FE670D0402AD9B0AEAA14387529AC9D246B0251A4321C0EDB9D98C4CD3EAA73BB4AC68C7EA1A459ACA7C9F97CFE3713E0845288EC709394EF37CA5BB24F767BF4C24189F21A9FB0D4966889A9AAF79CBFCEE42AF07972CF3FFD53770B807C5E51A1A1A387CF8308EE3A0D6D4D4A43C14D01482CDD12802B83D279BD17ADFE62F3B1EAA2491AF285CE4F130A739CDD5C7D118BBE271CA4C9326C7E9568948097827146686CBC5908C28C194FAD13619276170E3802C9E6B0CD0603BDD3A4F24122110082084403D78F060CA3B08C9FDBC8FA25104821FE7E63032CD3E733DA1C52C30C9D0A9B66CF6C4E3EC88C7F93C16A7C2B2BA34371348EC8927783910E4E6EC2C066784E8528F26499CEB76F3692CC6FA6EC!
605DBB64D636323A669A28C1C3972D1CE9D3BD3D24907A8B46C8E5A36639A2!
3B7FA7B4
ED7118A2491ADC88CD292FBA533DD6E261A3A0ECD8B028EFF7DB681439695CC5DE7EA24F7F029805B96890BC1F678ACDB2534C78F1FCFC5175F8C9AEE4CE496804D91288DB6CDED390338D3E5CA588F0B45822C49264B4FD6F09AEFF35067D914C7136C8946F93261D2603B841D8784708E312C471DC15F832126EA3A177A3DFDF619D2890C4C7719E4292A4D76F72C118D8D8D241209D474D5C5FC07021B895DF1044F3606F8514E4BDC64E689EEABDF59058941AACAA5AACA5C8F9B6ACBA2346171C03439689AD4D816412799945A2199A6A2EF7250F60F7E456190A250D6CDF75996955C34F4640FB5FB081CE08B4482A71B02DC9CED70BEC7735205B5E8924481A63142D39823DC841D87A0E310150E8E684E072627FDE84E653409727B9035BDA9A909D334935B5B7D8510509A3079AA21C051CB61419697EC0C4BD27C2224409740536472FA305D7DA620418FBC63EAEBEB89C562C87D293848EE491CB56C9E6F0CF05C43806AAB6F9C0153C9C9D6DF54D34185F413128FC7938FD4EE78F9A60A812026E06FA11041C7E1FA01594CD0F57ECB87719AAE638B6452C8EE629A268EE3F4E72640720F725D24C2EFEAEBD9188D627DDD878E9380A81034383D5F1AF5FB24C46A7666FC7F6BEA78A131408D65F769818BD3748F1ACBA6CEEA85E0B40CD901880BC1AB4D4D3C5EDF!
C0F658FC942BAA7B2A2048E6E90B8B9EBBB6CA3DA908971E928FD88DD128BFAF6FE0AFC160B7ADD9A7492FA610942412447BB06A300C034551907B5A68355D5802CA4C8BE71B9B78B0B68E7D894446F99B7D9D69B06D4A4CB34781E8BAAE23CB3272770A73F50D02210451C7E1C37084DFD4D4F14630C411CB3A3DB3EB470470D0B47A9C417ED8B061783C1EE4A14387A6BA6F29C3010E9926CF350478A2BE914FA2D1D3351AFA898410EC8A27A8ED612CABA669C8B28CEA72755CE8B6BF70B95CF8FD7E7C3E2FB5B57534353511B32C3644227C99487081C7C33559BE3E8B833D0D80A0CEB2F9381AED7138A8CBE5425114D4418306A5B66F3D4055550A0B0BB9F6DA6BF9CE77BEC3E8D1A3D1759D5028C4A79F7ECAABAFBECA7BEFBDC7E1BA5A5E0B06F9201CE67B39D9CC76BB18A42819E908702A6103EF86C3EC4B24E8E93E8BDFEFC7300CD4C2C2C29476AEBB689AC6F9E79FCFBDF7DECBA5975E8ADEC6553B2B2B8B850B173277EE5C5E7EF9651E7BEC314A4B4B396ADB3C5DDFC84697CE3CAF87592E1703D5FEC9697BAA2380BD719355A1708FB3564992D43A8753478C18812CCBFD56BCADB0B0905FFCE2175C7AE9A5A89D78CB66676773FBEDB7E3F178B8EFBEFB282D2D25261C3E8DC6F82261B2C9887185CFCB592E03DF49E60C90E91CB12CFEDCD4C4D15E14FF55!
5535192228CBA843860CC1E3F1742BAF6FAA902489F3CE3B8FB973E7762AB6!
165C2E17
37DE7823008B162DE2E0C18308A0D1B6D91489B2331EE70C436781CFC7375C061E59EEFF6D94939CA396CDB2A6201F4563BDCA37979595455E5E5E5270C3870F273B3BBBDF043773E64C3C9EAE79C8BADD6E6EBAE9261CC7E1DE7BEFA5B1B11148468AB5086F6B34C6D91E37177BDC9C61180C5294D3956ABA89209929F4C54013ABC361E23D710F69434E4E0E43860C419224648FC7D3E5F2D1A9469224727272BAF51E5DD7B9E9A69BF8E10F7FD89A02AA2D7121D81089F2FBFA467E57D7C09BC1101566D702624E93CC99529248F05C6313EF867A2F3680DCDC5C060F1E0C80ECF57A292828E875A33D4108D1A3985897CBC59D77DEC955575DD5AE0E404BBB013BB98C7FBE31C0037575FC2910A43461F67916C893094B08B645E33CD9D0C887E1704ABEA49224919797477E7E3E00726E6E2E93274FEE9792874208F6ECD9D3ADAA372D8C1C39927BEFBD9759B366B5EBBB24494852B24C6DC871D8198BF3C740807FA9AEE6BE9A3AFE1E89526559A7F76A8116F7FFA396CDD24080DFD4D6B12D9A3AE7095996292C2C6C159CAAEB3A050505783C1EFADCFB57088A8B8BA9A9A9A1BB3B1E9224316DDA347EF4A31F515959C9A1438770B95C8C1E3D9A891327128D46292E2EA6AAAA0AC749C61D34398235E1081F45A38CD5F5E68A3506855A327BF9A91D8DD0310147B0231!
6656528CC27D1581BC36E6A9213EABACEB871E35ACD5D6A5B05F6B5E000CACACAF8E4934FF8E637BFD9E1E3F1781886C1F5D75F8FAAAAAC5EBD9AA2A222E6CF9FCFA4499388C562AC59B386DFFEF6B7ECDBB72FE96397FC8F9023D81E4B46DBBF1F5619A36B4C310C66B85C8CD054F453B460485B6CA02491604530C4C7D11847ADF4E4D373B95C4C9D3AB5F567490821F6ECD9C36DB7DDC6471F7D9486531E1F4DD3F8C10F7EC0FDF7DF4F4F773D128904E170185DD771BBDDADC28DC7E3AC5EBD9A3BEEB883CACACA4E53CACA804B96F12B0A93749D996E17530C9DC1AA8A2249C8F475B6BBF4610B418DEDB0261CE6DD5084C3968595823C709D3172E448366FDEDCFA0453162D5AB4C8E572B161C30676EFDEDDED3CBFBDC5711CCACBCBC9CDCDE5ACB3CE3AA13DAE231445C1ED76A3EBFA31F33955551933660C454545141717535F5FDFE1E713245353343936A5A6C9A648940F2251F6C51334D83609219049E625514ED2D1CF128223B6CD3BE1084F3734F061244A836D93EEBA8BE79E7B2EB7DD765BEB7D55162D5AB4C8300CBEF8E20B366EDCD8A3097C6F8946A3ECDDBB97499326316EDCB8942E60645966E4C891E4E5E5B167CF9E2EA52613246B37949B269FC5E26C8BC5D91D4F506E9AD4DA365147A048C95A5D72860BD0165061597C1889F25A5313AB42116AF!
A286D3EC0CD37DFCC25975CD2FA73EB70F28D6F7C03B7DB7D4CAD064992505!
5B5DB73A
B8EB06DFBB8622E2F2FE7B7BFFD2D679C7106A3468DEAF5F9DAE2F57AB9EEBAEB505595BBEFBE9B9A9A9A2EBF37D15CB3A1CAB2F93416C32BC9642B3283559511AA4A91A631D6D018AEAA64C932AA44AF92F7A58A4473A59D8D91289BA351CA1226A13EAE23ABAA2A175D74D131BF9344F333A6B1B1910B2FBC90E2E2E2D617A74E9DCA4356966B08000012BA494441540F3DC48811237A35EA388EC3175F7CC1CB2FBFCCFBEFBF4F30D8715D40C330B8F3CE3BF9CD6F7ED3A151B7B75896C54B2FBDC4AF7EF52BAAAAAA7A357D68A9EEA248121A90ADA80C52158A3495519ACE704DC5AFC80C90155C92842A251FC92DA5945A8EB6C9EA8F97AD524234D794F907826470B98920210411C7A1C6B6D9198FF35934CE17099326C76E9EA3F53DE3C68D63C3860DC7CCCD5B47B8ECEC6CE6CD9B778CE0F2F3F39933670E03060CE8F5C9A74C99C205175CC0238F3CC233CF3CD3BA2DD596783CCE8A152B983B772E575E7925A90EF05155951B6EB8816030C8C30F3F4C4545458FDB12CD872392D995A2CD75BB8A633164494293247C9244AEA2304455C85314FCCD874F96F14A326E59C22DCBE8523295842649B4F8BC286DCA9DDACD8249088129928FFBB0E310721C02B64DB56D73D8B238689A545916415BA47D6E76222449E2924B2EE1AB31336ADB3FB8F2CA2BF9C31FFED0FA!
E83B7AF42895959529119C24490C1C38909FFDEC674892C433CF3CD361AAFEB2B2321E7CF0411CC7E1EAABAF464971AE0EAFD7CBF7BFFF7D82C1208F3EFA28F5F5F52969B7ED18620B812D0431A0D6B6F922F18FD150259906D625CB1892845B92309A0FB559741260C8C9D5B10598CDF94BE2AD827308394937FC88488E6E763F8D629DE1F3F99833670EED6266441B8E1C3922264E9CD8F2E51583070F166FBCF18648258EE388AAAA2AF18B5FFC420C1830A0F55C6D0F599645414181F8FDEF7F2F6A6B6B856DDB29ED831042D4D4D4887BEEB947689AD6611FFAF39040C82064242165407F7A729C75D65962DBB66DEDAEFB31828B4422E2DE7BEF15B22C0B400C1C38502C5BB62CE5375B0821C2E1B0B8EFBEFB84DFEFEFB4D3BAAE8BCB2FBF5CAC5FBF5E589695F23E343535899FFEF4A762F0E0C1AD9FF9F4D1FB43966571C71D7788A6A6A676D7FC18C1D9B62DDE7CF34D919F9F2F144511D75D779D28292949F98D6E7BC3EFBBEF3E515050202449EAB0F38AA2886F7DEB5BA2A1A1212D7DA8AEAE16CF3CF38C983F7FBEC8CECEEEF6C56DE9B72CCB42D775611886300C43E8BAFEB515715E5E9E58BA746987D7FB182BAB2CCB4C9D3A95B973E7E2F7FBF9D9CF7E46515111E9222B2B8B3BEFBC9361C386F1E8A38FB27BF7EE769EC7B66D5359599936FBE0A04183F8!
C10F7EC085175EC8D6AD5BD9B87123C5C5C5949797D3D4D4D47A5E555571B9!
5C646767
E3F7FB19346810F9F9F9E4E7E7E3F7FBC9CACAC2308CD6D5BC10824824426565259F7FFE39DBB76FA7B2B21297CBC58C1933983E7D3A43860C212B2B0BCBB20887C3D4D4D470E8D021CACBCBA9A8A8A0A9A9894422D17A4D14452137379733CE3883A14387B26DDB364A4A4AFACD5BBB33468F1ECD79E79DD7E16BEDCCFA4545452C58B0803163C63071E2C4B47B91E4E4E4F0FDEF7F9F59B366F1C0030FB07AF56A0281406B2926AFD7CB95575ED96EB5934A0CC360FCF8F18C1D3B966BAFBD9668344A381C261008B4EE2F7B3C9E5651E9BA8EAEEBC94872596E3DBE8A1002DBB689C7E3AD35E073737399356B16595959288A728C405B6C95D16894C6C6460E1F3E4C7D7D7DEB0EC9A0418318356A1423468C40D3345E79E515FEE33FFE2365753652812CCB5C7AE9A58C1E3DBAC3D75BED706DF9ECB3CFF8E8A38FF8F18F7F9C12A36F570987C3AC5DBB96356BD6505A5A8A6559CC9A358B5B6FBD95FE0EF6C9341CC7E12F7FF90BFFFAAFFF4A7575757F77A795010306B065CB16264C98D0E1EB1D6E5C4E9C3891952B57525555C5F0E1C3D3DAC1B6B48C66F3E6CD23180CE2380ED9D9D9645AEC6C2660DB36555555FDE2E1733C2EBAE822C68C19D3E9EB1D0E5F6EB79BF9F3E7F3F6DB6FF7F9FC409224DC6E3783060D62C89021B8DDEE7E710ECD7442A110FBF6EDEB56D!
9F874E3F3F9B8F5D65B8FEB80D1E9F372E6CC99D4D5D55156569696CE9DA677D4D6D6525C5C8CDD8BF0BD54224912975D7619B367CF3EEEDF752A38599639E79C73D8B46953AF6AA99E26F508213872E4480AAA40A60EBFDFCF82050BF0FBFDC7FDBBE3AE08A64C9942381CA6BCBC3CA59D3B4DEFF9F2CB2F53B62DD75B244962C68C19CC9B37EF84FBDFC7155C7E7E3E0505057CF6D967292F00779A9EE3380E5BB66CC9987B929393C38D37DED8259BED7105A7280AB367CFA6AAAA8A43870EA5AA7FA71C8EE3505D5DCDAE5DBB28292939AE1062B118895E1630B62C8B4F3EF9A4CFBDB33BE3820B2EE0DA6BAFED9209ED84FEDC7EBF9F33CF3C93356BD63066CC98D32BC60ED8B163078B172FA6B4B4148FC7C3A5975ECA77BEF31D8A8A8A8EB95E6565652C59B284E1C387F3DDEF7EB73574AEBBD4D7D767CC62CEED7673E79D77929B9BDBB5377465BF311A8D8AFFF99FFF113B77EE4CC9FEE5A9446565A5B8F8E28B85A228AD7B8959595962DEBC7962D9B265A2BEBE5E44A351F1FEFBEF8B2BAEB8421886210A0A0AC41B6FBCD1632F98BFFFFDEFC79CAFBF0E4992C40D37DC2002814097FBDE25C10991745D5AB46891A8A9A9E9D1453A15711C473CF6D863C2E3F174EA353164C81051505020DC6E77EBEF0DC3108B172F16F178BC47E77CF8E18733426C93274F161!
F7FFC71B7FADFE57D2BBFDFCF942953D8B87163AFE720A712A3468D62EAD4A!
90C1D3A1
4BFDF7F8CA1DA711C8E1C39C2A143878E31D0FAFD7E468E1CD923E752D334D9B3674FCAFADF53B2B2B2F8DEF7BEC7E4C993BBF5BE2EC7E4699AC6ECD9B379F3CD373970E000E3C78FEF76274F355A8C9D23478EA4AEAE8E582C465555156FBEF9266BD6AC21168BB57B8FCBE5E2AAABAE62CE9C393D125C2698A92449E2ECB3CFE6A69B6EEA7EEC49778643DBB6C5A64D9BC492254B442412E9D650FA75C1344D515555259E7DF65971D145178921438688DCDC5C91979727C68F1F2F1E78E001515555251CC7E951FBFBF7EF17D3A64DEB777FB7F7DE7BAF479FA1436F91E3615916AFBCF20A7EBF9F2BAEB822E53107A70A420842A110656565545555B5E63DE94D049C1082E5CB97F3939FFC84CACACA14F7B86BB85C2EEEBEFB6EEEBBEFBE63EEBD6876AF6AEB72D511DD0E73575595ABAFBE9A254B96505050C0D4A9534F9B4A3A409224B2B2B298366D1AD3A64D4B499B353535BCFDF6DB74A58AB72449689A86AAAAAD62B06D1B915C2876F89E138D3D8AA2306FDE3C7EFCE31F1F23B6D2D252B66CD942341A45D334E6CC99C3A851A33AD4458F72CF67676773F9E597F3DE7BEFB57A759C26BD44A3515E7DF55556AC5871C2459B61185C72C9255C7DF5D5E4E7E763DB36E1709870384C229120180C128FC70987C3C4E37142A1109665D1D4D4846DDB44A3D1D67293D1!
68B4D589D4ED7673D75D771D934FB0A4A484C71E7B8C499326E1F7FBC9CDCDE58F7FFC23D75C730D3366CC68D7B71E173B983C7932959595AC5AB58AEBAEBB8EACACAC9E36759A1390482458B26409FFF55FFFD5A5048E2D99066EB9E5960E4799AF8E646D7F164224D39B35BBA5398E433C1EE7B5D75EC3E7F3317FFEFCD6D12D1E8FB36CD932BEF7BDEFB166CD1A4CD3E4D34F3FE5861B6E60FDFAF58C193386ECECEC63CED563775E555539EFBCF31042B06EDDBA8CF3AB3F55701C878D1B37F2E8A38F76395B682C166B4D67D1929CB1EDD1D62D5E96651445693D545545D7755C2E172E970B5DD7D9B66D1B9665B170E1C2637CDD0281003E9F8F3163C6505050806DDB8C1E3D9A51A346919797D761B07BAFFCC7070C18C055575DC5EEDDBBD9B66D5BC6ECED9D4A545454F0D4534F756B91A028CA31013D3D4534278CFCE4934FF8F6B7BFDD2E205E5114C2E13096659148245A7DF362B118B158ACC30565AF0316060E1CC84D37DDC4DAB56BD9BB77EFE9912E854422115E79E51556AF5EDD25474B4551C8CECE66E1C2855C71C515BD129C1082929212366DDAC4C2850B3BCCDD979B9B4B616121EBD7AFA7AAAA8AB3CE3A0B455178EBADB7300CA3C3B97DAF05D75265E4924B2E61D5AA559495959D1EE95280E338AC5FBF9E175E78A1C347535B5455A5A8A888EBAF!
BF9E175E7881E79E7B8E891327F6EAFCD5D5D52C5FBE9C2953A63069D2A40E!
C52BCB32
DFFDEE770906834C9A3409AFD7CBD0A143515595050B1674E86ADE6D3B5C6798A6C9E6CD9BD9B9732737DC7003995716F3E4A2A6A6865B6FBD9555AB56753ABA699A46515111975C7209575E7925E79E7B2EF9F9F9BD7E94D6D5D5F1DA6BAF3166CC18E6CD9B77C22491914884DDBB771308045A4D419D063EF5C8DCDD098944427CF8E187E2B1C71E13A15028954D7FAD304D53FCFEF7BF172E97AB536B7F6E6EAEF8E77FFE67B176ED5A51575797B2FC2B8140403CF1C41362E5CA95C234CD94B4D996940A4E887FA48B78F4D1477BB585F375C5344DB162C50A515454D4A1D05C2E97983D7BB6F8E0830F442C164BE9F5ADA9A9114F3EF9A4F8D39FFE94B6ADCB944739CBB2CC65975D466161216FBEF9664605E9663AA2B96EC5134F3CD1CEC3BAA5C0C6CD37DFCCB3CF3ECBC5175F9C9295680B8D8D8DBCFEFAEBF87C3E162E5C88DBED4E49BB5F252D61F56EB79BCB2EBB8C810307F2E73FFFB9C33C70A7694F5D5D1DCF3CF30CEBD7AF6F376FCBCFCFE7EEBBEFE63FFFF33F39E38C33527ADE868606962D5B86CFE7E39FFEE99FD26BC44FCBB8D94C341A151F7EF8A178F8E1874F3F5E4F403C1E17F7DF7F7FBB0C4E92248941830689254B9688402090D26BE8388E3872E48878EAA9A7C49B6FBED9271E4069159C10C90FF5D1471F89871F7E58ECDCB9332DC9054F769!
A9A9AC4534F3D25B2B2B28E119BA22862FAF4E9E27FFFF77F533E81771C477CF9E59762F1E2C5E2BDF7DE4BCB02A123D25E38BE2566D1711C56AF5E4D381C66E6CC99A7DD9A9A89C5622C5FBE9CC58B171F5342549665CE3EFB6CFEFDDFFF9DCB2EBBAC47F52B3AC3B66D76ECD8C1C68D1B993E7D3A175C70414ADB3F2E7D226B2184655962FFFEFDE2A1871E122B57AEEC913FFFA986E33862E3C68D62E6CC99C7242F942449CC9831436CD8B021E5D7299148880F3EF840FCF6B7BF15C5C5C569C92C7A3C5266F8ED2A757575BCF9E69B288AC282050B183468D0D7D69F2E1E8F73F7DD77F3ECB3CF62DB369224919D9DCDFCF9F3F9F5AF7FCD94295352766D4473A9D055AB5671E4C811AEBFFE7A860E1DDAE7D7BECF0507100C0659BD7A35870E1DE2D24B2F65E2C4895FCB47AC699A3CF6D863FCF18F7F24180C3276EC58AEBEFA6AAEBFFE7A860D1B9632315896C5175F7CC1BA75EBC8CFCFE78A2BAE486B82C7E3D12F8283E445D8BA752B1F7FFC3163C78E65EEDCB9FD7611FA9386860676EDDA45281462D4A8518C1C3932A5F9F0E2F1386BD7AE65CF9E3DCC9831833973E6F4DD7CAD03FA4D70901CE60F1F3ECCCA952B8946A3DC78E38D0C1C38B04FB36E9EAA0821686C6CE4B5D75E0360C182050C1F3EBCDF9F24FD2AB8161CC761D3A64DAC59B3863973E63063C!
60CFC7EFFD7766ED75B1A1A1AF8ECB3CFD8B4691373E7CE65EEDCB9FDDDA55!
63242702
D545555F1EEBBEF128944983973263367CE3C3DDA7503DBB6D9BB772FEBD6ADC3ED7673D14517B5CB6FD2DF6494E020E9EAB26FDF3E366CD880AEEB5C7DF5D50C193224A32E5AA62184E0E8D1A3AC5AB58ADADA5A2EBEF862C68F1F9F9173E28C131C242F602C1663F3E6CD6CDCB8912953A63067CE1CF2F2F2FA75C29B69589645201060DBB66D6CDCB8913973E670CE39E7B40B5CC9243252706D696C6C6CB51D8D1B378EC99327337CF8F094571A3C99701C878A8A0A3EFFFC734A4A4A183A7428975F7EF949113997F18283E4053E74E8105BB76EE5C89123783C1E2EB9E412860F1FFEB59AE3398E436565251B366C201C0E3378F060264C98C09831634E9AEB705208AE05D334A9ADADA5B4B494F7DF7F1FBFDFCFE5975FCEA851A35055F5949CE789E6A8F98A8A0ADE79E71D8E1E3DCA9C397338F3CC33F1FBFD27DD14E3A4125C5B4CD3A4B8B898F7DF7F1F4551983973268585850C1C38109FCF77528B4F0841341AA5BABA9A83070FB27DFB769A9A9A58B0600153A64C39A90BA59CB4826BC1711CCACBCBD9B061039148048FC783DFEF67E2C4898C1831A27D81D80CC6344D2A2A2AD8BB772FF5F5F5442211DC6E373367CE64ECD8B127DD68D61127BDE05AB06D9BC6C646AAAAAA387CF830252525343636525858C8ECD9B333567C89448243870EB163C70EF6EDDB!
4756561663C68C61E8D0A1141414909393D3EFBB03A9E494115C5B5A12B2343636B277EF5EB66EDD4A6D6D2D0505054C9F3E9D828202BC5E2F2E970BC330D0342DAD936EC7715AA3D3239108E17098AAAA2A8A8B8B292D2D25373797E9D3A73379F264727373F1783CA794C8DA724A0AAE23229108E5E5E57CFAE9A7D4D4D4E0380E3E9F8F810307E2F57AF17ABD783C9ED6FFF77ABD1886D19A734396E5D6BC1C2D8836895F5AD26199A649381C26140A110E878946A384422142A1100D0D0D04020184100C1E3C982953A63061C2043C1E4F3F5E99BEE56B23B8B6B4AD615A5D5D4D5D5D1D914804CBB29024A9F5FF0DC3209148609A26922461DBF631826B490E03A0EB3A8661B4E6D46899D82B8A82DBED262F2F8FBCBC3C468D1AD55A6BF5EBC8D752701D615916F1781CD3348946A3C4E37184105896D59AC8EFAB7953DA66245255B57552AFEB3A1E8F074DD3D075FD6B6DA4FE2AFF3F26DC2702F45BFEEF0000000049454E44AE426082');
+
+insert into MemberImage (imageid, member_id, contentType, data) values (-4, -4,
'image/jpeg',
'FFD8FFE000104A46494600010200006400640000FFEC00114475636B79000100040000003C0000FFEE000E41646F62650064C000000001FFDB0084000604040405040605050609060506090B080606080B0C0A0A0B0A0A0C100C0C0C0C0C0C100C0E0F100F0E0C1313141413131C1B1B1B1C1F1F1F1F1F1F1F1F1F1F010707070D0C0D181010181A1511151A1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1FFFC000110800E100AA03011100021101031101FFC400A20000010403010000000000000000000000040203050600010708010002030101000000000000000000000001020003040506100001030204030603050408040700000001110203000421311205415106617181223213A1420791B1522314C1E16215F0D1F1723353541692B24363A2C27324342508110002020104010402020104030000000000011102032131120441516113052232718114F091A1B1C14215FFDA000C03010002110311003F00AFBA09BDC735A10E2A072AE3B63D504C36A740F77881A7B2AAB263A0E82231C601C547C053A7023A4B09B72015540720578D24B2CE210D7443E4F3624!
20CE9250CD3162D868D65138B46390A590C1B6C51A82A8BC0E6283B31D2D02D8C6BB308DE3DBCA96488362B469B70C421CC76A1E35629E26549FCADFAA23B72DFF61D9C87EE97B05B1CC31CF05E7B9815DF0A7C7CADB17BA15F93EB0F464523BDB74D3054D4D8901EED65B855F5C171A14075AFD5FE8BB8736274F25B3CA00668DCD18F6856D0B60B92B5459F6FDDB6BDC5865B2B98EE5A062E8DC1C9DE86A8D56FA11A7E09781CDD383711C473F1A4E7007561243DCDC40C715A5AD9D9C20B4902E970CD1390141B63A43DA096B4EA538D339D03082228DDA0871C03704F1A64236151315A4262067DE94FF24282B6876384FB04A2A0C56A4CA07923EE9AE6CA153ECAAEADC8FE06D1DD992D5FF232A839300D8A576905EDD44EACF553365554DA1D709257374E9D0062076525996D11210DB3BDB0E2854263E355CEA5A87E1B651E9E0B8F134772486DBDAA1248E0695C92479E1A1A11840429CB2A46DAD8285C16D1A9F20F37A41F89AA9B65892098AD18D6E1896E20E74F54E00E19CCBEA0FD519E39A7D8FA7246B6E89D3777C083A08285B1F027B7856EC385B537FD4A1538D9478473AB5DADC6C2FEF6E64335D4A51B24A55CE73B173B1ABAF926D5AAD11A2AA2AD9057360D6B89320692001892A95B6B7667B56014C9730B8398F28310D7623E34D0988ACD6C4858F515D!
5A4CCB9B395F637CC2A2589C51C7B41FB8D556C53BEA8B96595E8CEE5F4AFE!
AC43BECC
CD9B790D837700182650D8E74E4383FB38D72FB3D574FCABAD7FE87ADF97F275D30BA4607808A15573C38566AEA2BD019D1863C3199FCC3B70A9103C855BC6C400F95DCAAC4A6046C3A3862F60348049287B3C692F100523ADB5746DC078F68E155A9416CD96398C2C40350CA8CB0004F103AC9C7420A6A6E160BA8F319D68E4271396D9185F139AE4182F691E34D6B2298D43A38985ED6008D0303C39E355EEC64E07E36481C801734E49950ADD263B5215135EE2010840C0760AA9E4D4B55740F861F28247980F81CA9DDA4513EDFB9806E38A1196548EDA0CAA1B6B666418A69181E34B519B82B3F537AA0EC3B03E0B3C374BF22DED1AD451AB073BC1BF1AD98A89B8F0B51137B90FF004F3E876D735BB2EF758E4BAB87B75C9A9DA2305D8941EA7779ACF9BEC2F66D57446CAF5EB58E5AB3A933E9B74FC56C6D99610FB2D0123737501DB8F1AC4EF6999D4B559156EA1FA43D333C1283B6C20A287B3531C08E4946BDCC957A3637C34B2D8E05D63D0726CF24AE8838C2094692A47DB8D773A9DFF916BB9CFCFD6E1B14991A59206B82E9C070AE92664685C7753C32C7730C8639A121D0C8D28E639B8820F654693D09C8F59FD23EB61D61D350BAE1DA772B21EC5EB78170183C01F8F3AE067C2F1DDD56C68E5C9497C75BC6A0E90383C8CD699A50226C75B665A84A15C1470F!
B291CD46DC263B66B029C790AA6CC23CE8E4907A480DF4A1E34D122C4089E2974EA3820E1D94F6A0A9919305D64E0A8838914956B52C6817433E2B9D37221CD1967098E4735C010306BBB08C939D58D1947ACD8DD7ED1975BDC3594C139E694B3B8E97A9391DBC4E2D008408A3BBBA8F1D075B84456189C4008BCB0E554BAB2C91418D6E96F61FB530A1508F680C800D28434E230E54CE00A4321FD3C168E9EE3F2A389A4B9D9655A31568F7D0AAFCFC1C0B7EDC64DFBEB0DA032FBB6768161898708D1703C0B9733575A175ECD2893462ABF9123D23D3D20836F8DA467861C502D70E8DA3A592B24A45744E6A1C11073E741DB42BE001BA5D3035DE5D4E23E26B3DA59752A725EB8D89D7CD94862AA94AB7AB91D2C1CD4E4A0E0DD45B24DB65D11731F95EBA1BCEBD5F5F32BAD0E365C6EAF52BCE6B434F0E43F656B3333A3FD05EAA3B2F5BB6DE490B6D37289D048CE1EE3417467EF1E3593BB8E693E85989F83D370EFB14D219490D883C82DC2B909F16D16D75524958EE7EFC803406B5874D23B38416D6C483AE5AF6B40211C5C1BDBA4D2D85ADD30BB572354629EA078D4560D9044A1AF806001031F1C6ACB6494257721370631A51BE8E27C2AA45A05AA2E63D3A72AB2453CFD2757BE09FF4E0B4991F8C8714040C8F1435B3836A4CCB78F03DB7EF925BEE6C96477B913B!
53305C8F3AA7FE0BF8A82E567D496C185B127B8306B9C42270C41AAAD763D6!
88376EEA
78BDFD13488D94A3DCE20B580E2AB4AAADA15B49933657165B8E93048091800B8E02AC55E3BEE45795289686D6179607798A129C3214AC3E4AF7D4EDC7F9774E4AC8641EE3C39F180517437501F691498E5D92F05B43CFFF0049AE1971D7A0488F73EDCE95CF5282EAEA7D8D630FF64EA39CBFD1E9CB3DE76DB57C50BEE4071006971189AE03BFB1D3746C979B71B48207DC4CE6B5B1824BB82551280A8CAC3FAFB62B891F199018C601C5C065478DBCA1925EA466E9D55D3E617384D1BC3BD3E6198A2B1B7E193925E4E1DF552FA2B89A39206F931470E64F0AEEFD5D1AD19CFEDDA4E6AE7BDD22B8AAE04D76A0E7324FA727367D45B65CAA88AE61712A986B43F7D57954D5AF625773D0761BE996E6660796445C40989006AC8A780AE2DB1962BAF52DBB66EAFB68436195B27B89A5EAB81E341D3692BC96F42746EE45D5A0047B685E9C7482065553509898ADA96CB1BE13C4D7C6DF2BC38E938A0ACBCB5846B6B490F86312B482720415E7CA9B1EBB81A82037D33B4BDAC180441DA952A9C8EECA0AF25E7C12B515724796208E69431E5E4BB06907995CBC2BA966919E4B15A5D1129716E98E3046818941C178565BD4B6B71D8AFAE2699AE62B400480320780E555DAB08B6AC441BB4F248E609CB99AFF0030351143B2CB1CA9B871424A6F52E9D3579FFDD6DB1413699086C!
B339CED23DB6FAC788C2A89896D0B6DE117FB8EB0D9F6DB9B7B79DE7549AB5BB30D5C1A1DC94E5431C38D07B268E79F59B722ED9ED6EA39411212D6441092C78043978227C6ADEAD66D01AEC721E86DAF72DDFAAA6836C9BF4976C8247B676025087008839AA5743B791531276532CB30D1DAEE34D0EAD75D23D510BF6C8E2DC2D1E5C12F2292DDEE95CF5F96400BF2CC970C6B85FE463FCA6AFDB53A5F1DB4D57B973EB0B6BE8BA1A187DC26E64708647620E9040C7B74D62C2FF397B17647F8B4884B0E899EDFA44B36CDC5FB7EE7286B9974606C814A6AD5A9AF2542E4956DBB339395D72AFA0AB17E31570CAFD8FD18BCDCF70F7F74DC652C693AE68A01009315FE11E3A6B5FF00F4F8D62B54BFB933FF00892F5642FD5AD976CDA2D596F6E069604695525305ABBEB325AF77257DBC6AB5D0E44F78D20B085398EDAF408E5362A22E696C8710D425314231A8D93C1D92D6EE391A1F1CC1640D78D20E3A829AE53D248D96EB0BFB98AD213A5BA43B0CCE0AB8E18525E0AACB50982F6E0DFBAE2393439308D5415F954D57772A094B433AC7495F437360DF386E903BC2E24615CEB522D26DADBF1271F711C6C716BD3505C69EB54846DBDCADEEF34841707100627914E4955C3E45B56A0ABFEAE4FC3F7E5CAB5C94F16799ADB748993B8C738D4C19341C4227102BB76C6FD0A!
03A1DD21F68E89525C75B435141EFAA6F8C08CB6BDBB74467B756480A3067A!
8A62ABC1
291D14C32C5631970D65AAB1CE63DC496B4AA823E63FBE8C4B1791916EF74248A48A576B602D710712175A0E588A67890512B3750C92C13CB2CAD96E25635A0855254EA45E2B54AC1C5A4B62CF93927244F5075336F76C658C8F73DD140C85870C1CD00FC2AFA608B4868F417F45AF4D87D4189AE785BB85F1877220870FBAAAFB4A72C3A7866AE969963D51EAE64ADFD3EB90832307A80C96BCDDA0EA434C89EA58E0FE590AA38297B81C8F72D1AD5039125D3D771B2CA16C6859983D99252AAA4C37520BD4FBC362B57BB521C7FAAABB291E8923CD1F5677837972D66A50154675E8BEAB0F14D9CBEEE4967376B7CA4152D38F85768E734390B91635C1D877D401D7FA66F3649365B212DC3D971ECC6D983580A1011557118572F356DC98E9D4BADBB76D7C2D6C1BB37DA386A000CF9E22AA6ECBC782BC897A8FC1B2D9CB20D1BB30170FF000C201DF9E78D2B6FD0A346CB874F7BFB6811C7771BE340A0A9FBCD67CAA7C1752D1E49BB8DF4C719D7230340E273E3599D2CF445DF2D56AD9017BD4F14D30B40F6FBA4600945EE5ABAB8EC948EAF51BF78FE319E9CC67F868CBF464E753C8B1CE1972640A1A4A63C8675E96CB432B245AE73260E6925BE944E24E754FF00244196B7F3C2D2010F6039380C0F022ABB5131AAC92926824B3F71BE56EA0109C7138D55C5A646311FB3!
A8B236800B95AEC5701881DFC69E18012E1C0C69C49CC6592765324C328AF5D1F6E77A3B1FC272C7135A56C3D7408E99DCA4B1EA7B0BD6F934CA1464007F978F7D57D8C5CF1BA96E1BF1C8AC7AC362DDBF98411DB4D23A22E620760AA422E35E372A83D04C951FA95BD7D44B7DC6D36DDBE28DF046D1FF00BD68563C1FC40E2D3D95B7A95C0D3777AFA19333BA6B8A2D1D29BE3EC761B5B4DCA66CDBA9D45C5992B9C4A01D8B59B2C727C7445D47A29DC87EB0BFB89637B41D00855E5431575D4992DA1E7FEB37BDD7A7510E3F8BB2BD3F4FF53919D9596B9ED5239615B20CD26464870EC34C2974E9A12496E1DAD803496A3BEDACB9A24162D96FFA989035C1ADCF25C57926154E9A15B610CBE95B300ED2030799A149E4532A584064E6DFBD5EC0D6C5087B812495C91304E555D948AE209986F771B860F75A1A1AE52A70701CAA9D0154426F570DD66574ED639CE2AFFE107FAE9F1FA16A4447EB5DFEA5FEB5F9B3FC5DF4F03423904618F9F4BB06B15D8F1AEB37A0107999AE7797CAA73EDF0AA62030116AFB563035CED5A9C4923D44A252DA5910E7EA491A6360D23966BDF43884545712900B016C993814209C7339E551C018B8ED1D2BFCCE0D6FCC06341DE10208BDEACDB1CC42A9635A5483E9CFECC6ACC57943A5A11173339EF561C18819CF0AB921AD693BFF00D32E!
AFD97A8F6FB7B0DC813750E96CD187163896FCC0B4829870AF2DDFEADB15A5!
7EACED75
B3AC958F28B77516C53CD1B62B7DB2E66B768564CCB9900009CC8249AC58EF0E67FE0D16D54411FB16DD65B34CE93F4A45D3824933DEE794CC05792829F26476DD894AAA903D69D53017398D21DCEB475B0B6E4A7365F0717EA29FDCB97B9C54925078D7A3C0A141CACAE4862E01A899FF00402AF2A371005D8D46C52F1D1716A8E623800E2D2172E40679D62ECDDC85D4B8D931D3B8FE593234957105B8AAF7567B5DA82BB2089A110A17B5CE23038AF6E34AAE98AEAD0FDADEBA36B70738044072514E2B1736FD78E698E38C800A1257051C05075435568097114B70E2F90620292404C396094554740BA3FEF0CD736E7F67C2A68349C85A252F6FB7894248AEB3150FD8CCE1388DE400DC88C4F60C6ABB574085161326A0E0002411DB4A822A395EBA47988208ED23FB2A344256DAE6E03581A5855E4EA70ECC71ECAA9D502099DBEDEEEE5CD64535BEBC4B49683DF98AA2D082911DD6D04F6AE83DC73099E2D25CC6800169C7E069FAF0CB3C14C79858ED058A87170E2B8D6D4085B08DBF73BCDBAFE3BDB290C37313B531CD39767750C98D593ABD5029775728EF5B37FF00A26D5FB2B6DAF627C77AD6064A5A0693866DEFAF3D97E9EEADF8FEA7569DEAB5AAD4ADEFBF54A4BC5FD2911467D45C417273ABB17D6C7EDA95E4ED4EC526F7A89D3B8E826599E712720B5D0A75A!
17B195E421EE619A47895CAE7BB8638569AC2454EAF706D0633E6C4F114C2334C70F7142F2A3042DBD17B87B17843A4D2AC1A5ABF30380FB2B3E7C72A4325FECF7A6C772E6C6CD48D009241524E6085AC97C52B52736876F6F2025AE7B092D524B54853DFC692B44B611B9188B758A295CE631C5BAD1AA72030539D589303A263526FBAA60448F2C27D2110E1C53850756C3C505B7F4772C33492BE28DCC01A70C0AE599C2A6A80A013F451FF00AC67E2CBE4FC5951E4FD0128E3E6490073587D410F34AEB68146A17E3188D9AE4F1A56127ACA374AE2D6C424705F3383AAAB34884CD96D8F0318E3073D40177EC4ACF6BA1C9AB3B56471B5D23B5318F1E46B1A317145FE82974DC56C9689CD6822360610A065A42760154B4C744075943FAADADDA9C0490B4BE3279804B82A7114D82D1619EC7320D0584EA476481723C6BA620D69F39C88EDA22B277A1ACECEF3AA6CACAEDA2486E4BA2D2725734E9F8D66EDB75C6DADD16E08E6A4BC750FD2AFD2977E9A319E08A895CEC3F63E2C68C9D6F4226CBA2EE03835EC08DF510B9FEFABF276D4094C6C9F9BA31B159174518D4462482B95615DDD752FF84E6FB8D93A0B9958E099E3F72D76B1E49464BD6182DBC25D20D2311991D9565AC569129B1CF6D6FB8344AD05C41D1A828D4460B49965D7401D3B6AB36DC6960BB86068030!
D4D54CFCC8714AE6E4BC7A8CA92483B6C9666961BC865B76128E01C3123040!
B489BDFC
91D503FFB5A68A132CE118E70687AE927562884AA61562CDE01C584DA742CEA0BA76B6338807CADC94AAD67BF6D2DB52EAE06C1F71E9A16A0B2DEEE39A4209723F5A782609529D9E5AB501B61821FF96C9CFE4FC5FBAB57C88CFC11CE044085766BD87015D4656196969138F958EC02E08AB55D98791356D058B6190B1AE6608E94B9497386000ECACB7BB981902BAE2E0B9D1C321F6CBD8C6C851A55710107754D376116EEA4B9DBE69ACEE982E59839B30015A1A8B80CD69E98D594AD00C7D9D5F099DCC6C3AA29012C7905A03F13E3F0A1F038D49242EE7D4F73776F300D6C64C5ECC8C52410BEA00F1AB2B821924AF6B9312B81C0FDFF00B2B40659BB7B6B8B995B142C7492BCA358C0A49EC028369297A2024DEC757FA75F48F7696EA2DCEE888E4808922881C438150A79D71BB7F6558E35D4DD83AAE659DA24DA9D25B24ED05C4004D705D949D255D3506B6E928FDC56B15BC0220CE85B2BF502A209BDE9E5B77B4346B6A16A0E098E755BB6A58AA706EBFD89F65BBCBE4FCA793A9322ED4428EFAF49F5F9B9523CA39BD9C70C84B5DB1909B7B80D2E8DCE7B508450D6A155AD56C9328A1562195EB88C8B87398A0B5C749EECAB6D7633D96A4EECEE95FF009C5924ACC753587118E2B546648105A761FE731CD2CF61692B9C037D88DF8863D53510ECC76561C8EBE58C93!
82776E83AF1DBDB679D8F96118B637248C07B11508ACF97261F8E0B31D6DC8BFEF538B5B08EE2EA3602D00BA31A439CF2110373217B2B93D6A6B0B63A393224B5DCAEB6589D0DD92F0DB82D01D3940E01C8435B96095BA1CA8D8E7DAED952D76FC9DFE2267FF008BBEBA5F9141CDCEA81C547B8C7121BCFF007D74E6457535B6FBD2CE741734A804F04E2B4B93441489C91F2CECD0D934C61DA002814F04F1ACA924CB1D4321DA85BD9937128733DC00BD9FC38E1CF13555B34DB45A8CAA566F16E374D27CCC6F9107215BA9A54AAC0B6BAA2DC882090D2480EE280E9A67AD4080EE7DC12ABFE65345120DDB324909631A5C48E1C8516E06A9E85FA41F4E2CA1DA62DC6E226BAEA70AE73DBE66B485D2172AF2FF0063DDB5EEEABF5475FAF8156B31AB3B2596C76F6F0B1B0B3408C83A42809E15CD56D0BC224DBDACC0F986AC06155B1EAC7E2B46889DE4500714147C01B22B736696BB04E4570AA9DE07A9C0FEA3DA5CCDBECC1CE26189BADA303ABCC4AB5792015DDFAEBA54F732766ADB2AFBADDC106D76BA59A4064B8AAE2E3A4D7431636EEFFA31E56924549A44B117BB1271032C4E02BA4F4665DC22DA7B8B0B912025A000A01213FAF0342E959411A83A5F45756DEB6F220E1EEDB39CCF77005DA75050A0615C7ED60490F4B6BEC75A9770B7B9639B6D7115BBD7C8D538!
F145F1AE3BA7A9B1644968445DED73CC5B23E581EF8C6821EF6AA9C70526A5!
72C38D40
EBC882B8E9D92E9D387CAD8A13EB23104AA9C5AB8A0AD74ECF18D3528789B213F94ED3FEA63FF2FE7CFF0017A72ADDF358A38A393191BAA36B8973BE61CB1E15D975DCAE4236EBAB766EFA5E8C81F208DFC835F82F8675564AB74F71EAF52E76BB159DD5B996D9D1CCC85E59EE01E6D40A9295CCBF61D5C3D25172A489DD367F7219C471B98D6BFDCD01472E66A62CDAA058AE7F2F6CB75A7CAD001798C7038E7C56B77C908A7722F7275BD9DCBE428F94101A072AB71FE488F420E591D2CA5EECCE4D157A4297EE91E8A9E56C172F617EB734E8009D4490130CD38D733B5DB4A6A8DFD6EBCEA7AAFA6B6B6DA6DF144E6000040113135E59B9674D93CD6688F482002386345B110C98D00C0A877A8D240FC87E704464B715E1C6A37A016E57B77964F61E13D3C5292C9416A3CFFD641F26E7713CB316884C8C6B00CB5711DAA31AEEF49A55492DCC79F729FBB58DEDF5BDBD8D8C6E964697351A3003045AE9E3C95A376B6873F226D4224763E81BB85C25BB8659401AB4868634705D7220F85559BBE9A8AB1F1F5DA72D0F6FDD3EE6EB2F8AD6132056B4CA4B803866142D1C5D8DB7264A47A152B1DCEF366BD77A6560F2B846E51A49CC11FB6B7DE8B254C930CE8DD35D67B1CB0C4F7C4657460B5CDF2024B954BC3B8A658D71B3F52C9EA68A59345DAC773E98DD2D191FB92305A!
BF5B6278634EAE24E8D6484C33AC36C56A3FE4BF4B224A3774EDEB9ED17CED709D3A1A74680E2B96211DCE9785AABF90B556E644FFB67A6FF00CC19A7A87AF965F0A1F2E4F51BE0A1E7074113E446E2D0A14E054D7AD76691CC81A36914539683ADE4AEAE02A2B3820558DFEEB6339920B97C2D3E6D0D2A172F495155DE94BAD548CA517276F4C9E288CCD22E240DF70314E828A540E1CEB99F04371B17CA06EA282DF6CDB5FBA3246B8CA00893071738603C29BAD777B707E05BD78A939A4D3493CA6490AB9C549AECA508CD23FB7411CF7D135EED2C5571A5C8E10D452CF5B7D3DD86C8EDD6B3C0D6BA26B07E77CC469C004C109C6BC467C8DDDCEF27A0AA4AAA0E8D1B044D0D7221F483884E1540B322A276B2002BCA993D42F40C16A5CD040418E1DB4F1256F2408F6092E1A502042292C86E455BA9C5C3229047860E201C979D5362FC6CE1DBDECED9EF1CC983EE2591E52207152702E4F4D76B06575AA8D119334361B6BFC9F61607DFEE3059C6D473A0B71AA73CDA5E7F652BE795FE356FDDEC2A8A2D5C115BAFD59D8A2698F6DDBF5F1371704BDCEE030E1E02B562FAABFF00ECCAAFDC5E114BDE3EA6EF57FE51296460235B146C8C0E78A126BA78FEBE95F064BF61B2A1757935C48E92491CF7BB17179524D6EAD52508CEDC88B699D148D7B09D43D4DE04546A51138!
2E169B839D6B04D149EDE9040F6F369CCEA031AC2F1EAD346BAB4D492FB1EF!
0C8AE583
706CF716C1C1DAAD5ED0ECFE6690A40AA72E195A68C097AEA5D7FDC5D27FEAA5F4EBC8E7F872F57F0D73FFC7C9E85BF8FA9C7DB6EFB891AD89C039DC33C0678E55E82CF898EB5925ACF62B58DC1F2CA9163E6014B9C31214D64BE77E16A5F5C3EE1B0DA6D06E5F23A27981A7417870C48C780AA9DAF1BEA1745BF80D9B75E9BDBED5C63B3D7A7173A57B8B53220B422E354AC596EE1B272A2F050FA87A9AF77B95A66FCBB78B08606E000E6799AEA60EBD712D37665C991D88868CCAE590ABE4426B60B22E9DA5ED3A737103878D519AF087A1D47A3FEA16EBD3F10B7B49049087796DE5C011C74BB31F6571BB3D2AE473B337E2ECBAA83A5C3F5B3689E18EDEF6292CE73A55C40731A0E7E66AFC45736DD0BEEB534ACF52F3B1F5874A5CDB87C1B9C05E9882F6F7F13D9543C56AEE98EDF2D89D8779B37B563B88DCD39BDAE18E34CDA48ADD183EE9BFD8DA46E9659D8C89A3CCED42AB7AB843D6B0722EB5FA9ED96E0DBDA23618F57E71200CB324E5977D6AC3D2E5AB2BC9D84B638B6FBD71B8497328B3944511712656F13C4EAF9ABBD83A344972460BE76CAA4FB8493C8E7C84CF2953A9C4A0ED45ADEA892F4450EED8CB8DFCAC63DC488DC48680348C11500A74EAB604B069637B0F989CCA7DB4C010002799E350122DA02828A2A0649CE9BBA860DC1B14C7F26E3C99A238F!
A4F81AA7B159AE9E0BB05D2B6BE4B8CDB6597B06E4BDAD7C650381D21414C08C2B9F4CAE60DD931289905FD63FF1BFD299B73E7FBEADE08A39155DB3708D8487791EC5D298E75B32E36CCD8AF0586CE582E21F6A595B23479831CAD2D279118D61C94757291AEB54C91B6B6DBD8C735F216C67CDA55BA7578E359ED6BBD96A3708457FAD2DF6FB7B381B6770D90CAE2648DA1A30057304F13CAB6751DDD9F25066CF54B62A39F70ADF065318D570079802A3412C505D7B2F6C4D780D4D650A2346609EDACB6ACEA3A622CF746B04B33CBBFECB465A752E23B4F2A96C7E00AC58768B86C90092471639DAA473890981C1472422B365AEB05B4B068BD57173A3610C3E5C31D2B8E3F7D56E8595C827FDC6F823D6C91F190558237BB1C4B7811CAA7F8D2F619E683775D5570E85A66964B86306A10B9EEF39191249F2357C6857ABAE88AED9ECCA85F751CF24CE9646B25982885A71862C5706FCC7FBD5BA9812508A39B215F3CF3C85D238B9CE2A57B79568492D852436DB3067635E892391C4E00019A9A4BEC14197727BB23DD18FC885238B82AB94BBC696B485EE1059362DD5F07EA658BD984A963E5F2EA0BF2B7D471ECA2F2D538F24E2C126DBA7863D4E424A9D23340817E34EAD22C0C6870685E38534110F445ED208C08CBBC6346085AADEDEE65B364AD91C629F4B9C4120!
79B044F49C6B13B2568362535FE4DFF2DB9FF33F83D3C39E7539A27C5EE54A!
D04D2DD8
6C6D5241C0F656BB5A1192889CB7B0DCD0BC46E2C42A3251C10D67B5EBEA6AAD6C1315B5E39CE7CB1BFC9896807E148ED55B16437B90BBCDCC73B981AD7073090E242029C8569C55832E5BC9187E356949919D2F072434083D24C4EB70F539078018D480985E0358D45207DF8D04804BD9EEADB73146402D4FCDED5E18F7D537C523266EE77995F116840D40547300938F6935298920BB683115C96303E51EE4A42C4D763A5C712E4F1CA8B40905BDBA9E5D2D73D583CDA1715C95DDB4E940B20472A720EC43CDFF00350641F6DD48E25AD5571D2D1D940258365B770BA6B031AEF6CB487BC121AE6E3A9389ACD96FF88F4AEA4B6EAF96763DF24A224D3F9AF5739C49C533FB05518DC3D8B1A2B5BADDB1971246D90CAFC3CE4052531AD98D382BBB22175104FF00655E5723FE7665E06A0C4F74F751DEDADB1B516CCB989875623204AA7DB8D64CF82B673305F8B2B4A224B0FF003BBCFF0040DFC7EA6FFC39566F82BEA5FF0027B22B3B16DD1C2B2DCB11D21D2D6BB837F7D69CB7F08C74459E1165A58DD24054C093592D25E920C7496F6D01597DB405E5EAA8D009C4775550DB1E124730BFB975CDCBE4C9A490C1FC2B8576695850626E4182262B4C030D021AA841449271E75086F520278AD020B8882FD4E1AB4E4399A8C83F24C185CD67F8CEC1F21E0B986FF5D2F120210!
87B69C8677F85421B6AA28F51C3C28103F6C88FEA1AF4572F95789EEECA5B6C144E6D97315AC8F3211A006928712E3CF9567C946F62EAB8646EEBBBCAF26088A86A832F61390ABA9892D44B5C8700AF69E35688C5818273A800DF55B84CF327BB0A1E460AE9D9BD9DC5AD71004C0B5CE7211CC7C4555994D47C6F52DE967FE633D3CC67CEB0CBF43542F5284FBBBC0E4F75C10E15D4E28E7A63CCBFBD6798CEED6AA0838F852BA21B9306BCDD2F27C2595C41188255539D1AD12D88ECD82711CA9802F4AB41425C3BEA4906CAD021A25476D42181505420AC7C2A105B792A27F45A8430E4B92F13C6A106C92E72D4921BC50F65401B1C39F1A9210B8259238CBD8ED2E42D51F8539D2B5244352CAF28095A6820819E38F65164358870298D420B0988544C6800758E21831F29CEA04D3103827851204EA93F11CB9F0A0090590A3CF2E34C0434F95CEC014032A01108BC68221BD241C4A0E144210D1186AB6405C3821A564077B4AAA22E294402401C38D42183E1C56A10D845A041D731A1AA4E7891C4D420D9049E6788FD95086801F6E7520861CD3335082800072A0417AC801A326D12093A720B4486621C53234584D60B8F0FEDA04159271071FDD50903A1E71C30772A843011C73CC25400423B9FCBF0E550920B215791E0B4C040EE2714FB695B09A8E394BC0662ECFF00B!
692423E2D6F1E5431C41C751C1BFF001141479A0C336FB79A325462332311F!
68A3320D
46B0F1A9004250A1A2886DBF1182514436D2015E35086DDA8E2733408682A119AD09018011DA385490984918F8E352486054A0436868C90C4C9313C289051CF1CE8B09B710EE1DE6A119AD2003CE88B23802341FB054218CCCF1EDA0409D5DA725A80059000F3877D1221AD4D071C071A0C21568E71974C4CD4875C85147FC3C52ABB2459525EE2C9F245FCCB7694C16CE21B6F6C0AC8F41820CD399E1545726BC68A596BAF9B18DB594DB16C2E6C5EF009134005063A9EE793A476E14DC94EBE05E246DDECB730BE26B4FBD24C0BE38DAD20E8FC6414469E04A53ACA9CFB0AE9049D8FD3BEB4BE87DE836C9042710F90B6307B46B2D26A8C9F61829A3B16D3A992DB202DC7A4FA8B6C5379612B18337B51ED1E2D5AB3176F164FD6C84C9D7BD37444F6F235A194185D9F6D290D93C7202A10D0E62A10CA8414788E5C2890CCC2E544862D421B0899634584C047251CA8118B6A28A828E1EDC80F2A5408908BF7D4204237E14440299B22F01DD4BA8E98D08F98A90192476B9E3858F748518D20BF4FA88CF48EF38525EA3D58536E62668BDDC1AEBA46E9B780B8E9D49A8A9CC35A5C32A475F15D3D474E3566D97CF303A4912799CF6C936B04B01714642D6E59297767979D454D74D17FAD41C8B9FD3A8DB79B809EF83667CBAEEAE1EF424E93EDC4CFEE82094AE67D93E358AE91!
A7FE59B3A554ED2FF93B1B77180C443882AA82BCD3A1DB4C0EE20826C74844C69EAE192132ABBBF4174EEE72BA4B8B40C91C71961FCB763C7CB9F8D6DC3DFCB8D68CCB93A78EDAB450FAAFE9749B6C2FBADAEE1D711302BA0900F700FE12DC0D75BA9F6AAEE2EA19CEEC7D7F15357250DF0CB13CB256398FFC2F041FB0D75EAD339CD1A202009C29990C38341E278500092B9A5020A04E7F6D421B1CF8D1443028FD8B4584C0B854900B6A2F6F0A841C18355541A90493005C53BEA007BC7876E550120F2E9D4E3C568910D102A48C688E1C2A105CB2BA4D00E0D634353B29521A4599DC61313423756BF11837EC5A3C7C839160E97EA0FE597C54AB658F48C72F3129F1AC9DAEB7C953460CBC597AB2EB56CF298C151FB6B937E8C23A35ED496BDBB766C910249C7EC15CDBE1866DA649249B344E6024A267DAB59DD59736844B1D9E80E90831E67BBC6954CC20E91A91BBA747ECDBEDBBBF2A290341F6DA70209FC0E18B7EEAD183B97C4F728CBD6A644717EA3E98976CBF96DA186E0B987D0E66A4072F3373EFAF53D7ED2C94566D1C1CFD7E0E3523AD763DD6F247B2DED9EE31E326A1A34AE0A75255B7CD4AEECA6B8ECF646AE765DCED87E7DBB9AC19BC239A139B9A48146B9696D986D8ECBC055974E99A0F78DC35AD43835A5E70E602525F3F17101AE295B893B0C84AC3!
3C537F003A1E9FDD934AF8532CDEAA09F1015C5A4D01D32B480E382820E1D8!
6ADE49B1
1D6061BC8E2B4C28EC7187B88E409A9001C0D4CF8542183497765400E63CB8278510034CF0490CC71C395090A186B082A4D081856094C43498F65421B048068A232636BE96DCEFDBEEA36DA0C3F3A656AFF75BEA35972F6AB4D377EC5D4C36B6A5B2C7A19D65622F992BA79C62D72E96F7068E7DB5CEBFD872B716A11AEBD675524AEDBBE8468C0260E6E00839255193AE5F8F2C13D6FBAFBA34104F68E1589E1835D72C8A6EEF6734C76D9C963DE0E0EC096F6507D7B2FCD13E5ABFC5959DD65EA9E90BB75DD94A6F76594EA2CC498BB09E1DF5BB0AC3D9AF1B2E390CB9164C0E6BAD045DF5859EFD6F1BDA0C17D1E1A8E0E6AE7DED3469D2B6171BD467D8AE55E8C897DF6E36C43DB289258BE5940704CFCAE3E6683D86B4FC75B78D199ADCAA0277B9E695F76D48A4384D1B700072231D4D3F0AB96049415739D4664BB30DC367F6C18DC543E21A1CD778203FB69D525401B8D46EFEF2D2F22F7632B37FD461684714CF0A7C78ED571E01669AD3722E61ADA4213C813F72D696B529680D08726699D12B62DA482A33A828B088A9DD44869B9E5DC2A018FA8EDCAA02061EC0D2951050CBCB5A4A9C790A0D84D0734E00F70A813447C28902B6C635F7F08700E6876A735D8828171FB29327EAC7C7B973DB659F719DD2DCC863B18707118154F4B3B79F2AE7664A8A2ABF266CACB!
DCBB6CF7D6D7768EF2A5B33C90C7CF484AE3E7A3ABF7376269A29DD5168DB6B875D5AF91C71923191EDEFAEA74EFC94332E6AC3943163BEDCB22F7A077B8E666D1EA3CC55993AD59860AE67BA2C305CECDD5762D639E6DB70807E4CE3CB246FCC8EEECAC56C77EBDA56B57B9A6B6AE6AEBA58020EA6DC36E924D9B7A6B647FA1B27C9230E0BE356BEA5322593195AEC5A8F85CAD750ECE6CE46DE58BB55B1573B4E7193FF0096B6F5B3F2FC6DBFFD99F3E2E3AD7622E4DE2EA4898D7E9716E2241991C45685892654F336A18336E4AB9CCF2388E1D95646855C8261DCD8EB6314C15C41477004F1AADE3D650EB2E90C0FDD5472F9C66798AB60AD3105EE04E3876D3DE1304892ED4E5382E74A2B62C1195400B6B70CF3CAA105003505A8063DA8FC28C0A31296871E3442B6047340523C291A18C6E59771A0886D69C83D6931B799B227023ED094AD4A1AAE19356F7B71731416AC76903CA10A0E649ACF6A2AB76342B4E85C63DD62DA76E6CD2235BA036DA339903379EFE15CA781E5BC7FB9BB9F05252F76EA496EA47E2A1C4AD7570F5954C37CD244C779345217C44B49CC7035A5D5329566B61E8F74B88AE7F530B9D14EB896E47BC52BC69A87B0CB234E47EEB797DFE37A4BDE323FB6ABA6254FD46B65E5B8BB1EA09ED0BE377E6C2F6E921D8F9791E74B9302B0D8F3F1D37!
446DC3A3F7DE610913892C6F25ABABB6A5376A74D86D4804F0E34644303B85!
420A19D4
9249BC5CEE6B88A2F56413C70A5240B07143CD688205B4A0C3C2890D82350ECCE8480771E7C3E14400DF37F4E752A1421BC3B8D161343850209E54510C199A0424B6BFF00E40EE77FCB55E5D8D18F7267ACBFE9FF00E8B3EE1597A5E7F965F9CAA33856F310E0F5546146E3FF001077D40235271EFA0419E7418059CA800C3E9350860A8431D451059A66415C07754B104FCDE1411073FA7C28104B7FAA8107AAC14FFFD9');
+
+insert into MemberImage (imageid, member_id, contentType, caption, data) values (-5, -1,
'image/png', 'My sailing trip in the Mediterranean',
'89504E470D0A1A0A0000000D4948445200000190000001900803000000B761C6FE0000000467414D410000AFC837058AE90000001974455874536F6674776172650041646F626520496D616765526561647971C9653C00000300504C544517AD57F7F6C7B3C8AD153052535555F6F306AF9A84E6F1F9CDC8C2A38669ABDC85C9C3BBC5BDB4FBFBE9EDF5EB004E261D4372D9DBDCF9F577B2B2B2E9F4FE71CA70F8F386EAF5F974A1BEF8F368F9F532916942F9F359DBDDDE908E21ADA8692A62A7AFAB19D4D4D3E8F4FDC5D2A94584CA777A7B36B8650067322C2E2FAC947C29B35D68C885C1B6AADCE0E3E5EEF63378CDCCE78A265998D5E98CDDE2A284D08EA4D78098945BEBF5F6F8F545FAF6A59D9D9DF7F8F4F9F6B299B8B4E8F3FCCFCD4AEFF6E4FCF6999C7C5B8F663D5AC36EBEB3A5BBAC9C0A182A49BD674D4B2F2D69B4397CCED6DDA4CCC67AFBFCDE3275C9193A64EBD52B66643DECF5F1F0F295D2D1CDF4E753FAF6AA00301795714CF8F4953173C40DAA5498D67BFEFFD1CACA34EBEA9FE9C705F1F6DC4986C9009749EAF5FCD1DAA58BD2796699C2E1E9EEFAF49AC6E589797!
848F4E747B6A491EBF193E4EE9135311DB8E084BCC6CEE3E5A1008640E2E57D99765302050692CA53E2EBF1F2DC0283AABA02A751A78D72DEE4E8F5F19BF8F4BDE5E666538CC7F4EC62F5EC77878886DBD483B3A08C9F8061A5BFB1CFCDC8F0EE9D5B91C5001D0EECDD41FDFDBEFFFFA4F8F6BF4E4D15D7D8D8E0E6EB8D643A493822A8A8A8F3F6D40F223BF8F39BFFFE9D936D47BEBC4FEFD31C24548FC0BD71EFD005295EA1224E85EACA1C1DB063D6D662F8F6D105A852C0E287F9F9AD9B795707111CF7EE89040B11EDE75B9B9A7D4D88C8F8F3A01F497CF1DF2100A24EC4C4ACF8F4B6F9F79DF0E146BBD2718F92941B1C1DFEFC8BF8F4AE45484A2F6EBCD8DEA482CE74979EA5BDAFA08EB1B716130CDDEC8F2221161DAF586B6F733070C08C62388C63398D633A9FA7AEE4ECF3666665E3ECF3E5EFF7E9E9E9D3DCA5D3D7DA3F7FCCC0CAD297734FA5AEB5B2BBC3B7A795B9A998ECEE6EEBF4713C563193C03FF4F150128A46DBE7F03B3D3C5B5B5BF8F9D2C2C116F8F8DEF8F7B7FEFDB1F0EFA070767B717171EFCD018960375B583972502D467A4447606F0E0D0CE2E4C28FBE4FFFF79900A650000000FFFFFFE9F5FF3479CFECAEA490000024714944415478DAEC9D0B6013D799EF85553C3212C4264316A238EB5A264E4C2C9B47480209536C614C0CC54E8A49FD2!
0A5B00BD824BC4A6B5F072C521ED746214989AD14536D9C40124CED7A13DC9!
4D26C58E
042288BE5181C96F516BA7773B7EE867B976E766FB6C8AEF6CC9C33A3D7C81A492369247F5F82319291ADF39BFFFFFBCE77CE19547F825054A8600800080400012010000480400090B88FBFE403802889C6284800486C68F8450240A2CAE3CFF8F04B04804417C76338042600247640308D6F7D8BFD9F63024062C98353C7B7504C42FF7D8B63C2210120B1E2C1E1983469E1C2350B174E9AC42111230240A2C863D2C235E36E3DFBECB3B7C6AD5938C90F1100121D201C8F35E3E6DDC1316FDC1A4CC4278F009028F2B875C715B7D620DFC24400480C8078F3E088208DF8981600899240262D1C77C733C62D149308008996400ECDF30232EF10271100128B124B44204422DE9E0540A2E5584FFA007992F72C50482C52FAB33E409E5D23E25900242A0A993469CD3C1F20F30088E21432E93100122B20223904141243200B0FFA0039B81080C4B0CA12998788CD0C0148E48970F390496BBC257290EB66C13C24669E75C8338B3C796821CCD463E9595E44100FE865C50A0891C8C2430785F590831C0FE8F6C64A2284C89A63079F9C376FDE93070FAD59B85058A1FA13008981443091856BD61C3A7468CD1ABCAE0E2B86B194C863788B038949B0A6AE042208C924C46212EC3A518069FDD963B02F4B5144C4772E0290D822F1DEDBEBFB8500249A4460F7BBF290043AB10340!
6285C4CFD700909810F1FF25004461014000080400012010000480400010000201400008040081002000040280001008000240209401E41F860660741402E4A37FF9E8A3DF0D0F3F00A3A30C209F0E7F35CC46FDF760781401E4A161120FE5C1F82800C8A7C34280692901C8432E20605A0A00E22610645A5069C51C0827907A302DA500C102F90A4C4B294038813CF49520138995166D30C05846020816C8A71C90BF936C5AF4405A79662B03A3293F102C9091BF617FFBFB87249A16D35A54A7AF48CEA46038E506420442807CAF5E4AA565A05A9A4CBDBDBDD6140B10911B0811080132F26F814D8BA68CB9CD56C4A3D76E6DB640952C2F105E203C90BC80A665A8D134B2F2E0A2AF500BCD165981F002E1818C7C6FF49E164DA5DFA8E87585BD4EDB40C398CA06441088006474D3A2FB0579D8ED84880E88C8074410880BC8C028A6C59873EBECC4AC6C2936FC599DEE2A109109884B20231C867F603FF35B69D1032D4D7A220F7D8E26BD68D04E34D20FA32A0F109740DC80F8332D64572956CCC3D4AC6BA50C0DBA3A42440BB5962C40DC04E20E44BCD232D4F07665B735B550B4C3E1E8D7122285301F9105889B40DC8188565A8C79B1AD8F1BFDBE425D0DE3E0822244FA5232A18B123E107781780011312D26BD895457FAC6F201DA4162801031E518A34384661843A2!
7535556202F104E25D69D15479A395D8D58D74C6E18A01DD20C674A3260AA5!
96E16A9A
46A7D5A4F51B12118887403090EF913F78555A861A5D21E1D1A96B3038DCA3BFC8C669A44217F934421917D799FAACA6CEC546260181780864E477EC9F7EC3FFC9C3B418E32652ED5A532C2EBBC241B7E227ED292D111E249A6AC93191A23B398D4938209E02F106E256693199641C7A4DC92D94C33B18630EA71E53536B444DCBD06F49117A68FA64A321D180780AC41B88ABD2A2321BFBC828DC34330EDF6032B9DEAFBD421B49D3625A733BFB5C2D34DBE2C4690FA8C404E20384372D269D4FE775DEE9830F4AC7B51BFB1A8D911B23649B36BB7B0FAD2E71A63E2A3181F8022195D66F9271FEB0365A285A94074A234D1C337DE4F23A93467E8C5E7D0A6E17F4E598E94402E22D105F20A4D2FA1B3C10FA4D46CAE12F9069B197ADBDD118311E7C1A4355770BB6509B964A2420DE02C140FED11D0831AD37FE9D4B1F350687FFC8CBD563890C444A1F266C549DB9AD0C63E924124920203E0219F95B5F20786E32FC1F6C79651E8D878336A6B003666D4E8F44EDC3A427637D98523457916DE69DE7F05758E2BBF4A50DB40B888F4044818C70403EF97753630BE31835281D3746A6C51168C433469E474E26679B741AE790D64DF1DCF5A7078C9969793401E22B1071206F60D34A29A746E7E1A0CD8DDC9815A6C92E11838B471AB92CF2167379BD392D5ED23ADB81F3FC599!
99ADC4E7D5D510D8D84A21213883890914FB84AEBEE013A001007A3B5E12C22B78D50028F649E878329E71A687AAD214EC490AED16AD2F3DC9030E69BACA5988AFA078C16959840FC00C1A6F5D0878E80D190CCD9487283CC97568B2F0F87A32687ABEA3635C4058F7E5DA1C96A2A3C6F16AE1F839934A32AB4B9297A959840FC01C1A6755760208C568F6D445E7DF0ED2B53B2D12D8D313AEED166633C0019C0F366BB7E93D05BBA5A44F623D807F5F65E95984046BEC63EF6BF7C80E4E0E9E1F70313492BE4BEAB464E1B11DA68D626771E0EBAA50E7B96F2EB2C4383B693EC0BD11791250AA6BCD0EEB6954A2526107F40CCBFE1E8BDF2A154CF2A9271BA4665360AFAF02CBB5BB986665F72ABD27930C6F383C2C8DB08919A266BAF3B103181F803F2A791BB249A1695CB7D979C1AF9DAEDE5645385A75FE16FC691B269143E5B4753289BDBD063228CA6C2AD294780780B0403D937E21B1FBE22CDB40C163DFB1DEA5A64AA45E9AB5ABC83B857EF9ECF8967710619C1668DCC535ABB0977AA2BCE1B29CA988397F448F75AAF12130806F2A5089091EF4B34ADF466EE6AD6C8E3EB74838E78AF3E39DD775A9A779E7BA7FA5C256F4012A650F68AA6666EF4ADFAC6C545382F9A3669534C56ABAD39572526100CE4293120524DABBF49C6244237E456101E4D469136019D8EF!
B99CD2DCACDEB0633D918D2D7A9336B30915E7B5F2FD93AD53260B668B5166!
39E4A4C2
018C81BA240249A16C5D5A2F664399288A1E13CF15E9BF8AA98D0AC51F05CA47F3129491A2D7986014B739F7B2637150D3868030ADAA11213089E87880391685AB4851BC34E191A1A4CEB62B2FC5191EBAFCD6CCEC10B55E54A9508A3C14B6AECC2378DAE204DA15B6D6545D98F7F272A31818C6C1D058834D3A2D3B9EA5A1F7E12117655D83BB5FDFEBA369486AB2795DB626CCD213C480A642C8D7A5258D9ADEEED41959840460722CDB41A92B911CA65C2E641F674F7356B46E9A2E16ADEDEA9D04D934C399704AD39420AA4D2CE37DBACF63EABA9AEA965C0E106E4D3608148332D2A977549FBE23C9978B097D1285D4D4339B76BD2743E4FC919A430D39502997E63B956A7D3695A6ADCF3A24A4C2018C8157F40249916A3C5593DBCE93363DEA4B7629B6DA1029475B80B9FAEC4A62F93C9CD94AC37FB3D2E228381615BF11EEF43F5A95F20FB9891304C8B2EB7E1359170B2BAA175B18DD4268156C5180B37E33529712E42B7E292B7C2C204EC71A846FC03F1AB1029A685B23AEB59A670D644E8ABB9A43609C883EDC273592445819BE6F27436BCF0DFEA081108D767BFCB3F1029A645FA8B61B4B3E8015D05E19149056EF96BF411DE7E14725B94F47307B554A840BE16088804D362F064ADAE25E42B96D2D4917C2E8187C3D1CA2D1CDB73CC0A9308D3D248B6D7D638!
4205C2DDE6E4C1518048312DDCCE0AFD8AA5349DBDE40010454B782BE40AA8D0300AE381DB55EC06F45081E4FD5B20854831ADFE4D5CE1DB149A67D1799A427C48ABD922451F288C291CBFA8F54F508D84CB24293D5EFBA066C0112A10FAAEC040029B9601AFE37686E45974BF161B2F9A9F0F48E3E1A08A4C51DC7F42D5A469B46822A1B59807E851E6518487FE7C031D3290110940029B1659A60869AE465F25FD76F698B5441E0E4366275ECB8D7C5AA729A336B94E6FB2F6F559F5293ABFB7A612B691E99B5CEDAA0801096C5A0D4D9CE714062F11BA9F1CB2EEADD05DA5A50271D470859D8416331DD06946F7AA81349DD08A4245876DB19FD3308C516C9B4CA48004342D7EAE76A321E8FCA11BE4798CBA8DD827AD73DD810026C96E13D4B04E43494362F0DED636909EEB8603FF9803A3AE119A925B24F2F003E4412940029B564D721FDE6F4405AB8F0AB22F46D72F5D1FAC4976062CEC90D9E81A2B4C56E4349A7E09442873668BBB233179C6DC144F1C281AC58E43B0DBC283D447580A096C5A44227DC19D3834E4F13CEAB479C1F07038AE36F58EEE593455634926877DFA3A3581DB2C9425677030A79C1036500D2D45CD2E1CF63EF2A92D9316E121BA8D2C9240029A16D9E212D44A1ECAE783427D151C0F7E839EDF263C3D90993C28AC0C59530276220D2D2956!
7BAFB5995BF8A229B36653277FB4D16E371526E7E6DEA8C39B070CBE7E95E3!
67DB52E4
8004342DA6A599ACE41982CEE77D859A20F5C16D85272BA27E78689A4D6E4613785744C30DDC6B4EAEA191796973049AF65E7D4A6E4B03C5346CE23A443EBBF4903EF4C1EB0301A143CF21124C8BC26D35D34DC92B7979646F9F15F170041DFD9BB8114B113FE038A0E1F70DE2BD05BD810E4232E5B859D03BD842B56A726CC242789FBE31377D801D68865BF7E9F3EAA1D25466287E15665297665ADC74BD50E24A1EBA86C97CB05013AC5FE1AC852F00D1B44E59F84D9BA6E646299D48833999203069339B5C38ECFA465D7A1EF621838E7BC40B481E7FAF24D7B189E80009685A86A04A5F3ACF42FA259D9A01472881D7AEED62550F939E827958EB36B5A4E1CF47DD5BC7B49ED7F3E9E6468A907AFA6C8D5AA370B5D03AAC1083C765A5C56F23A8FA4A1E20014DAB35995BA6A893D2F263F581DF489D960A89079FD66DBE3BAFE99A4DD8446CC9961A03D938349A4428E34D9B504FD5F1F230D5256B5ADD9A9D061DFBFEAC3A0FBFE2A5183C8FF08104322D4A43CEAD072E7D69943FB03E06B5A1F815DE10C47518AD39DE736734D924A73072D18C903D08895BB0FEB208D3A0C9D1BBDDDF93F7BAC5990D1E632CA2102A3305BF0D7D537AB03CC20712D0B4B0449099A63381F627BAFA25FDA1F2203BF47A2BBC765EA3E20D6F3CB7E5E2261F2F11F14E1BD350DE348845617!
5D565D6E6A2B47EAF21F6CD214C0BD9A66F3B6F0E9A870C40029996A11C973681EE4862A8C9E5FB25B95743E6C16F2BB57ADD4A80BFDF9D69530DCD4B89CB369D227BEB68AAE5461DC919D6C242219537A5E5F9CC280C9C427A5D4028321FB457F8BBD945A840BE2D114820D3EA2FC2535BFDCD9AD179F0FD92DC86D079381C0378E7B5CDA3BD4491E4646D4C3778661B6BB24FFE47A94CB8B38DB5595344EE26A2BF2176C163CBB2F39685A69EF8F63B488A215D56320009645AB499DC09A362B45B09F09662AFCBAD3184C1C36168C187139ADD2A6D86B87A6FA1DB62172937F4453578A189FF40B5EA843BDBE873322923DEC96D6B129D70FF8903622540981A726CC2AEBFD91AD2DB90034820D3129A3AFE6F588A2ECA4E3F37450B7E728825E276E933C664BE78CB739FB3E0257B5B53AECE3DCEE7D878BBEA3C6FA41C9425853BA629DE00A17576575267CC8B49E6D13719437B1BB20009645A4C1A5EE667BB857E7A7EE5783B387BFB783A3C1E0E3A0DCBC156D4CF570B643E51A7F558EC6A201BD2ED7D7D7D763BFE883EF015159AAE64F61BB89B8059D83B098A2768030704E710619BA56B0F6F6C8004EE696536937A365774718DDF9811E2FCDC672EC2ED1EB217927FD184D2E0846ED379C2A6F99B4D8985DD965CCE17B8DC49017F0EE9AAB2687393893F56640C9!
1874C400237E2B5A42954D124321F618CBCA769A8F079381C57F1F9052BDE5!
F419B73B
8AB41BFD8BB5860BC8E6978FCBB02E8D291A44721A9336632F3B4DB169B43E5211790803D2D614DD694A2C9A3BD378C923B3556E8F2E4E0E13018F1A58FEF4843661CD61C5F57CFE34F2E7A87A95923B1D433901C42D564922352D666EDD5D0D3A04C40029A167D9527C25E7B06CF395B2EDEC06B5B5C6370C8128C659074CD11EEF4945EEF9DE72E2296E40A2BCA1B7DDC873E3BF7C1AA2FBCD12255AA44213945C99DAEBBE2847159A9FC0F6F5040029A168DA666E4609DEDA67BE94F535A3C21D4379965E2814CEB06373A834822E424803E57B49BCFB466B26702B4EE6596D6927655B2E518B456725A904FE7462A9C9F5C2E8548D8A7E59A6ED9CE37B8EF7CC546CEF656E4E2E1A0333BF14D9B1A48716B6FF45786D26E531086DFFA16CC77723F7B2E6A8CB1518884CDA5544B13F9E1075DDB1ED09CCDCA2FBC3BE48BFE9BDCACAF39CD8C27CE36AD9CAFEEB9A5D82D0D991A5BC254B96C0A91B2B99431F373E014BE83C44F1AED85164ACE612227AA6C1ABC6489B249847838C8AD18F006ADA6B0AF2AF9142265473C9D470A4D2BE9C6F3375EEE1D94BE4151E2A6B91C7C501E67F4CEF2480984FD37083AF10EC6CE264D6BD8DF464685483A7B48590A85A54DB6D590CC77AA6B0CF20E1355C4553F29F800FBF97E47E482326AB4A82CD0A4D530E157EDA328E495608148!
3A7B486E18C52DFE334652BA87DA891B757E808B2B6ECE9E926E882010B62E3004570A44C5B2249E3D6CBD296C8FE16FA566BAD12ABBA390338EBDA415EF8897905521924C8B31926EBC29E70639D1B9C91C810BD89CC24F0DD8BE6F2200095E21120F4CF35B90FBF4E4EE06E64864DC011DFF8FC80D5A18C7185588B4BB3C08447A659F10BA7B96B191ECFA696A7038C6AA42A4DDE5413836C16DB06D89D0F54BEE6AD76B8B2781C8AD1089B7A631F0E5159A21C83B2174FF269915E4A880632C0391766B1A83F906BFCE9E17B1848BE7867DE707C6341089F7D332D4E852F4567DA1AE26723304C65267EFED6B4E338C6D20126F024853468BD6621C88E068D103DAC6E69C885962DC00917AE7521ACD6E233B3FA029737A2B458F752092EF5C1A85A0E9F8C2111920926FB70C2115C85F840744AA69410405A43B64204A322D50089896021502A6A534858069294C21605A8A0302A6253B90FAB0808069C909E44319808069294C21605A4A53089896C21402A6A534858069C90B64386C20605A7201199109089896D2808069290C089896D2808069290D0898967C403E1C01D3520A907A7610FF62044C4B5140E451089896D21402A6A530858069294D21605A4A53089856D840BA6555089856D8405E9119089896C21402A6A530858069294D21605A4A53489C995647B50A!
47757547622A248E4C6B6747F5A545E7E66EDBB66DC284B9ABA62CB9D4B133!
8A40D077
575D52B19741477535773D080AF9BEBC40E2C4B43AAA672C59BF7173654141C19D3B05952B365F9CB048153D22AA198B561DDF787CD5A2EC194BA6AC5FB59EBD1E1C91011217A6B5B37AC694B9172BEFB847E5EC7397A24644359B7CD72D332F6E59B162C596D97397A8764606481C9856876AD184CD0577BC63F3FAA811517DD3271EFDCF071FE472C85D0FFAC45DDFBECBDFFFDF7EC57F0CBB873CA6B5B3A34385BC16FD123EA8546126E09DD54B566DB923169BCF45CBB554C3518F57FE0F3F8A2AEE437547879FACC9E637B74117FECA25F47FF6A2731336CEDCB871E3CC99ECAF99C78F1FDF36F7DC9219A127E09DD5D9E72E16DC118F2D532E75242890ADDC20CEE43F6CDC86EA98EC19AA6AEF81440A98B168FDB68DC257CE74FB7B33676FAEF41EB38282CACA2DA12560B6AE42A97CB63F1C2856CCCDAEDE19BEAAD9CA4975A9DAFF4B451FC8F33EEFB560C54554552C61652028018DCFA255B32BEF041B955BCECD08EE5266ABCCEC2973376E5931FA2B175C3C975D8D824890AB4EDD85CB3DE7359371B9297A0E41CF5EB268CAAA6D1B8F4F98B244D5A15C207824375F9CE9A6828BA8C428B8134A047329A34143C5E584D9D2BE55C1966DEBA72C5A3243D5B173A70A1563C779E122151F473396735396CC20BC50B1B6045B2A7AFE389ACFAC3AB708B1387E91FF4E5!
B5665578B03D9EA134F3DF3CC339F70E6F2BFBF7CC62B1EF51F6F7DD36FFCCF3BD18C828DD26C6B67F5253468084610E00B566C9939E1DC92EC25AB2EFA3C55894AD46D88095237A2BC6D85C7736CD47A7CFDCC29A23FA54AFC1BBFC10279ABE04E7CC6EC298189A0F9DF946D17435221A2E2CFDE0A2AB7CC66638B04B3DDB23EFB925B8D484A1C3F40B67240EEC46B5C9CE2396FD8C97521DCABB56C3643C5F8822BD8327BA647A9C2FADBA80A895B2068DE30A3DA957C67642F9AB27ED5DC6DC785777E7173AD427FF2C45408AA1166A23909D20262B17EC2CC8B9B37AFA88D0F03F603E42916C89FDF89EBA8DC82CAB68B9B2B2BE32A15263090F80C00024020004868556901005152ACCE4ADA5E00409412B5593B3E58BB63DD2EA500F9726C0329387B61F752A7F3FA86A4D50024F671F8EC8503D79D6C2C4522A905209293EEAEED67D7AD5BB60CFD9AB3FDB05C2FBB6BDD8203D7973A492C3DB0604E419C002938BC6BF59C65EB969D6547E4ECB575D7D8A1B986FFE4FED0328F87D6797CD5B5EDAB771D1EED0D17D4BEBC7D99DBEB2102DC8BAE5B9795B463C3EEB5D3D7AE5D3B7DFADA0F0E5CD82E873656AF43AF3A5DC0C1C6F40D0BCED62A1C4841416DEDCBD7922E4C3DF0C1743222E897EB83F0D05AD10FEE7FFAE0C0D4054973C473672D029EB57FEA076B455F6!
FFA75CF71DB3127BC2CFEF29CAC053B36A077E4F1B2AC48A61FB810BDEC2E0!
94801AB0
47C69735767167B75A29FDCFB470F29965E9FBE7BC385A475CB38F5100921396425EDDF8F904F97FA4DAE874EE4F0EA6BFB91DCD01BF2F396AEEF9EBA3F6BCEEAD5BB0ABC3C62F5594EB873B66FF77E0ECB1B3D3F0785F0E4E139EBCEBE5C103C90020EC8A3E4DA599DB4E1034F15785D9D725011AE7D9714AE5FBF1E0CF3E953AF8544634ED205E47D01DE11BA6C90982F24F1B9AAA076D7CBDBB376ECE6D4BB76ED6EEEB95D8785967241EDE19757675D38809EDEBDFBC006F46CD6BA75490BA6EEFE60C385ACEDB54100614DFB5AD2DF7240761D3EBC6BD76A5491CB3CFC9189A5D3A7065FA5BE9C7561C307922F2FE45E3BF667711E91B57FC154F7714197D4860BFB93D013ACD69187B0A37F5D78120145E4D8EB6BE9F4DD3BF62FDB250DC876942AF72327DDAD6681FCFF0549E88F530F5C77C6495C3FB02369B5E49A0815695968508315FB75EC12D7455C02EB1C3F3F7D1417598A2C7041D6BA6BEBF8AAE72CEFD667AF7900493AC0F904320A0E48CFF5EBD36537A7C88A8435FB39A24B51B52FAFDEBE7D3B327C5CB25DE38A3499D26048170F02EB5DF0B0BFDC801424ED16BE1C0371C6612C4532D97F6D75AD570195B460C7D40D0776FB2DD214132E20672FAC75260010EC1C07584B600B4264E7FB59142C80B8D0BA8A13F03224E0DDEEA922AE81B859025B10C609!
091E88B880CB5820A94E88E803117F386420D98FACFA1F2856AD5F520D831B7B20D58FCCFE7CE59E957FBDF2D4A91F4E9801A31B6320AAF53FD8B377D7932F1D3C79FAC4CFF69C3AF5AB4530BEB104923DFBF3CA835FA0F8FDEFC78D7BE9F4AEBDA74E4DE880118E1990877F3BEDE41713D17FC78EFD7EDC4B274F3FFBCB9FAD7C7ADBBB30C4F20129F3FFD7F24BABF23D1EE87864CFE463139F9888F471ECD8B883274F3E7BE204F2AD378F03115980A4060072B9FD6889A75FFDD33D5F3C3171E217CB97738675F2F4BC5F1EAEAC9CBCF2E9E3E05A5100927FA4ADB8DD5D22EFFE76DAF227903E96E7963F376EDC49C4E3446DE53DF7DC33F9D49B0FC320470548774FA9DB038FECB9C5F2F862E2DD5BFFEBB95B279F3C7DA2F627951FDF3379F29E37DF03D38A029092B6EEB2336E02F9A74A367F2C5FFE8BAFD5FF3AEBB5279161CD7B66EB5B93274F9BF6C23B8FC028473E8754A57617B7BB24F2C8E7E35A58812CFFC5FBEF3FF0FEE99FCE3BF193478787BFFC78DAB4699FBFF99E0A8639E2409C196DDD6A41223B374EDE37FC0002F2C573CF3DF7DA6B1C90A78687B72281DCF7F8CF218BC805443DCADF2BEDE96A9BE52AB17E34FF937D13977F810AAC836C8575A29205F2CCE4FBEEFBFCF37BFF301786396C203D8180E41F29EEEAE1EBAC87F79C1EB99DBE9C9DA2B3!
3C9E3D71B8F2E34787BFFA2B16C8BDF7FEE15730CC9107E22C5177A7F249E4!
91692F8D
5CF9C5F2637806727A1E9A81DCF3F137DF63793CFE9DEFBCF80D18E62800A92AAB2FAB229F4FD87370E2D0FCE52EC3425310B6C262790C7FF25D00120D20A5A9DD6D25C4B3E6FEF6E0C4079E5A8E79FC941308E28104F2F8E3DFF9EA7550485480E4B71777F19375342D9CA8ABFFAFE7C6DD6213C8096E8ABE9713C8BDF7BF3EFE6D00120D20CE9236C1B316ED99B7FC8BDF7D0D4DD14F9E3EF1CBC3BC612181DCFBFAD7C7BF0D493D7C20470303294DAD6FCBC01279F7B7F71C5B9E35FC3E3B4567FD0A0161F5C10AE48DF1E3BF0B656F5480E4CF2AEE4AC5127977DB9E71BF5FBE0F11998781201E9C617DBDFBEBE35F7C0726865101E2BC5CD6DD96C17DD6F1F00B278E8D7BEECBE1F77FFA23BEC29AF6F8E38FDF5F7FFFF8F16FBF07DB1DA20384950869F9CED8BBF7A5975E7BEDCAF0EFBEF9938F3F9E8C80DC77DF7DAFBECEF218FF5D682E460988F38CBA5B9D41EAAC177EF6D2AD9FFEDF3FFFF5F0D6E7DFFAC1DEBD3FFCC6FDAF0F6FFD57C4E30FDFC886518E1290D2764122EFFE70E5895BA7E7FDE8FF3DFFEBFAE1E14F3EA91FAEFF352B8FF12F8240E403D216E82F97A885966FF65FAFDC75FA74ED9D9F4CFEC15B8F3EFFFCFD7FF5EABDF7723CE63A60906500D22E0948694F57F11132397CF8D4CA9F1DAE744D41088F5FC17A611481388FB475975D269F3FFCEAA!
9BD3C8FC7391E2F028F6803612B5F5E22CE25EFFDFC853D7BB90A0B014138DE7E6702F0882E90FC23C5AE26BCF3DDB9AF3EFDEA0B2B577EFEC2BD3F7FF1C53FBCF3DE23B00528CA409044EA859E2F87E4BDA7DF44F1F6DBEF3CFDAB8777C2F0461D48697B5757991B918EEC29E7FEF8CFFFFCC73F4E59046E25279059128138CF947912713A33528F9EC987819519C8111648B1941728517775A9334A0504A5A9F55DEDA530B03103925F52D6D5DD7634E37269697E3EC252AA1EF6DCD408211B903649AF505A5256DC5DDC56967AB47D56C699D22A00125B85208D5C3EAA2EEEEAEEEA2A6E6B53F7B4AB59CB82241243204E6755497BAABAADADB80B6129EE1AEE6A6F3F821CCC2DF20150F42C0BABA4AA24E348FBD11E755B57777D7159575B598F7B1C3D5205431D16900C16485750AF84527A7EE999233DEAEEE29EB6EEFA2E8F689B051A091F487108AF978FE6EEEA23B35807738B2EB7060B44748194A8EBCB2E730EE68A59EAEE3200122320FCD9AA7CB7282DAB0720B10232ABB8EBA877BE282D0385C40CC8D1AEE259004409551601D2D3E55AB2720101CB0A134889CC404021B102520A401406C4EDD8888765C1543D4640D0D85F7602104501A9F29D9CA8A175122320556AB182AAB40404121E90CB2C90EE9026EAF5A9252555A007998154B140EA83E791A1EE2E3!
E5AA6EE2901224A00C2F2E8EA99D5D6DD55061B4F1400A43443DD85505C6EE!
77E83B18
D35104E1FAC34F2D9AD41A9976170630CA4A40C61E0924769099B4A80484C81E49F492D263C109123EAEEB6A350EACA07C4C902190EE685108F6E75069FCAAB66B50DB7CD82FE55EC805CEE29EE6E3BE22250D5DED6AD86E2376640D8F39FEA23EE8AA84AEDF2BC7129445840D4EAB21EE9FF7E082A7887DB3C78B073F62ED8522A1F90E00A5EAEAAF2CAE125B0D5245640D80DF0C5A9DE33C12A58B7950BC8E50C69D14E368AA6AABBBBDB527BBCA3ADBE0D7F52A69616C5D2A26BD827CA1208C8702204005158140310854506005156A8131A48B7C4ECDA263159FBE67BF13822B19818E1A3A79ECF218953CEA946E236CEB4111C5D4712A9EC8D5B1E470579245457395E815C16E4312BC12686F1C9A3BD9BCFE689B6E81297402EABF9F223C1E411A7406609F248C055E2A800993F34F440FAC848FAEDA1A11FE3477443435774EE5F727B1F7A2C53CA8B5509F2684FC8E6621478A40FCD4F1FFA6864E4A3A1CF3E1A4AE71EBA727BE4CA15AF2FFB8D2420B3F8DE625B626EA2880E902B9C303E1ADAC70FF995A1F99FA1DFF65DB932B4EFF6D07C412177232D3DF1D9D0DD233F1EFA4C541E650447FDD1446DBF47C9B2D0188FA45F191ABAFD196F5943FB5820483399ECE02320482108C51357E68FEC43FAD927F64247047924EC3EBCE824F5CF1012F6F7BB1F60C170F1E3!
DB481068E4E70F21597C46149289380D3D803EBB7B48E3FB2AA5823C7A9C4E00127ADC8D28DC4619E3CA95277418483A92C77C944E3C806085B04F3F7665E88AEFCB6414F3F228710290B0E2235453A1EC91799BF3298480CD15ECD87B2B847D9CFDCA1FF3D5982B9C65A455529FEA74029028C77C528CB9A284974771891380443BB8BACB2352F94E626AA26FF58A8B997A09DF492CCE703A0188821AED63605B91F2815C4EC875A8F8052234DAC7C8AE3B8503113A895DB39C4E00A2A046FB9839FCA38A0779748F1579281B88D068578FA5B3718A0522741213731D2AEE808C81467B3C0119138DF6380232361AED7103243F75784C34DAE305C89869B4C70910BED15E5FE674021068B403108FE8A91F5B9D4485033933B61AED8A0792A0073EE21548C21EF8885320EDDD63B193A8582097C762A35DC14012FAC047FC0149F0031F710724D10F7CC41990C43FF0115F40C6EC3A9432818CE17528450219CBEB500A0432560E7CC40B9031BE0EA5382063E7C0475C00817528650181752845018175286501390AF2501210588752161058875214902A588752149059200F25018175286501817528450129857528450181752845018175A8608044F19F308075284501817528E500298675286501292B1EABE7A1940AA404D6A1240381210020100004804000100002014000!
08040001201000040280001008000240200008008100200004028040001000!
02014000
080400012010000480400010080002402000080081002000040280001088D8C77F0B3000C784193E7E8425740000000049454E44AE426082');
+
+insert into MemberImage (imageid, member_id, contentType, caption, data) values (-6, -1,
'image/png', 'During my trip to the moon',
'89504E470D0A1A0A0000000D4948445200000244000001B30803000000F941F8540000000467414D410000AFC837058AE90000001974455874536F6674776172650041646F626520496D616765526561647971C9653C00000300504C5445635A53317090B7C8B169B3CECEB0946B6B64A99A89DBFEFE92CCD3C8CFB78A9485B2D2CE43393599A795B7A696EAFEFD8779687A8474968977383938896F537B7B744E91AD756959CBFCFD99A58B8A8C86CCDACC746B6410344D75C9DBBBB9A78BB0B26EA9B5A8B8A88A947A9A9C96000000AAB59A6557488ED7E99389258E6A2F6B736495947A5A635286846A857B74B89C87D5E7D47A846B728D8BB9EAEB124C6FBAA58BABA870A995792F2314A79C95695035A5A58BBAFAFC4B839699E7F5A8DCE63782A5265472544A37A9ADA6958C85C9EDEC84BBC9AAE8EB4A52448E8848B79879364344689AAAB9EDFA988569A78C76A8ECFAA697442B657C24150D4A6F75C79B79776F2C36322874735AACA550A8896753A4BE062539967A63B3B99C7B634B6B735AACBCB2C9EEF8462D1BDAEEE9AB6D4F745A42B7AD9E8B9993394238AAF9FD0F405A646348D9F7F5B!
376662728209B9A6AB7BDB235291F573E2807080BE7EFD8B8E1DE021727171713A59C68C7F7F49CB69E677675827312B6946894392B3E0A0A021215BA88683A9FC693533DA954414656677E7842475354B9F7EF8BA59992E1E0585238D9EFF8141009BB88742F3131C1BC7D644A40493D232731278CA58C175F81673926C074627B947F646A6E1D21196E0D0A495239957B734A4A530410081007057729185A552652524A5A5A525A524A4A4A42524A4210081163635B5A5A4A636352524A4A4242426B6B5A4A42426B635B4242395252425A52527373637B7B6B4A42394A4A4A73736C8484737B736C525A4A838C738C8C7B737B6C838C7B636B5B84847C525252929C83727B639494844A4A397B73636D63528C847C929C8C94948D8C84738C8C72A4AD929C9C8CA5A59D5A5A5AADA5937C7B629C948DA5A5949C9C83ADA59D9C9484636B525A5242414A425A4A4AA0AD9D6B6B52ADAD9C52423F424A39ADAD934D42314242313C39425A4A3D42424B515A524A424A525A42404A4B5C5A40515B5B524A526C5A5252525A846B5BA58C84424A314E4A2D5A525AB59C945C413C28292C6B846F000306000004020106010005B62849F000010F9A4944415478DAECBD0D585367BAF76B88243169208910925890001762A312F92A1F129208848A016CA0D21A1001052A4505D60E0!
8D6BE68A716A8D416A11BD9DBC1A94E476BCB6EE7C096F4400213D868E4AB2!
8123B2FE
39CEA6EFB9EB6A723BB9753633CF7B3024AADC897B64AD6BD9290AC242B61AD5FFEF7FF7E9E67ADB5A0F864C3C9936527AB4E8E07864F0DF73CC6A698FFCBE7270B6C4653C32CDF474C739B1AA6BFDA4F162F38895930CC62C12CE6B1B08CC5BD8FA79A7FEFF39385658631DBF71131B7B0AE756CAA97DDC62C27179CB4DCBA75FBD62DB825828859C4ED5BD88293E65B80D3EDBB648DC5BD8FA79A7FEFF393923BC398EDFB88985B4C77BD83FC801261B72D48B3B0F1CB58DCFB78AAF9BF787EB2CB0C63B6EF23626E31DDF57E0BBB7D1229D16DC8657788BBA352F73C9E6AFEBDCF4F4AEE4CD57296EF23628E596ABAEB1D305A805908888898134477D2D92FD58BC867443E9BC67AB7A633CBCF8DF54C63B6067BB2E53CAE46FA517FAFDFEAFF9EAA809AEA79AB129909880888E60A11A14404447383A86C4C896ECD1AA249FDD62C9733D5727FAB78D4DFEBB7FABF27FBDCA9B6F37D9488808880682E10119E8848678427222022AA330222DB55A2D97EE8A35A694F6A47EDAFF5BD1FD6E7FCD2CC5AB0592B11011101D15D88082522207A384A746BCEA5FDB44BC24754D23EAE4D038FCBF77E589FF30025222022209A0B44842722D219E189088888EA8C80E8C987687C64E3741B01A7DBC8F8A4AE245B8BB9AEB7F1C646022202A2B94144281101D11C212A9B5289A65BC2!
FF5AA5FC7C2BF19FF82686E92811011101D1D47B7B10E98C48678427222022AA3302A2F9AF44730D6233CD6FA86EDDC2B0299588808880E8C11059082522E2095022A2889EEF25FFAFA044C46699EF10119E8808C2131141546744CC0F259A6C64E3648D8C8F3B3404BCBF6E3C700F58022222A6095119A144443C2C25BA35ED21208F7B494F342DFCDA2BFC01C72722202262FA10119E888839A733C213114154670444BF39448FAAC59A58BD3602D1A36CB12656AFAD406421948888C7588988DAD7666AFC47A744C4CAB595203C111184272282A8CE88989F4A3459E3DD6C0F5E4E40650B2DD6044444CC0DA23242898878F84A34E521676778E818A2E4B781A120180111110F61501A91CE88985B3A233C1111447546C46301D19C06A511D01010CD7964230111D14E442811110F4B8966BFCB1051D21325FE9CF73B23202220223C111144754604519D11311F5BAC89416744CC24C64FDF494044C4DC2022948888DF4C8988DA96086B853F072522561F117720223C111184272282A8CE88B001259AAC31F1B73A39DE235B19C48F63768D8DD3D903968088880743643949281101D1A357A2A976219A2F434088A68B47787C22022222E67C7C22229D114178220222A23A23207A8295683268A6DBE8486C141B81E87E7BC0121011316388082522628E10954DAA44B3DD65!
88289989E31311101131F7E31311E98C08C2131141546744CC0325B2D59541!
40FF105B
AC09888898194416428908881E8112D96CA54A34493CBCF144044444CC793C1191CE88203C110111519D11103DC14A64EBD04CF7A0EFF36D30DE43696C3C49404440343788CA082522207A784A64EB25FD744FC935DF76957AA8E38908880888E63C9E884867443A9B753A233C110111519D11103D3E4A642B07B1B23CA2B015A8EEFDFFA635B291808880680A88CA082522207A744A34DF4BFB871DB652F2FFE2FF9BCE7E67044404445342447822229DCD399D119E888088A8CE08881E0B887E76D23C5B6B6C7CDCA07A5CB7C364DFEBBE675E242022209A214465841211103D2C25B2BD5D861E3544B32DF91FD7ED30E9F7BAEB8908880888E60211E189887436E7744678220222A23AFB5521321310DD07225BD903766A3CF098F4E963632FF9E5DB2C13A779D3683BDD8398D9D41EB0D363C83C89D41C1B8308BB8722F3F8FBEE84ED41642194E81E22A6E00C334F029F0D436443C7277A085EF9BEE96E2A88E6EBA1761EA8440444160CBFFCCCE34C6A790888084F747F2A102D63D0982760F2403345782202A27B9296F93E8C58088888EA6CFA4D411349C030CC8CAEE3809809882657A227ADF1EBA1C3043FA9935647841D439608C3AC8860656314C1A56162898FBF009B0AA2270DAAE99E2CF1CE6A9BCE1EB03603911979480B36A6C9000EE09372687D52D21EFF3D7!
BDE78737D198635E02C359499115508A193988580681AC727B215886E21443033E80BD0823514B9AE5729DD69713CAA35F21CA3190AFFA4F545D85D58B0FB1467B6AD44B67268DE49750811646E284308A524B94BA595D2CA980DE13C44D1412ADCC225BABC5C53B1E7701912A2320C6F9AC4660AD1935ADA3F10228C80C8DA0306D7B20648544549EE1A1EAF3C26465AE9E6E353A9C8E05179BC8080121EAF44A329C9C8733C98DE9E82240BF74A160222C213DDEDD0C035A5ECB07B7A4C1EAF2420401A534953B891858A18695C79785C390F89122FA384BA35CFD17189FFB765083A229D59A6757C225B81084A2F73C3B7EE8E5B217D6D8D8E2EA1F24A62623401E51B62683EB4CACAF0ED013171C81AA18B639E639EC7F765166BC946404428D19DAE556CBD7B1E350F85D54AE7F1F0D8E006C1150ADD1434ABCBCEA33A3A520F3A3AA67F0BE0DD338E8450A2072E6CBEC084FE859FF1831583BD0102EAEB0278BC684D745E74349577D0F1E0416A9EA6842AADF451ABDDD4E408B892B90A1023472ABCE420353A9A47AD380CE89D844ADF62699886083D70E33CB1EBF396059B5489E6314477FB592D68EBC315587A339DC78BA994F25029C6A30243071DE1018D46560144FB2B23C8E4EDEA5AB7701E353A00BC1135A0A41C5EA5D903B6E8E449CBB162CB7D4689D80E449!
8CD42648D2A4B31F094E29F410DAF546C007EF2A80C9A066C0F781F5E8054C!
AAB14EEA
F54CBDCB86A1F3721301420944814D29872A9262083EAC8A3AD076B543C56EADBBC124DF710BDF3AECC6FB0981BD62BA8BC7037B7CAED31C8F7282ADC3579071DA954A9901740E3F1B69747A82412AE4A5849030D2A71E756565606C448A590F632788C378A50D3B5E517831EA759E23FF14346262A91AD4034F63FDC4D6A66AC4195C1E3B96D2793DD1442A99216C0A0490334198E3C8D349C4AA5F983B92E2FA7F14A948A0A09C33D83CA2BE79504944BA5B438AA4628ACD448304BD92423D66C0522DBF544F8B069D8FA45FE01E1E1113E3EFBD56A05A42B5A80465A428D3E7830402A14C6C5B82729F2A2039002F11C3318ABF748DC41ABF23232A4E5E50154AA86A6916A2A8ACC27F1C1D68427B20D887E59DCD72B636222D46E6454826550A534A5BB7B9D22407350A3A994C868EE12548E4161AF61444369EFA8F1174A03A0BEA7F24ACA35D18E8E2528DC5390165988EACC2621426DD4EEBCEDE44A3759ADDBFEFD310AA57FAE8AC1E3E545E781C15608B70B2571E0B1A3355485927130CF712BA287265132E059D0260F05B86F6A49745EC5E169EF9036AF95E8496D1C9B354455A8BCC730775E8C9B9B1B79FF7EB8D9409354D2A4197893A2A3234F08CF54564A69D238A8E779F83C28FF156E0A49A07B09147054EA120D9ACB8B3E68D5A2DB68A1B3DC53F6496D84BC!
EFC8465B8108B3406DDF5056914175538308EDDF2F73DBEEB3C18DB7A13C23E3206A91CEA3692A2B256E6E34052DA69256298DA109150171521997CB8D082FCF2841C96C2B5503E29477904A4D4F41CB3C6939697B10594EDAAE12416D5F86F9F3A81BC8FBF19091DD22D46472780932CE79D4839A0A6A798CBAB2D2CDCDC7C787ECE626E40AC94AB55AA6DE4F22F3787190D11CF3347979409B23EA6E032DC2E6B2CFFEBC56A279B8E7D0ADB174662E4B82D25E2DC311028822B832B5A43C20C391BA752B6811D8E94A3C7CDC222ADD7C20DD91D532592D5CB9422A2D29809A07669B17BD156C3654728E154516EC3636E3FDDB9EFC5D88A6A144F31622B0D5F2800D0A60688CA2F0082EB756488DD668A2B7C294E778D051535EE986308A409DB06E6435FE3A924C9811E7EF0F955C8E3B356F099ECF780152EA1E4BD9C9E91FF061FE40647B9E68623E4BA105B871C93EE4FD50E0FBD4927CB864AE240F8AF974DA5647D4550F0A535E190113A434B88018ED57EF27EFE7722519197BE4E0A9A3A5792554486860B86394BC926FB169B65A139E68BE40548CB967842334A4B4884AB5226683902C53297979D41206231AD99C83204501E5DB237088B643562393DD7CC811DBF7FB90B8D48A1406BC205AC3E3395A215228A88C19341711D5D93C8008FEBE91111721AC74134A!
A53485BB821AAE546F77AB2C41E388C01431349A3C80233A20A6BCBCB29286!
5C116433
32797F049924AB2509335C198E0721E345339064417946136AA839161B55A2F123A5CDB746B0C9D6051A39760B8DB04FD1C4842BC8D20C8682E1EEEE5E12CEA3C59473D568383EB89C83E89A478D2E0F8889E1D140AF7057444696683F69BFCC8DEB23714703D320EF8160FD0B6A72AC74A752BF379B310B86A13D8F66DAABFFB8ADEF99ED016BB62D88D0E02174C486326578F806B250410D704F5754087901E134F276B5309C91170D62E40835571E545FE5BCF298F270C5B82B22BBE118ED8702AD56E88843E44885BF5BA1CC8FA6F1A88C62042976FBD6D8718B6C02221B54A231882CAE6077144285507A50A14817BAD37895725265A05B0494F68ED179289541D5A509882929A18114F9E0C51998A2FDA84423D792642A79347AC956F4B27F81298FA790521DF7E0FB598314996D07A23B4A746BDE0D5198BC5235E3FB48BB53E336088534A13FCDBD42E14E738FCB95A8D4952405C810C39FA10134B652F3A20318313C296F3B9ECBE02223A3E66DB7FDB5649E3429DD712B4208B536E6215B2415F2A85B7F420365219961D385E8715DDF333A3ED1F871AC6D07220C4DDF46F3622A155C8550E9AE84502868815CA8BCC84289A3A33049131D8D6AFC684D098FC6E39594540A81A018DE06B58CBC5F564B5693DCE2A4012059C83B1DCCC3752B5A53A9282F71ECB01E4EC!
D6CB61D886CD113419459CA1419BCF0729022A952E8EE5EE14E53D02424F20619999CA47167680202F07D3E18B4689E541A2E2D5780B796284AE21424AE5A2653C771951A7F06D59AF40E1EC4F71059A2A0D168D4BCADF5681710ECD62DC213CD67883004D19BD492F20D31316089FCDD3542254DA1A409254232C94DAD91248129D2E45135349A3BAD84C78B914ACB0360D204442B144A2E92A20D52258DA1B1D67190F700A6BC835486B492468D76BC69B634DC31454475364F21421BB9A882C78BAB945696074895EE527F65BABB422121B981C8B8C5C8EDA85B1DB732A8527785349CCADB10210CE051F3CAA3515B7689A256BD5F161818C0D06834EEEE9A3CD4016B55A23C6A8092164D755C52044A64BE85596C4989EE1DD9385F87C5DEFD77C0B1B8669484C754D2A452AA342983214C07CD4912864B556A12ADBCBC041CF5C13C5E804A2954D02AC96E641A8DA7D10468D038B43819494692E44AA0188BA669DC79C85167ACA63A6AA8BC122A244250A43DE0DA9167986E43D163DAF8385DE87FD6626D3B10C1E6BD19571E5329A5C54879EEEE0733183486422989E3F122C8B5121AE80EEAC7888E1172B924B550AD1692C369C2385E9C42A9D484C7C9F6936A79923D542A2F20809147454320A3A9D1EE1A74DC07060DDEEADE8059EE1CE9C11620B2452502212A930!
6C45556D2620262A84A1A3054A16128419484113EB512292FBA04AA7B6A068!
DA65093C
8643597EBA650A8D4C270212853384F4D92C9B9AADC241E1AD988761A2A41AD93EE0A2ABC85A160005087D1616A6C0822EC97FB9DCDE7FDCDF07F07339BD797046C0788C2CB03A8420F0D23DD3D23434393AA5DC9115C7225B23F009146A8F62171C96AB0491299042AFC8808B5126E79322E2910A6002AB5C431BA445382EF771D4063D040BD0ED2183CC79B18B8A2DB9659E6B3C7FD90CD0F3C8EB5ED4064B1F86784C7F85456F2624AA8EE4A695C1C831A1327917073B93E64B7725E89A346E348959054DC4075848CBC41A1ACC48713A1FD60D5E47032A9965B2B51903468D47586263A03808B2E09F04F025F44D548A3A9E9E60633FA205B81C8063DD131C08816105EE95619C3939694D0DCDDA5D1013C294DA252D5926464B54F4C89660F83EA2E018A643237928F4CC253D036A8D53E649FFD24B7FDEA0DF0B25A355728D594E4510F6644474783C90657AD606404C4F1024AA85B8B30EBB837C213CD578840887EDA1A87462C6E8F51F0A2A50C8934A01C2092A9642452AD4CBDDD9D56EEEFEF2F11AAE0814C285128680AFF5C2E50847A5FDDDCB811001188519C50A94CCF70748C8ED644F30027478DB424461AAE29CFCB5B69BE7B5875A23A9BA725FEFA92B8988898CAF24A779EA6DC5D525E020C81BEB8A9F793646E95E56092780C254D55AB562B84B5342A4F23!
A409795CAE2C02D29ADA4DED531B081891548AA424E541C6414794D3C0621FA40668D071F9A879156343F66DA4C4B7FCF2CC8BF3FCA0E8E8C0D4125E797844E5867245098F16CE50C4F134B4182E49C64D91C9B83E341E9556C1D0D014B5A0443E1212505252121313A78EA186D32ADD486AAE8F5B606E6E2D49952B57D0F268E91A6A09643428F6A3A90C45493843C363588F80649E1547BF56E3E1741B13277BDFCF8F9466B6398894E8000D956EE5340D0FEDDAEAA8E1C59168112A5475F970CBD158A224798A429E2B510BB98AC03D34854425510879C09AA65CAD06ABBD61831B29B0960C4F4894528D940A390D1D628DAAD15003A05ED3D4DF3E76CCB620B23525B2142978E1318A4A1A4D0AD987E70E085169493E32320D529492867667756444D348AE81242E894496E726A9481212494A43157D4C849ACCA5F9C4F1DC6460AF0325F214F91BD13428D0408C32F23232D01EFA0119EBF18345D80C446577C613CDF35D85EE84D99C22850A5F21DCAEA8CCA329A24BCAE3A84AB9303730422197D284E134AAE68DE88C74AE4422CFA549C9310A1299CBE506CA85D268C73C29DA09AD5622A4F17CD424AE4CCE2549E29429CA2425C3312F2FFA605E74465C4049794092F58823B3DA99F1D71ADA31DDA11E93BDEF3E4A643B10A1318D71E11B14A41250A2A46F153C5E74!
803257C5CDCD252B2592CA720595F186E3C13792684A798A921AC755CA6548!
92C81BA4
54C857AA0D6E64894A45F2E1B9A1220D4A3AA94222952425B9531D3332A819E0ADC3E3F224E663B33E33DF930991AD79228B3C4EBA218EAC8AE095F094290A501F7992902454E572951205A4232A4379D0D15DA192BBE64A78BC40898C4C5291641B50CECA28E14262937185422ED46932C0484D26A5C4D1A454A92A9D473D58C2CB08E0D1683C255665B9EF1989084F345FDA89DE90C6456CE09214E11B4A02243CDA1BAE12A9324542524A54B480726A78002F0F24C55FAECC95C4D1144A92BCB6962B0BCC5528331C330254B53299504D835CC695916A1146DC5C6509A248A9E165646494C795BBBB952BB1061B83C8C6940833ABA41B22226412B29B90AC90F0DC8B248CDC148942C155A9DC2BD181ABF19379B80B1529346A124925240506926412B9926617E04853710365422582484626CBB8B5B56AC868E40D713C9E3B2320038CBA26C6C7A7525866B62D88A6DA03769EEDD4081025F9446CF091B8A94912B982A4A02914BC24451C35C65D88E7AF184D06359A5A92A1510AA57134FF4005B93690248F53E4E632A88E7190DC5432AE44418E90D592C950EF73D5B5240557A2A431949A9292F2983869B98F8FB00C7BEC207A548D8E3F3BA2BEAD4064461045B8C9B6AB6B6B5524B990A7A05179317131017134A54AA554D03478277E1ECF5F49536650E5B9812A39491!
617475BCF70D4506924990F8811586D592D37904426079248B51B942A89B25258C20B280FA749B7BB299465E6D932F424425466734A64C692DC7C22C8B2ED64552D57C58D8BCB88A341CDAE904A632A5529AA24771E3ED8F52055F8FB0CF78C0CD472AD52A98442490094F0FE72921C8C36904322E5CADC6464B7FDB52492CF76B24245936ACA79313160B71464C9D8591B2D8412CD8F43A2FCA272354B140091DA2D8224534862A8253C1E189E180492849614A8F44787F9D89A9747DD53C49030244A9252AD22A9E44A39CD71AB23030C78AD3C4E4E8A50CB483EE1E4402ED707CCF506328D262947FB85F8D022A46AAE6AEC7C7A8F5389FFA88684CCC9133DB9FB9DA9146E6E5C32C927902C94C4C4854B2B855C89B0BC52280C94D2027393AC10513324B96FD01CDDE58124894CA692AB94CA68EAC1839214923A305C58EBE313E8C3A36E7053ABA1E42705AAB81BDCE2623644D0227C7C7CB8925CCC6C5B10D99A27B258028564AE4C48A2B9FA489471253CA1929BABE2D2E28434A1D247599454929197B73583172D91E72A3224508E496824D4E0A8546AA819194AB0436AA99BD04DA2564A783E24B52CB016AA341257B1410A00A13D6549F29493B31D08F284A6335BF3449693295C6E2D57C925D7F2488A125E8C5CA9520B15B9680757A544E8AA9296E4E5959484678!
09F96705572B9FB06A92C57250B0C540919D152726E2049450629F321E592E!
27CD0A09
0FD245220D8ECB80D4AAE1B146C6A796E917588B585F044F31522AC88240B54926BB9129E3C262380C615AAC85C52A052C8857BD2A2A498125E744080265CA2929395A44089520ECE3A90541B18A8849A5FC895C9B824A18F4CA1022BB5818CC6A7914188207CC824D4F82809742DB29EA5DAA620BA6F63E393B293DD8CDB894E16B926C964642E59A620F1623412B244A95083ACA825808D5425A1959404F0023407696FC84924AE4A459670E5B5203FB5F240459C942B91221523056EF75191C85C35B9965C5B2B2343AD5FEB0630A1C6276068E28188CD3F9B1EDBF53CD3EF35AD16EBF90A9105C35250A222A19DCAA4B4381A892B9328B8AEB55C19579D2BF44F42C365CB79D12519F2F52A552D643E486AB5204581009244A1CC25293608492AB53250469671C9B90AAE0ABD934B26BBE13DB5B9AE4500117672C241FB67757ACF2708A2325B53222445275DDF808C462693149552214D1EE84A2207E69224248942AEA2E5E6D2A4E5525E3983AA480170B82A1A570E653D2004E8098592405A1C097FB74C2691A9C95C256A357223C35D35F86FB96B0A30846196C91832CF6325BA35EDD2F3491F2A82762C4CC995CB555C28D068A0430A6E6E20302293915019267595332AC3A5E52552A9060AFBC05A2006F2197867B99CC4850A5FC255A80241987CA43E5C994AA670F3!
E192C026B99190A2810EA5800E8125BA3D0943E6C7753DCFF47B4D6B3CD13C8508FFEE4545AE7228BEB80AB210D0909002734172241212E88C462E5704C4544AA53C7F852430571628E74AE464955C86280235E22A8442A02E50450E044F457223F9282424B4BF35974452A95C5D5D8BCA901061E30C596C03225BF3446847F9B2225757B95C225172E5F214B81718E8CA959054F0304092EB5F4953542A14312445A00A8DF75006E6CA49708117919412856BEE766E6EAD5C660587CB95A9A162833B81B9AE289761D8DD6466369B6D249D596C0D2254231515A5B8E6AA801BA023D01570021E482AA1524E93C8938495CACACA241F256433556DAE1CD428508E8448AECA552AC834A8E6B8A440197824994C4592C00BC018C9E490C952528A2CA88968FC98FDB603918D29113E7015695191EBD72A50230004CA2F1220016AA254D1E42A955C016E49C815A604CA6B417F242439E42F785D606E2E572A942A7303554A48864AD01F39BC55964B02D32477FDBAA8A8ACCCDADF814DCAD0FC84E851B758FFD6D0DDF3F977BE7F1912A3FF06870DC92A101C52A0442257285442B82B49E22A7C84204BB5AEAA40A8DBB88110E885A059342998245757F0D024254210C44A85440AA5B232AC0C6FAA7E50369BF5DE1FD3856CBAEB7BBACB9FD22B61B71F7D8BF56306D19DC76518A2!
088F5C444120298944E64A84AA37000B21AD522194A0EE0C840E173C532EF2!
4DE07AB8
521A6AAB7685F9E0C7E568028072D743262BFA3942B60291E5B6CD29D1C49583C40802610424407125E10A95B972D7DC5C9250215182610A8444969B2B41B76882AC2691C6285D25A045C0111220B0421080505999D5524FA48450A2873464E1B76E127850898AD4A828654C8FE46FC8554A8504107A233737492897803942E8B822C981D20B40CBCD9527B9A31D4154B94895AC00E1355959113AC310769F3DCDE60AD14C77F999EEFA9EEEF21FA9123DF9109971838DE40817A494C06F254A896ABDAB6BE0FA5CB912104A427A0310C105E913E84E8AAB5C992449CA5D8F3C508AEB7A9891F253114A646508A1FB4232DF21B2654F64DDE4705B5656565C54545F74A8C8F50D55524A2E02C3D5F50DD023D51B24C0080915200433F1AB952014457049A9873C76D23A1816B31E07FD21434478A2C7D9138D1F55B1016B282B6B282AFAA9A80C4408F4251725B8DC22F03B127F10A294B17C97827B1FD448F96D6ECA49D42664CD62780EC3702AEF14F7B604912D2BD19D7E090C71646E28C35220B31581B8FC84AA36C85470C1B3560ABAF929C51A635E1CFD010D2A2B2A43AD8B160CED23641D133BAE73982D29D15447D49F2E3C4FDAA0AA89E37DF0C466C14E4262432041D48F2183EB0DE43A64C08B7EC293D7582009C21AAC761A0706BB3F277335D6B38562763FAAE9EFC!
C78D7434DE388FAF31FA2F1C0B140EA52548683530CD77A2B5370DF7A05784EC28459E1316377DF6A9E66CC3F882C84124D382110BA051E90452AC353154CC577A4A7AC684C80ACB48DE363B69264C16C16A2699CEF6CBAA5FD93B6CBCB7D20B23EC4B313D224FC8295DD99C6C2629E53CC16A287D59432E5D08E19EF3A348DF39DD90A447736F0DD72CB3A4D08CBF4B3960D414478A2FBF44DE010FD62683D3646D46F05D1234D6798E5D8B1AA63C78E61C7F01FD0318CF044738268AC54C72C130AF6BBED0116F33C8308672624B3F0DD77C3DE0DFB67E153998989C0539585A8CE6669ACC74EA460C63D11FA83DD73D845F3A47DF34F2A44966389058559594E69786465A565855DCD0C49AC3A66999512CD7430D2E306D5548D6FD34E6777799978B5583B35F0B649EBE541E33D1E024433AD9E66BEBE104299FFCC72B206CE1050846EFF9919125235ADED8F4E40710B9B7264A3AD41649964BA6B999046992D4F3C44B72D58E2BB4E694E4EDB00A1EB634AF403122388770B33774E67FB579D9CD6186B9B53A22962BE28D1EDDBC742B25E0782529DAE5F671DE55CBC781E222AEA1CABFB2C8E5166C8C9696C7F6C8212DD9AF1AE228F5BC93FD5D08839438499AD2DD4F7EC0DFDA8209A69093EF308793DED1920A89BD51375BE4327FAFCB933678E1F3FDDD2713EAAA71!
BD25A58359ED2A6DCFED3D9EFCCF6209A2C9D59AF7314B2C707A26361A0425!
93FB0DAC
E3B9FF8F870483D44627D7D48FDCEA74E387709BAAFA76515868460D38188F044D3EE65474608B3DCBDCC92A2C7C6136582997EF78B8E2EFB4F819E90900234ED0C0909A94FAC4AFCB4852E605DCF7AAF20D132E6C16F4F43890888A6DCC663EDD816CB3DE75B783221B224663965257F72BEE550221074B820792C0A0A80A4AAAAAA979DCF6B9765BD075A841FFBFB8110114A34836D6C1DF16115A227DC585B8E153AA5FDF3BF04BF2FAE02112A48BEF63F8DABD6412C5F77E16FFF951C529C5855FCF9F9E6B065D588A2A9209A7C64E3E33ED86CAA95FCA0F143F72DDDA7BB91A778FF34309AD1F18AA63B186D4604552516BEEE94E572EA1056852374ED9555EB9E4708E1F1B76B3B8122ECE5F3DAB7DECB2C0899A2B1F141474A9BBF103D5EF11B405495959AEAF47A58EA68B2B9AABE20B91A21B47CDDF3BB76ED8ADF3586510150746C714EF3D5CCCC10CB541095D9A012D93A4496C2B7DFDE94B6312D81B3F35871C1B56BFFC5028476EDEA8569C50A9369452F9074E01AF86BCB5F054F55676616CF5E891EF75D81667A4AA5271DA287B7DE139D12C4ACB0B44D09C1C9D8CEE4EA1FE3972F7F7E37C8D00A6008C2B4A28D03147DB0B30AC3CE801265864CDD4E841110D90E44F8FB429C1212D2C2523705071FAE3A5CFD632F92213C565CDA05085D320149BD568AAAD6!
16166666564DA7B1914867B691CE2CC7C045875465A66E4A0D7B3D75933838B9EAF0B555CB97EFDEBD0B4DC13846A64B2B4C5D2BDA566D3CF0727195E5D3B0C2B17C465467044478977D5AEA8E54A7EB694EA969614E9B12C494E4E264D6F2E52FBDF4D22E9CA34B9776C17409B4C8D4D57A61E3DF76565992B3AA0B0B0A2C447546408477B766A6ED4B081E4D4888774A4DCD826C9640A1BC5CFCC5BAE52FBDF3CEDE97760345CFEEDA7D09E2348BB28662EAF1BDB0F1952AACDE09F259C8B1D92AD16C47FFCFB571F0A10D369B6710CD6D7D5B42B25EDF111B1B4CE18C8E1EED3E5A882C9178F0A9E203CFBF0410BD04BE1A20DA7D69F7EE35673F5D11B4706950B0E9C28103871B8A59783E7BC08FD33AB2918068FE4364F95F7FF8C31FF689478383474D148E6F776658FC5E80A8FAE575CB81A2975E3AF0D4B5F867773D7BE9D94B0B9293D7F66E5EF4ACC9D4B30AA4A8AA3BAD302C33F18110590825B205882CFFEBDFFEEDDF765028A309A684510A27CA29332B3E412C1EBC7616AA7BA068F75BC9C9DFED7E76F7B3CFF6FEEDC2AA552B82D7F4B27A1A9B0E6CACAFEA762A0C2B0CB1E03D1FB357A2599FC2E811371110104D7BFD5942FEF06FAFED181DBD41E17038E08A125C0AD2C057DF18BC76E0D5E7215EDABD3639F97F763D8B22E8D94B97D65C5AD1A35D509C7C!
61E307F52EF16161CF649E7CD0D09469281101D1130FD1C9DF6DDBF63625C1!
74434C19
BDC8898F0DBA9E898AB320873F6DC485E8A5775E494EBE8A20DA1DF40E50B49BB262554F63E235BF8DAF3C75363EAC9075BDA0F8E4E410119EC806D299A570DFB67D6253D4A838E8C62005208A6515225FED90FDC757714BF4CE4BEBAE25FF0DE9D09A67DFD90C25DA6E8088F39F2DAC8D07FE7C3A012A39D3BB99C916C213D9344459FB36BD106C8A0A164306BBC181E2DE25D30AD187AF82277A0971B4EEC0B3CF8EA5B335BB2FAD885FD5D373ED33F6818DDF2D48480B639958994F1513D5D9E304D1EC8682CC7E7D1F7B7D6F6C7054D4C51B60A56F50A238E2A0EBD55688BE7BF5FD82F7F18406F8BCF3CEB3EF0043A0469776ADEA8D672537AF3AB0F1955712D2B29CA24CCB32EB1FA444D31DD9F8B0776E9CEA7DD36D647BD2207A58D04C1FA6866D7BC5265314452C0E1AA4848E8E3A38B0C2362504538200A25777FE88430418BDF3CE3B9B712D5AF36C2FAB97B3ECA99EE6031B379E4870CA723A673A9AF91436C9FAC78F946626209ADF1015BC1D2B365D1C4510DDA084F67306B35961A909C1371C1C5E79F5D58D562502297A67D12210A33550E7AF580591BCB60394E8BB0F839D9E6175F798BECAAC9F6CFDDF269468DE43742CEB053105942834481C44A1845EECB9187AF69FF10990CEBE3C0E9EE8C7575FB226B477DEF99745EF4081F6ECEE15EB2EAC3A5BDFD!
87301205A66BA1E1FFCC3750A0BAC353685123DFA127FA6BBC24C770884AD4134A35D89D0ECC41DB162CAC5A87E1308D18D504A540F8BF36E75FC268A7870F0CF1B5F5DFEEAFFE04D45488A56BFF3CE97CFEEDABD6BC5850B170AAA5769591BFFF6EF67839D38C12E692653E153C593ACFFDBD3DFEF8C80E80982C87217224BD6DE58070AE762E82814672044A33DD7BBDF459E48EC40B906102DAF7EFF256B8506A6088468F7AE5DF1EB2E3C55FFE22ADF751BBF3BFC49F0F5A33D2E695194B48293F75FFF84279AFFE9EC58EABE20CA6854A897492C06862E727A583D2C2764AC1D2E26FF0D205A9EBC710CA267AD0CED8AEF4CAEFAAE8705966871D527092FFAF6A79DBD48611554119EC8E620C20FF9061039ED0B324599422F52828228FD51519CA33D478F1E45100D9A0EAF4510BD7A1899EBE75F7A16A6DD684CC8BAE4AAFF5AC55A7561E3DFAAAA1A139C9C7A96755FA498AE5611D599AD418425161424566196AAD7636F8C4651BC4C9420F0D7A351E78E721262C5B81245EDAC3F809A1B5F4DFE9F8D7889B6EB25B0D5EB5ED919F21D6BDD05B0D5FF5555D5CD714A635DE75CECA77C513C7B257A5831D34164B31E7436CF219ADEFAB1DC362786245717242686142650A238948B17219BC16DD451D6A6A0E0D4D44DA04451F555AF2CC7E3FDC3C96F1D58B76ED7BA7!
57F7B2BB9E0A903F1EB20991DD818521CC28A77728A375DBC7871F03ABE4BF!
5FD4E9A8
74DFBCC8B04444F164496AA90909077E19AC9FA8C1375F1A26930487C71F4A28973D429BE3A240B41E45B5F957CC04AD1C61F0B761EC6F7A3BEF6EF0756AD3BC0BAB0EEC0C66BF5C5D59C78A7673894F31729A13D21E649202294687E42841C754166E17B6100D1B2E465A320256210A4A8D1D1514E6A6A614856FC68F060777D62C18FCB5FB562F4EAC6F77F7CFFFD570EAC7B7ED7BA03170E1C38F0EA2B21F5215FC5A7A63905F7F75F0C5D339A3C9512DD7AE410CD74179F59EF126423104D59EA63F589998561EFA1E37D548F82A33671AC31EA4061555F4F4D080EED2E4EAC4FBCBAF1551480D1F85ED4EB2E20885E4D2B280809C9E2A4A6A506F75FECEF0F0D7ECA32F929CD2D0444F312A25B96AAC4CCABEF856586D417B844698F72CE218228A326B1E912BA1B4CF9A4AAB83EB1FE479CA2E51B972F3FB0FCC03A9020747D06742819E8BB1EEF04105180A150CA5A6C1288084F346FD3197E68D8A7AAABDF7B0FD2D23296EF39A8EE01220A25A1C7D4EF109C304A7101210AD99958BDD1AA4407408B802090A203AF3EF35D48417548419853AA53563CE5627F683F65F0872AC213D91E44F064436261E17BEF15D4EF2CFC2AAD87330A52142C0E4E65052FCDA6049B5EBC860E2B531052F0DD848CB6FCC0C6E5CF1C280C29C84C0E599B0610A525502E0243A1832EC544!
75F69B41F470C70FDD590F63D364F3C72648692199608C323333DFBD1E2C168B834763631362972E0D0A8EFAE1ADEA8282E4EA6AB86E1C7346F89F0361990599D59905D56159A9ACD4B484508A1765A87FB0BB78C64A34E78DF5B8C66FAD3CE6074E536F87FBBD677238CD401100F187CCF732C126C78AC5B1E25888A0A54B299C6559AFBC054F42648614AC058E36BEFACCC68DAF5C85C7685EE6DAAB6FB128B14EF1148A576868E8202B11C3BFC53DA74BBE65995C8908881E1544337BFD2F219A44E7268990AB89909A3201A390C4CC77F7C5526281A4BD2C966F7CCF57AFA4FDEDFD6A6B00325908A38D61D50556847E2C5C56FD146B61B6532A056CF51A8A03AB78023DD8048808257AE2219A220A380B1213513683B416F25E6AAC98122B7E41ECF4EEB2EBA9D7BFFB2ECD6919CE4C21885108724899609270710ACB0ABB5A984559BA301E4A7CD021CAA06F2276CB62C60B347420FD3B106193B713CDB9942620BAEF469EE9EB7FB11D660611563D1A7A1A284A0C4B0DFB2AA43A2C01B29938E885843497D4EE6E5F9765AF2080F040161BBC1018EACCE4EAABCBB27EACBE96159F9D1D9CBA29F862FFE060A8032B04CF5DF091B7EE4EB72C13CF774640F4644334D911ADB21242BB43AA1213C32E7CB5362433318425C603AC4E6A77E367AC1FAA7F744A031D42425480!
6A3574531D56985CFDD4A727CEC65382E337C5069B42071D6E7CE91B62F543!
F8E9BAB0
094E9EF0448F3B4453A4B3497BF1C722F1BA7830EDBDCCC4FAC4C4A720A10145D783C4204541B1099CA3BEDD4F3FEDF283CBD9ACB0B0B01FAB51CAC32DF58F5959D505AF343EDD729D634A4848080EA6F4DF180C1D8C0FC1CFE1653DE976C31D3B7F9BF044F306A24922D129C88192F65E483154EC21EFA112ADFABAD8616110446C424FC2E851D675D68B2E2E2E4E9BE20F7CB731ECFDF7C360CA3AFBCAD9CF60665A302538383821C17471D081E2D0F394D700D3CBC8FE6671F1DD730C20AC4E124A34DF2112DF08BDC85A9B995990589DF9FA33998599993F382CBC1114B430489CC031994C1C0EABBBBB9B057FD0F9CE20AE3BC57338519C1F963939512814E0283E9E323838E8D073D52EDFC3237FD192254B46EC5F9EF0F9D8AFD6626D6B10E1B23F7E52AB095BDB7CE72B4CFC4296A9D2D21D966E8D2D6D7C235AAD0F1AFC01B7C81ADD469DAFC801E365788893D8011F46F46E415562E6EBEF6C0B2BAC2E6439048B831C162E0C02424CA6A8D1A82856EAD1A39FB1D2AEFFE0D2DDEDE2628AEA8AEA61A5F624380C0145E258CE2832D63D4FE530BD72040281D74064FEA2455EED1F3CF7EF8BEB171F4AFEF8576BB1B63588705CCCD8C4C766EB99AE277E156CDCA19AC7674C051136664A2C3F43EF96F58A59DB026F99D1A3DBB0EC5BA0440E3746473951BE0B4212130!
B9F494BCD4A4BDD948A207258B834884219A5503851A651D651DFA77B8E9E83E8F9ACFB5CD4C5F3BE2C8E499C0D108981B4040AAACEAE0E3073F45ECC818101E6798157A45D7EE4C0C0D2C8D0816142891E5967C79D8D8D8D2134F1F3EF7C0DCC7A6E59FC35D381E8D6D8A968C74F266AC5D28CDD53D95B3FDD8201448337FA4D09148EEFBB60880A7F4C08DEB7772F945C0E0BB3D1651032D6A8A9DF347AB12BCAD7DEBE4DD0E6DB73CED9D9D977D568D0A0387B803208B6488C2872603D75DE789E7E5EA0EF603BB7885A74CE5AB863DFF2D939C1AF369EC8E63C91151D6CAC55D9323EF3AEE8FCF26B3DA0549F30C2C37C37238E23649E701ABF9F254AE489826E50504F8738380BCAAFABD7539FD90B757B4250B6034C8011A89169F45C685B8FE99C73770F27AA87734EEBDBDC63027CC48303A162902231A2C88195DCA96B66777534B7346BF56D6D1DCEBAE66667B6FDD3CE9FFD6AE3896C0E228B15216C9C1E6CE2D61D4B6BE315CED8798CA703118EA1D571E1D1D060FED939D9C69689E1B70D56257208DAF7FAEBDB76BC7DBDB020D3695B6A2C545CA909384168727018ECF9E3C0273F704C94841EA0881305610AA5A01818A404413E0302E3C517FE48EFEA6AA36BB5DA8EDE0E6DB3B6AD4DDBDCECEBAC3DA7253CD10CABAC69BF6EA2D8DC0BD79D7466B166BDB1C!
63B34631AC67A027738340D0D3B0FBFDCAED37B8DA060E6D0D9A2F6F6F52F1!
FAEAF6F3
0173BBDE0208EDDB1EDF5D7607AFBE85BD54E9BF6C68A01A378CAC26CC008C2E10A65C1F181536BE34170825D58204C1453FFC5D0C16107F1E0F0E08D3537408A00BBD8B4FFECE7F77799BAA2DAA2DAB4BEBD00D339F8BB0A1E119EE8114134263C65089306E486EF9EE6DA7C4F3FB87942239E79CA23EA8C7B2D4B19DC29AE5F29A247DA41D59DCF58B4C42E3F3D3D3F1F2A2706CC58B46451FE887E815350D08ED75FFBDDEF5E7F6DDB6BAFBF1094E6B4E9686C509018CAFBECECA50BB383C490CF82AFFFD16B411827780527FE0727532A07CAFD739C73AB4C1487C1E1A0A0C1204A6CC2A6D8D8F8AB9F80F46857F9365F68FEEC82AFB6A747CBE9BF7265D0144528D14C209AC6A9A97E7EC2CFFAF59F1F39B267CF9E2347BEFFE6DBF53FD597354002AA3FB4FEE543870F2D5E7FE69B95A7BE5DBCFE08DCFC153D65B64CE75459F09AE2C5DFEB04035E395E1E8C7C00C78369A48F40F99D6364324798152323034C26131E95E62F1A487D61DB364008387AFDF5F7DEDD248E4D75DA0752244E881A5CBA345B1C8B725B42FC75D30F692CD62BD79DBA9D56A1935367B9B058ACA77FE08014390065099BD66DDA1B14FB6EE673C79FD6360346CDBE179ADB383D08A4CF5E74995A89CC339E2C33BAFEF2F31EFCFC54CF5AC64E6C774711F0EF8459EFA2F613ECD62D3C7BDCED91!
B2BE1AF4011B3F53F098A740DEC3BA0073C3A137DFFCF64D002269E5F7CF1D2A831C82359495D5978DB99371C30C0EA5AC7EFDB7DFBCB9F8E56F4FF9A72F59B275F5D6D58E5BC76249FE4805D3037462F51274B3753583B104646335DC5FBD289DE9DFFEF2E18686E243EB17D7837A2105C3AD7803D22EF46576FEF59BE7DE5CB9529403D26307BA931F19999F3EC2CF11E8E9462FE6482424B3480FEF3E94D3BC8D0623BFC640EF76DAF61AE8D06BFFFAFA7BFFFCFB57FFF99F3FC4C63A6D128BC1E8704287973A04C727C4270427C4A776A765BDF5A7B52CF1A098825AA9831382839D96553B5186C13205C5EE5BFE7E1868586CDAB573AD97BA5AB5ADAB7A7BB42F7637BFF8E282652E4DBE532BD15CC6F14D0FB90741FB4B8827793B76ECE7E35CB0890F6053DC394A061ACD803AA2F1361A74B038CB04A76AFED9FF8B84A1ACFED0B72BF7087246D219F9E9768C743B3B0623DDA33472A434D2C323BD1464C02372C0F9CD43E03FB0FAC5DF9EAA18F148672C6230D075517E7A247A417A7ABA1D0267098301DBBEB4C65853C12C2D658ED8D9798070303DEC60C130D92D82DBC8740415BC7B11CCC94F079D498FCC61B3EBEA043940DFD6ADF09C9D9D5D29C80D484D0D288EF1BCD1E8C51F311A9923DE911E57987C03DFDBBBCFC83718F87C636BDAEF5E033FF4BB6DAFFD!
EF0FFEF41FFFF1D1C77FCF4A4DDD4B817C969030389C1D749DD5D6665AC131!
999A7C57
9CEBF14DB8024E1BACF697830E4141F1D79D52570C82F3A6ECDD9BBA36F99F67AFBD92907656DBD9D8E4B9A2B9B1B7F9C5A6E6E69EDE1EDFEEEE6928D1A319233CDBEC63F9F9F597DD35E35DCBE88A59C68CE8DD6A695C34EE64286C7CB90D65C5F53FD51F5EBF929DC31C40F654A7CF89F448CFB7CBF7881C8984FCE02FA86056D4D5E5D4302B72E815C8C456B88F2017C2B05B041AC3647AE47BA457E47855E48036EC115478555454E4D4E5E4D4E4E4D0E16F056087901A61024574449107D0585A0A334B3D3CF2010D00267F04EE013B8B90C70163C38017D9E10402568BF23D3C803D0F58C6084A6190BDE803F05DF94888BC8C5E91DE23CC2E3EE063E47B42180C86D7B62115DAF6DAEFDE4EFBFBFFFEE8EF1F7DF4D1F534A7048028387E347B7858ECD2E2DC217AF9F0731D0228B29C7D3937065107C720EAE61804371DCFA238640F0607EFDD1456FD43FC82ABD79CD2BAAF7CB968F5A27EBF171B2FF43477BBBCD8FDB4CBD353B7133D76104D2645F79CE0F76E53EECFDB917F5624A17E096B941DFADE19FDD6198BD2D3472AD066AF1841CA9393E39543AFD3FBFBE780665480705480EFA8A0EB738C3063A474A402C8600AFC73EAD87AB6BF5EEF6FCC0185C8C9A903C8602939233975FABA9C3A3ABA5418012500082064D6308184D25220AF0678C06364A4D4C31B1!
0C36B2C8F1C3E1332D4889119699D13895255E9C8487A297A5B29D3080B30D2730C46A391AEEFD0C32D0A3D9BDF37C2A723151AF1EE5A711D440821F4AFAFBFB683F5F73F7DF0D1471F74A7A5C58AC53782834DD9C3140A4B40EFF8F4A7FAE2D38273DA8F0F9F3051707C1041416B20AD715243AF640F8B29B17B9FC972E9661D7559F65656D8E9CBCB3EFC9B5FAF366A55F78517BB7DBB7D3953B713FDC6104D37B09FD53A66BC1EC2C6CA67F39DB693BB4D7F166B278419F98E86C5ED6C48439115E02B4065FC8106B8E6A094C1F6A45BC3009A031A528136B71137B0B0F9002F80445FA7A7C39D484002CCAC078A7498C0FE9482F0D4E9EA6A6A408DE8747E458D91CEACE04312025E6061B0903AA06104B6F888574D0DBFC6683430F97C2662CBC04482D537D26797EFCDAC310032DEDEE970D70E1609EFA3EBF5FC11782D9DC91CC2F9D1EBE906BA1124A8B51517217EDF8AB67D2FECDBF73B40E877AFBD0D97A31F9C39F3FF7DB0C0293516399F604EF6407FB06FFF80F3E19DC5C5C7DB04F6C555D7A20607B3AF380C43DD7F251BE48892901AEA00140589639F7FE683F5DF2E30253865A5157ED13BF4E595A8DE4B3DDDDA9E5E9396D533534FF418575DE3B6C6DAE76099A05B6366D932D68E8C4F636D7498F9F0CA0A109C5226A287EE0FF8E8EBE8483DE87575FE700!
FF0A9E1C3464FDF9CEE5D039BB50EE6D081083AFB261B9EAEF3835B03884BB!
A871D2CA
3A606128E07928A74B03ECCD21A5858FAEA251E004C4D5D8E01DEE9596744566664A406DE4C07A86A8C06C428A42084D0488DA1A6AF8FD9D757B3D92EBF0F3EDADB637329132CB2274C7CEF52A6671D1DD18716E4E5ED3140E77B19F9508D199803DECCF39E0092C1C0ECE3F3FBBCE9ABDE7EE18517162E44086D7B0D6E77B03EFA3FFFF11FEFC6C78A831C28148E29FBFCC504D6A5A1B60F8AAB76B6083A7C930F9FE00C0F662357845A8F408E2809ACD0EC2BC3C30E83E2BDFB9EF9DAF54DFB51D6F5AC67C2BE6A32F59B560C0E9A4C2B7A7AA04E9BA9277A6C4BF631056A80B20935E24269535C545F7FF8F05FFFFAE673DF1C7FF3CD438B0F1737E0BEA778677D3DDCD6EF3CF4D7957BD8E04340147200205013BA5E57C7063AC0C7D27179A9CB816D0B06D560F0F3AB6BBDD929DA52C7BE5967A0B78AD87E6CF8ED1BEAEA80146008F0296596320D08BB1C7E4D0D28C34DDDCD9B37457AD8E6FAD61A8F1A3A1DCAA51A500FD01BFE88C708BF860FE23462C0C3D393C9671A3CC744049E1AF1DE0CF6D993DDDA576380BB9BBD4BFB408F0C7D7D1ECC520FF83E7A4FE6109FEED9C534F61BBBE85D9E6CBA71C8E8A96F330EF5795FE11B2E19F9AC589CA1850B5F0057F4AFC818ED38FA7F2D7B3A750740142436C5870E0828C1ACFE5081F6C471FB53DA96E34FB72C68731844!
0C2D057206B38122AB120D015141BBF73AFDC7FADFDB9F087B66DBBEACE4C6B6FEDE9EAE9E0B3DBE6D9C28D313AF44E35F0CC080DAFA94BF1DD81A287A2A724AC1D168505DFD2F8ED6589DCF1480EBF5AAF0C09D0DF8D3F448D4BA52A7BFE97C13B9687A0E921F5C68EA4068A06E861CD1AAF7D4EBD97E9DECBAD656766B5D9D675D2B1B404232846AA39A3AD018D8AE7DE09081A89BAD37E145401FBBCE50C31675D619D937753A3F581C88448DB1AE0D2A6F3A9006EFF50406EB602E2AA300A256484388263E0E151F4706E61B98A8D8F2F61ED9BC79B337BFB5D560B8D96AA0D7190D23DE7CE310DFD84FC7D359FF1073A08FD90FF96CB3376447E029F5858556868022E0E75F5F7B7BC76B09941BE2846060884289E70C787550C409FD836D1D2DF6CDC73FB3FFD4DEFED3DE6107B0DBD9701D862C3648E1A40E5D71C81E18BEE2F06550ECF3DBB23E5AE6F4CCF27D2FC5A6159EFB52DBDDB6EAC59E5E0EA767FA4A74C77B588F0988DDA9856EA3E3F6E1035930F4E05E736B6D9DC550EB0CF22098B56642FB0B8C0F1D86D9B7EF8E231E1F063E3E9AE2165E6F596F273A67D47862419EA6A17EFD9E3A0FBBAD1AD4F0B2D5310F8AE0687800931D637534CC43458EDD8080EDECDFA1DBA36777F80BFC3B9CD939023434C65F60E4D3D9A0296049EBF49D3A3D5BC7068DF1D3!
B5B2F5107E3A746DD5B7DED4C15C40A7B5CEEFE64DBF9B404E69A95D7A6929!
70545A83
DFEB8344075A0599ADB50E04E4A627BCAC135EBEA513E0F383A407B7ADC61A76AB815903C4F8E96FFA1940D1F4008F1E505A013A042AC4F4C69327C895C766436BDF08628ADFAA038932E8FDB474BED1D34F5FE7E909D6876EE8A21B86F8FDFCAEB6566D1B7FF395BEBE7ECFA1CD4B0D5D6B86FAFAFC762C1C672808AE3B5EDBF1F66B3B768C2ECCBEB1571C94ED104C615D0C3D4FC721123C575FFFA9B3AFF38943878F473938801B420C655F41E92C3E75387B1841940D25BFF8F9E79F79E6D56DCFEF15BF109BF655E8250EEAAD6599FA2F5D99713B11760BDFFE7707909B317C036396DB6320603FAB8DEEEE19701B1B1FF772E7D66C85069651651DBF756BE2902D6C625F0376A7CBC0DAF0666E38F44D3BBBA36E249DB11AF839B87AC912CD6AD41603F8A05B08065CEC985E02F69EF623DFAC5C79447773CF1E1DDB5FA067B3F7EC71BE09F7D902410E14376C880E1D5BAFD3E944223F5DA7CE4F0F22045B17F0F2D389E075AD9E9D20565B44A2CB0050291E7676A83EB72B2DCD47F798A05190D13C3CEC989E3508085D5DAB5FEB4DD11636586558881FBAB4D281863A448B9EEDE97713118424C8CF4F0B90C09D2E20064002BFCC677A82530220D906CF21A6B7DD10BC09FF467A20CF13A843CB686D6DF36CD3EABB8C86B6D636BD96DDCCEE620EB56A5B5B7B7D53C71!
85A845314B470C71F76ECD891BD307BA93821280818E2F4849E17440D06B1B43D2D3BEB8B8B4FB5890EEDACDFC91946860881333C1C3A183A98CA42380D0F005588A27DFB963FBF6FEF0B41E2A017C2D6B29A7B7A383D3D26534FD4CC94684C1E6E8D3910B4F9C71199380C615CB76EDDDD3D69CCF6620DE3F7EF9719C74B6EAB03B65807E5343460584319189DB2C32FAFFF5EE40F3EA52E076FD2430D74A8E1CF0EFD65A096B8ADD1AB51DB0A94C11E2360546A6EB6AF3CB2F294CEB9BD5DB4678FE848FB1191E89408EEE87447D8CE3A1DC248D4A2D3353BEB9A44EDED2DEC665D53336CA836D81E7AADAE89DDDCC9EE14358A448823BA1E5298B1C60EC90EC0E361C7007B528A3EDD8E6960DFACC901F76DB7C803B406CC30386150136F6FF0469E48E5408A40CA1095A03C6C3600E0095B1DCD41490C80F0F4EEC39B07E9609F5159062E1BAE9E90EF9AD95AFA10BD8DDED5DFA5D7B6817346F840AA355CEAA2B7B5797679B66A9B3BB56D06FE15EFCD570CC0509B76CB36C4CE583243E1B070C7EB62C490C3686C90C30DF0421CAFF35126045154131467C59F081AEBC12AFA3A0CE3A96C78783014AE9454975004D4C0F040284ED1DE7DFB9E7F018DCF0EDA54BDCCB7A7A7BBBBA7078CD14CDB89EEB4F09B278C5FB8D32B3DDE1771A7B711EC6D0376679883B9A1FEF0E!
297CFFCE59B373F3D545F8FBA91AAB0E2E29D8777D6973560D89DFE0678575!
9F14EB81
4D72F5E7FD33F074A5E4006B5B8ADCE735C0DBA03B667096C3B3B0FE0084A5EC692D58C743413CC503A2A8F214119E96C3039400FE043CF01E96177B091D000472D221DE2075802ACDAED1B1BED9B448DA7E0DAA2756E696ED23583147542FA6A12E93A454DCE28BF811AF13D22A1A462823346ED831EA5E81B947AD82D015A6F8A6E82C7418D371E1E505C79F78D6CE6D77802377E9E9E7E9E48CE00244F4FF80B73D8C86101A82867823C21A8901E81470795E233FBE8E8AE11396723DFA0071BA6032CDAFCB45A604E0B7F50FAD3032ADA5681A14BABEDD5B6761957B4B5B23DC116F5199B21796A5D362D4486685C89162ECC5EE8E020C60DB34382D8C1216870345E3C3808F300A6AEB63FD6D7FFA943DBFC69FDCEBF4739643B0C0F0E42FE1A1E1C46E9CCE5E2B0C3952BA1C3035EFDA8113B2876D35E6069F0469038ABDAA59BD5EDCB319958AC19B513FDBC17101F9477579E268CAD826B43D5E1337BE89191E98BF223E96C9DB3AE434FF78A4CCFCF8F444DB18B50B761A43107EFEE49472DFB9115397410873D3A11185AF851A7DB79E433D2D3972C418C2CB163E0690AF525ACC605C88E864F76E07B188BF019E9E963EDBF0323917C3D7C9ABE83CD86ECD40EE4B4889CDB9DD9CE227B917DBBA81D31D4A26BB717C1B76AB1D7B35B44F6A74E9F686AB1B76F693F2D!
12413283ECA6852DAE038874ED8D9D7E6C340F6AF03E28A1402170E95BA459520AD5189001CA5103528468F1BBC9F664E6334160608EDFCD2D9D6C112CAC59D404E8742088B4464FCF2E444DABD613D2186438C85250ED01417440C6D3C884CFE0A33E0B03BC92EFA93768B55D9E6DCD4DCD5DBD5A2D084FAFA81965314FCFB6B6152B7A9B2F683B45179A9BDBF86BFAFB86F86BBADA56345F48058416DE91A1A0A0312DCA4610C5C622573D181F1B84E68022F5467545357FD6E67B4A7BEEE9A6669303D2A1C8012F816020DB01ECB76F5BA8C3F095818141AFF3FD839008836283C49460C4D3DEC2B59F74B33EE3403E5B336D4F84DD4D69D8DDFD8E30D4B9545F5FB4F3101447652020C53B173FF7CDA93D02667E3EDAF0A893D923323D3D1FEEA0DE03668EA0AEC3D9794F873FDD989373DEAB228759E19503A5128E13DE309BCE586407851352967C3B44086CB1F474FC1E4811EA3902E50117843F0596A41412D78807D812B87AA03CD6CF370AD03603D9815445F712205703E4D89F5A692F6A0166742DED2B4FB58007A283DB766E11891AED1B452B1B1BDB45203C2853407D8E0C36522EAB28C1B636F251E30ED31B481D818F82A45677B3F32654F8C07B7E7E29D45175E802F51ADFD313DDE51BC059FB41E681D0C2029B7540265B8FDB6C2DB8754F1024B0D990D2C0!
E1406643694D0FC98C8F6A353ADFBB0F9449DF6AE86AEDED6DEBF5E46FF6FE!
120CF350
9F1601E4B902C447EBD7FDE205BF5EED0AA361CD97FCECCD57D618DADA0CDEACBDB81F1AB3D58B168A1DC6070E2DCDCE8EA5DCA09828A32EC141D6B6A07816ABA7A70DFCF1F56E566F0FEB52F6B9CF86B305FFF87A7DEEEF9D0786C5A9F01C64B881D001AF8BE7431D821C502AA40CA2D4F6C2A6EAAF5851DA9E4B83A64BD36F271ACB4F6598B9FED0FA6FDFFCEBFA6FBF3FE53FE0857749AF5E1D0DB4440E30732A505F12528548265DD09133E001E4541873E8022F345C2AC72B2792995327A8D3C31644BD035055E740C19B93539193C37487ACE551510A3E076953291AD4905E8A3A8C46F04E01BCF9BF26DDC3EA6851D440D08D9049BCA14462F2511B5FA447241F4ADE3AD872BA2D90CB4070569EB2B70782DAD1B0601DC84E8BB35E2FA03B3BEB409C5A80AC53E8898EF61698A11708A024BF89B44874538724AB53D7B4E5C52DA24E5480233AC01CF3E15BDC44855A1DDECF00D6D8D0D7C7044FC3ECEBEBF3F6E64322022A8C235041C1B3FA0E6D0750E40C483A3B37B39D3B9B2F347536FB75BED8D9D4D9D6DBCA070BC44405D96658699170CF0FCF6F50D7C3B2FAE0132F19FAD7782F5D9A3F34086A73E95217D463FD9EDA663FC871BD6D5DFD6BD618FAFB5BDB56685B9B9BFD7ABBBC97F605E355FD5D3FB41078191A5EBA742940340C96689042F13D0B657EF6150!
78A433040D41BC5498DDF140F9754CA95A8BF3F1D75E2D43F7EFABD7CFD91610A8BA37D9A029E287420D4EB7C68B643361AE6889A001045A96B97B1BA5DBA57B1565995C872DB3C154320323F2DFEFDE7473C729C4790C644222206F2199103395E5E5E39CEFE02E0018A67301BEC3A41C71EBDBF80EE2F60B381132F26D0611C491F410DBD1546AF110F0FB02D9070F4F073DF73938D3A9B6A46507F01F0861A8B99D68E4B7ACEC848C5486429D3C88762A9EE3CEA71F446820305354C9BED001D0FB09F50151BF5237C787664C41B9281116D5B11945260886F6A5B4EE01CB5B4B4E85A4075103B0201000E40415A43AF71F60359D221E9D2894E746ED1F9758204F9F941650519AA73CB96A6CECE4ED00B4FBF4E3FBF2DA89263B7D60142AD7560592005415A82E23CBF0FB29DF766A66104BEAEF7223B3BEF11A6014A7A01BD0BF7E9CE4D106C7ADB1630439D9DAD9E5D862E7E9F01201AB1B3CB47DDAF9BE1D7019AB6798C46BE277F040833AC59C3BF04F05CEA85A2ABB5152C746BD71A3E14F56D60AC6119C093567BA18D0F49B20DF7D8BDDA7D13095AB874E94287ECA15030C608A258948E28DDAC844DC14183F1F10EE2F82853D4454E3C446A2A2B7E6828DBF75DCEB2EBCB76FEF71B5FBB0A6EB0584F2F380ACE7AE8FCD3DDACAE81CF58C1C11428F7878791B77E6!
1D33F97817CF5B25E5C508C9A7E704B83EF6862BE85EFB08FEEE1F3A05A2A3!
EF4E6910
E014A1FE06804E9E79D055E3902E73D2D2D475AF61CB1FFFE1FFFF8FE0804DC87D883B60A6C1CF8510330036864941E6F84015FC4A683E1A50B60BE570E1B5914E44F5A99CC1C36608338F360324BD373D8FABA3A0333078A21D4A007814A727C21809D1713EADE3E54021BFA809848EF7C6F3E6A1D36D051B6818AC868849AA5156A2A00C10FB06814B5AF043542AC803B6A6277E8D9F622761B1B89145C45F65B10452873417A6B63A3F2DE7A450515F22CB0C5759DADBD7E7A040B2E476CBC73A1D50F7D805FE7163F600B9E425F8A0F4294EFDD87CB26B06D1CF11EE9832A0CACB0D60FD884F7EB3D3BF185180CC0DCE6CDDE205C2881F199DE783B11C890AEB3137D165BD4D9894CB4166681745D80B7B5B5F6B6B5C2B3467E3FFCBB5D06AD5F9B5F132C132DADADB3D5CF93DFE5B7E5C395AF5C66DDA168294C0B97A2AD1E3A309C1D994D8915079938A32EA9ACD44D0BB359F10B299CD0C1A121CEAA54166B55EA2ACEF030C7E57A54BF89F554D1D76FB87E3FB8299E75B619EAB4A1A82F5CCE72863E780B0DCD1E86E5398094BD10B4A9F0AC4BD385AE350BCAEE0E071EAFAE8AFFFB9BDF2FFEFACCB71F9F79F3F3236C8117E4162FAF3D473EFFC73F8012FB539F7F7EEAD4A9CF4FC00DE48953F6ED47EC4F9D3AE2DCDE827EECC0066C71B0240236FCD4A1706ED28197!
D5B18D91235E48FCE9CC212FB86D439B4D64AFEBA08F806C807418AD198B49BF3982BAA5E9352823B1D950F5E80CDE4BE14502A311166C1C30E8DBAC5DA27D6071FB468C06E61092294F3ADBD3D8875A6A81A0E6E6E6A6266D7353637BE3E5532756B637B1057A9D962DC2EDBDAE19D0B26F477E1BBE192026626B011B6D2B5B0BC2824A70109F4E2B41080FB0277C3430476B00AB0C9B18F86A86D9F43E5498B7824EA18B688B9F27DEE4D3D64AA7038A4D5B44CDECE6CE2DF63A364201E1A3C3D394B613572ED8E2205E3597F890B560B1F071788B117FB39D77FE88014A392DEEEED96D4626A8207C5CAB1FC80CD827800A7D83CEF64EDD960F2FB361D6962D5B2EFFBF1F5E6E6F85BF2B2FEBC023AD6AED8E9D48110E51E4F095ECC8E1E0D8D81BC1949EB4E034A74D833D5F7CE5D2F859779BE912CB291ED7A2F8A1E1EEAFBAA3F297FA867DF07F3E3FF28F50CA1A71BC0BEB93539FB97C91B5CCE5E8DAB5DB76434E1B76C095081DA1E6EAD9A5D9FDBD0B1A265456A821B86CB1BDBF00C43E47D0D1B2A7658FB3F391EFFFF2F1FAC58B3FFEF8CC736FBEF9F9A913A75A103D630481DB0074F6B4A387DFAFFCFC9B13DF9C821F7EFBCA952B4FB483DB3805DB4A6FC47F97234CBE97D1789EEE6584D249A0A70F8D78C18CF34C7047A81F9C691CF160EAF523E08098205CA0!
3AFCFC25F946648C51C50E994FD734A6476DF0DB35B4F14175601A02050223!
EC6904B4
8C500F378A50DA68021D6A6A84E21D6D4CB0D2509F899A5A20A700386CBDAEFD94087C119E98C03537FB41CDECDC8A2AB94611980DD850B0B5FA0D46F8C17B1A60FB899A209BB576413AD3F9356FE9445E6BCB16A8DC9A51490EDB16F29F0824A9F302A8C796CB90FDE0A7831774409308040869D916F4D44A781F02D40F991EF0CFB8B6B582CB321A3C9100C2F7F1EB1ABA32D02FA01B9B9B4146E1BF3118BABAA054686B6D166D4172E4D9D9B4658B5F332213CC36D00DC266ECEB33D0D1F7F633300DBD9DDAB6E6A3D6CA3E1B67682940943D0020DD488845FB225E488B8D3FBBEC930F0A76D62F3E7EFC6CF3D1EEB4F855AB58608F8642CF7EF543547EE4AAEB3F64BEFBF9E7174D9C84F857B2D6FEE7E93F678684141486392504A1316BD90E41686FFE17825233BBFB7BDB56A17476B705A8F8D0D7A02BFF38F3F59BBFFFF6CCD71FFFFECCEFFFF2FD37C7CF7CF0F15FBF3DF3DCE747EC4F9CF8FC7BE0E508C0E30C750DFCB16F3902BFF09623C0CBF7F6F6B891D5E16AA43F6F041303B818BD20C3B0C1BB42DD0C7868E1D90E5C4CDA04B051917B1589E0E52374C877606CBC8C025029487BA01CC84BE85B75EDF03C6C45BD918E271AC8546C100ED46807EB1FD552B0383E1DEA205D2B5BE70782A265835140CD2B7A2D181F76472BFA46CEA041CE9083C033AF3CB5458!
4529908B500A066C6469168E5CACB4DB074B61FEA2BD322705077875EDFE50D3665C84087EC34C4F4D41A3A75B035DB2F9FB88CA2BD0967044767CB1611D2A426F877C088C3ABDADB2FC382D9D6F40806CB48D7821184226C056A1202678DBA5BDBA000847FC54F878670B4EAFCBA6015C1976D76EEA2777509D07F00DC74192E19B2F9E8016ADC36F0C131F52D5A845A4AEC16E1E3D5F2172DF2EEF30643B5347F295FDBEB7961CBD1202442D9D69B6C2B44C390CDC4C1099CB369C11C56F7D35F24EFFCE9E346DFE6736D3D3DA8C1A9C7D4F8E9E1AB593F74E5479EBBBEAC3A59F0D9BBCB5CBABB596797659D5D901C92995958E8148BF7AD218A50EC2DACEEE5F4F60F2E186B3C4683BFFF02CEE6C85FCE7C7DE62F27FEF2970FDE3C73E62FC73F3EF3C173678E43EAB2EF40C81C69713E2FE8801A1D110433F09406654D0B3B6760C0E8E575DE4B00A508484D9B80DD26A00F0DA14C6510E8CF836CC0DAD175B4428E632325EAC0AB6878232AC6010FFD294412DBB9596FECEFF732D287041DCDCE7A58A51DB0825B8D743F3A20A2F7D381B56845BF427483CC2EA40FE46E91A674B2757047DBDAA16D866DB9F274631300D7D8B272A57D8BE8D4691192C7F6F653EDF0B71DF7488827677893CE4F4FEFA237FBB1113C6CA46190D9D84059131287D3A82940DFAC830ABD0D3!
22ABD8D8E70D5B7465EF118D28376ADBCFC22E0D68A776B004E22486DA03E5!
07EB1E94
64FB6BE0B7E0AF096BEFC45F991FC21E6101D996350AE2D8D971178ED8D7EF0615A50CDF6E666FBD35B742D8DA73F3C71AAC9BEB1117E964DCD2D4DCD901B4F9F3EB152B4F2C30F4F9F3871BA51BB791118C135F9DE4BED367FB979E9A245D99EAB5A575C5A02CEFE522B24CA179B56F47B4651126E201942ADD450DB03400303C343A360898239F17F3A1B7FD6C5FE83AF92772E3EEE9BBE343232FFFC3981E0BCD7B07D72F2D565D7A32207B4D7975DFD38EAB3C22F3E039ACF5ECD0ABB7A353324332BCC25013524395C19C6A528766DC1D397D0D8DA050D27AB8A0F2D5E7CE6C8A9239FFFE5A3AF3F3E73FC9BE31F2FFEF8CCC7C7CF1C07F303B58D33FD3C90E325706E71EE109C17003F4FA37CF6394A68E083442DCEA02D6836DC7716D1055AF8D745A266E74E7020CE5AF8FD821BD27780F3416E4700C5D9E6C82B91FCF35D74E3C0C880371370832C0729CBB9198A25580494C3CD4D50CCB4E8B46D8236D4E708C8B02FC35682F401B616C861FBE1CDBC9E569FE009CBF53440A9B705A9006C8FCB8D8D4D4DA22D4DF89E9AEC964E11A455A8CA809A16246AA82512EF5F85409D63F01DE97EA07A900F74008BA87D4B8B4EC407DD804700E7CA139745A2CBA099505CD18D7A8127D02F30EA0D7C2F3DF251788718581E3C33B5A286A12EF066E08CFC9A81544FD44AA483!
F4A66B4214FFDFFFCF872B3F3C0D5F72CBE9CB8DA2C6CB8D4DF02D5BB5B06C98874CC0871F9E380DB7C78F9F3E711A58FAE4C4E90F8FFFF9F89FFFFC67F80B143536F9F5F6AD59E1D906090C156E86DE15FD7D76AB572FEDEA5BE1071977453FD46ACE7E4F73509BA20364B2A5783ECB0663EDE57531212136E8C6A5DE8FCE5E485BF6E9CBC7937F2AF8D4198D02CF3FEFDCD121100CD81FEF5EF64377547AE43997B02F8ED33F5BFBC5D9CBF6BE67BFC8FAE1BBEA8290F7B2CEB282BF1C46FD2183D9A0430B9D42DEEAEDFDFF997ABF9836F2755BB0149D420A22B9406221DC9690362848178CD35C299710DE123FA03E52F2D03A326A2984ABCC743A524B39A1B5A596BAB51FE6E93EB4CE6476B21F2651F79D872A1B952B54CA50955439D8D801C738D818B0212647BDE94EB2738EB6CE4C4EA299BE7D5F66ADAF9CDEB700FFB7B1EBB76A7DEBFBEB6A77AD57D9C166DC35547DE7DFF51DF5AEA1EB94CC3B064141908077089588E765F3592FEB69CBFACE4E2088A0A3F1CF3D351FA2BB1C1A01887A62301B0E0F9F111C4D1E1681591EA6387940C2CFCA0F86EB504730F258903A144EA967C4C3714EE34559BB5ACC15D963990B411E938B84EB811930F6918153A7EA2225582101F78CC9A6FEFAB13D28861E7F1DB6146A05B29A6CB402270D1ABC04ED75F3F09800B844F7!
8EA928BE27AA79C82BA26870751D226784EAC98AA6A33072F0DB549A239EC3!
E8F5AC6E
AE7A5077F9A29F574D683D5D8B16A6359D949687D406EFAC8C835F7A448AD364C2DCE1E9EBAC3902700B7AF471E667BDA04F477BB6BF374DF3005081A59BD39796746D29B534BDA4A5B5A72902C6744C6D29A9E849DDB455F091A92DF04E5CC5663B31D6C93BE36B87476FBE2CD5564773E333FEE8FEEEECEC4069A5E1D7D6E71A3C846722974E9FF9BBE3BFFC2234449B36303939D46C4EB02EF652B76E95CFDFF9FBBFE8A9F9C462E802B69B5F601D8BE12135A3BFF8BC1CBF70217772F8FCE266F6D5305459A5EFF3E1CF87BFFAEAEAB9731BDD97762727B777779F1F3F7EE6F4C4279FBF726BB5B1F8A8024F1DBAC6F0787ED723BFE0577FA2EB84091947CD866295A26F783157556DD3A617161383060C858A21CF520DCB0BA93857AD10180466C0F73D41909FAB8389B6218A06577BBC39881BAAA2D5500F8F7298915597D64F74F32A553395526EB547BC3AC7854DB1A82225F8069F7AB044455A1A5CDBDB3AF512BE316BFD4A83A5FE67103244C3F6D68F7BF5FADEB1DD1FEB393FEF421DF9920AEB7976786A13C801649C11C61BFCCE3A447D8E252039582D18A5F5D038CC100C518F3EE28E44810FFD31FC3A9CE23216DFC00DD3FA813E3D8DEBB0888FD33CA75E5F87323A38A02C3A88FE359DFEEBF74B51B3E0303346D7CF1A2FC008E6573B7B54B81A3D9D79DDEA0!
1D7994E0F343C290A06B7E0B9237A3A155521FD7DD7B4011CE0068CA42F690ABC03AF6CE966C48C38965A0EB9F5151C1C39376FCE39057A1173EE9C8907CDB8E436F3CB75872C1C39FD0F00D135297495EDF9E4E6D0667CE2F4998EDE5E375BDDB873E7EF4FE811438D0D5DD8A6390B15614CB6D57B5F77BD25882A7DC3576F75665FBDB00B5EEEEDF9E1736FCE7D75EEF37756E4224034C9BCDAF10EBCD8A5EFC61AF1D1FD7D0556EA2EC8E8D1BFEFEC2CE3FC89261B34503160222F62D996EA642BC0851B2FC55431648617AA8400361D27A05FBDA0FAA122F64A11AA101F31E4E3B7E843E16C421DFA79E0A63007AAF1C13C6000E8D79E12CC0AF0D2F3EC196BCD9FF5FFEE474808D81408A435DA9B676C85D9FBF1C7C3975BFD83A57D22674D3A19EAF5B5DC8ABFE232F6C690DD6ACEC73F1E2C3D9BFAF1DA8FF5D2B3FA5E7FA95EC7CDA5522E07528339A1AAEEA19796EF5909979E6DE6FC1E3F0C4815710EB70D32F8D92C93EDF9F5D5633E2577A180C78EC0897318661A51A35153C70DF835A22312A0A4C2034F450B07D02A8FBF5FFA6B748E701F1C3C76B80637CAED01BF5974EB8A107AAB9BEC6C36B89F40D3738E63CDB90EA0B0565F75A2408B994E47CDF4E3B49ED695A862CA8F11711C1517745CB6CAAEEB64FD0ABBDF73AE872B60799CE128F557FCDC5A0E34D!
858A98DAFEC9D9A3A3CDCCB95BB01A2E3B0634CC95FB8C02CFC76385CE9FDE!
4F4F1E39
3ADEE58CBBE71EBEF4F2CDEF5BCE205015127E8201C1E2ADCFB7A3E65C707B673EF861310D6AF5E3D4C65B4F32F3EFFEEA7DB57FF7B5FD5ECAB06189A7C5E27D79D79DB50FC717F5FD979B223660CFED5CE0E39495547221E857381462B5FC9C5E12654FD58AE02A2849556D548D6B3F1632886B24CEB07F7ACB809670BEF63F359BCB3DEE94324F638236E6ED57574134A157AA4138B57C27AAA54B4A19530ED1BF004370BC605CA21F43F70E1D885DF1D81DBF1BBD99BBFC3CFCD23376F0ECC1E9E1A38757360EB90B9A3818159DCB03FC88287B53DD63D7436F23E8C20B88DBB747CC4A45B6C810AB18B01D87A9D51674A76FCAE63F52D086EC86B93048453CBA459A10A817756482F3D3E2808D5D04E8D700F44E17262F1A3067E8594F402F9098494360A92CD651887B9D2B5D24A6E25D7E9E409BB82898799232C4C6229C14841C77F1D09AD3EFBB1B4EAF6C8F20B6538FEA0EF361C0839771DF0320FE64CC3326CDA2E0BD483A3D77166AC4823EBB83052F885E283E48E5A1E3F050E60B380475AA6E5C217F51DB8FF805D32DD0705FD77B464179E0F6D134293439B9E7AF17F3F73EDEF762700A2D8C357BF7EFD1AE6E72E5074E1BF0C7D0B9302D9AB26BA4EDC4B862F6C57FAFEED5526EEBC7AD59548CCBF1E1E3ED705DFEC4ADF9BB7BDCF27F79E4F0E4D36591F79E6!
CC95BADF7FEAE6470A8848353CC60B550208E60BDAC6135B06084130FBA1881A89A89E0F7164AB5903D801787037B0079E725427E47B6E8E0073DD7009F4830BC5DC662E0CF0F9A1FC78110E7727051114B3BFDAB9C9A07267E72634F6B1EDED63CF3A3BBFE8FFDD91A08CECA323370F7FBCF0E3D0DE31289DFEFEBD1F4FFD6E7BEFC7BD29482888DE066CC45C1408C9E506A95B5DECF83989A038D6089C18982EC7982B88A6762CA7A7B496B3D251831EBC05005874BF8DA849EE040E206EAC9EB04FDBF438BDF4F3CF4FBFFFFEFB9F538FA797A653DFF3E7F5EBEBD7AF7F3FFDF3F7A99F33389BFEFEE769DC078030514B4E63CF606E154E196B7A56D69EADADF4ACCF8C17F28324DBD575C688E0BF433E450FD4B9429EF5017986201D868DAC7542C6EFFFF1B03F373EDEF057A0B20F0ECC023C310340013A0CA0052082F69E01C8D2D6816946BF0457691AA80B6E9A41A4993AC4F9CC9C35336EC2A2352C6B9D96ADFC0FA739C4EAF9B5810BCF373787802238CE9EDD3BD171FCF9FBDE72A815DFF8AEAB2BE9D1172A6E5F18A22A81B01E32529185F9B7A50B60A273E7B4785FD7EDABF389F9F9DBDF7D75F5F6575F9D3BFFC7F2EEF3BDC9C97ABDF59EC146D8B38FE11D7EF47B45DC74069D6D9E809568A4F84E75B960E8866DAB216822130708481614651BCBCB7AF2BE1E!
897859D58B8C381E0E9888E786423062789AA5FAB90ACC58D175FD70BD1367!
C5551FBA
B6C70DF5AC86E9A60145A567DB378F7E74F3E6471FFDFEF7BFFF5F3EFAE8E8CD632C9F09121052FCE38DA8F9D567E0EB714A237F3C84231DF4B2126230C6A5C7B53A18CE154CEC69D71D77701B2CE98AEBB83D3024561EFC82F500E144F961F4EF1F17547848FAB4B634AD69DFA7E0F2645EFFF3D34C06F0997E3CFD33E50FB68374F4F1F7D3D8403607C00B10108D8EACFE78F3C7B57067E7CAEAB341C83BF85EAB2B2EB874D55F1DF4D71BE32B9D6B92CDE8DF92918603FDB94EB86DD064F009D68ED557D755868CE03A160A107958FB3967DD677068AF3F37385887951EEDA45D5A83DF35081BEC52593266EAFAEBE3B5DC60CD6FACACE4464B83B515DE97CFCE116936FFE089AE37E0CAD45672FB60B5EA58AC16AF41419F91C43DE143BF6CA8D9E9D9EF273A3A3A7A63113F5EBFF8F9B4D287D5056B64F377B1A6117846613BB9B130FCAEF9BBC3DCBBCFDF9C2F96DF5EE9EB2BF7BDBB7CF9CA70ACDAFD2E59AD3FDFAE37374BCD3AC455C72F674E9F19A8EE0D34220A8C98AD7AD9C85D9B927A87625A0FC063E016C386F12527116ABC647B804E0494E485E29B9562A5E8640195527DD387F8CE460C13571DE0C975231630066041488620958BAB15B051A973054EFEDEB1BD630387C7F686869E95C4717AB6D7DFD9BF0D0376E1D8F6B1ED1FAFFDEEC2E1EF2E6CD73B7B1!
C981DB0FA881BA67D724C13D851A11574ADC0488A49D94108E12ECB3920C33C7D9D79FA34B394E6E9EBEBAF5FFF9C01A1FC0C56C16FE6FB9F334BA9D4745A876CC61FCEA314D105F3A00055ED03DA9DD05DCFF64EDD9CADAF3D3BB6B596634605BACB5F5971E6D6F323F9D571584F966EACAE743238C41C89144AAFC33F5B3F885AD04816798A0EEA1C14937EE0CCD1CD3B98A3D4B2E644871FAC8FAF1FACFBEB0773EEE0289C86D19575789DC052CF3AA3A42B80D2543F1CF8D2E8206135BAB6DF3FBAB6B6BFC6F47DAE54DF2F954A555AEC8633E3377002FA69FF598D99C8CCE54BEF277E392E79FB6D9833D0D0E66648CDBE073DD55B17ED62BC55B5135DEAF4D58D6E3F8717F2CB91F206AC68C42EBF3DFFB65CDC8C7D79FEEAED6A47074B64274EC30276B7E2EF63D6D0361014DF6C4DEE32F0BDDBC198755F7F7F4A5177847F969797B5E51D43B1C1333BD43DB46C201C3AF2469B9454F1D6C855F87FA158B8E265C3F162AE12F2E3A55CF3595C2244C55CCC713C27EBA8AA4BCB0633881F58B2584F11EE7B110B054BB6BA2A21C7D51EA7C797743AC3043CF0C9E4C608FE1DDC9391E2AA6758516D09E43D42F10205E33916A48C0A26F2E03A83F255CA1AD27A3E0F073DBD948677641E50BEC268C0C333A09CD743F9BC78EE10C550FE3E88B1E8E6F37E31D7595A659A2!
C2F814CE87A78EC3DF0D45721723A71ECAF768EE683A0F47850CBBA766C10D!
8814DCAA
F749EFAB1FF59E918DBBC8E0DAEAFBB2B2BAB6B781AD4B9C435E9C0C14F339923615512DD7F5C181F61AA63705C5262E3E339389DE34C85487E8DC1AFFEADAD4378EC147FB3875BFDFDFB6BFBFBFD6B535BFD535B5B5BF89B1DB879F4E651DC7FF8F2E5CBC3DDA9D268AEEA023D0D1C6B33801390D4071EFAE597EDC9E7424584D1E466C80B572E0259FBADEEBE62B8F5BCF4F0950210F596AA6E8CD5D217CB06347497AE27FED8D78A37DEBD38FB69AC0338E9986C4D4C4CBC8BB572BD9612AE148B9570B1B9DBEAD83D73FCCCEE2FA74F7FD267D53405DAD8D09777740320521802DA9113CAEC65B86B460A08DAD1B49498B71DC38B188A925CDE5196776C105224E2661DE8405D336DF8A4B6691B9E9BC56D0E59087A0926A6886583B2CAC3AAE572E1A2F84A829B7CBEC86A1B778405AA06A90598B061EF6D5D4B2B38F34030AE6719D0A50644801DD5658375D2A6531ACED5900781C05A682A4B96FE8DE75D3FC7AC08131F8C19E53A8BF91168F622B43B6014354C3C230A298D4B866A15D4917597916D20D8E27ACF31EC3C37674955CFFE5AE75AFFD6213BC298AD5A5FCF37C021EB8DF575A6D75D786183BC75DD5FDB1AB8398B55AE3FEB078D7144D0D12337999538323B4057015799A7F8F8E38F7811371F999D650A77655D4AACD724E2756AF6C8D1DFB337E5E8CDD9!
53FD529CF472EBD4ECECCD596C478EDC64D27F766A7F6CA63136C65F77AC36E68FF9B5DC682E571B2FCFCC0044D8CA94441DF5C9E793BF3CBF3634392964147A14E3972DB6E2BD656FB3526A8632E7F56462A3558DCC941B337D7FEE2EEB7FBF387D4BD7AF9EBF7874D67AF3369DE8BBD46A4DEC77BC6F4D745CAE96E2BDE7BB6C785CC55088DF4ACCBCC7F1DDDD33FFF087B7F105455F86D9525435EE014ECBBAF2E4FE7DEDFEFDFB8BC410374D7B222B96D2442A69CB0BCBC672524FDACAFDFBCBF0CF14AC09C4926EDA4AC48223AAC65CBA146EC5079442F1ED4A2EE4D0DB17328228910D6E07560FAB663EE6CB9A7806A34C26D8CE8103E23A5696AE8B85D7352C271F73C08205D013650EDEC4633D6AAAC552DE349C116FDD72188E02BB43EE3AD106480A62148080F488A697BE7F4C8B85A7C14B87CA36A1A2C58A599ECBF8A6031DB6EE3243D7B30A6DFCACCE1A4616A8D6FB59EDFC6C70B41334330E01B3B6D5BF86655D61D297651BB5C1B5A9C3FEFE43ACFC9153C718B55AE90486668F3DDBDB825F7908AF0076F9D43630B00724EE81608E0CBC64E20B502092668F02521F09C43EFAF8F7920BC3AD2F819781D9535BA75853C4DAFDFDFEADA9FEFEA95AED1F074761D746A75ECE5E9B7DF9727F7474947FB55A2DD7DA83E17A591FF51B4E63AC3AD6E0B797FF22F5!
43939BD044DB17C044D7BDDE4B1DC73B5AD53E70C9A6A765166CFBF69BEE2A!
F3AEDDDD
177BCB8BB76E656E6452AF36D29EF5F4F6D58C55C5AD13AD8ED6A58989CBBDF1DE8B5DF71E163CA0A808E358DF05DBED76E0F4F4953F67941D7DF93E8063ECE092BEFC64598369038E889EFBF84DED68A9142E68A9275A6A31757F41D71505A8C3492462DB11C7B66D708415C166E13AA0A06643D92CA8C7C986DC0810CA6093E7E1394223264FB08C665A839BAC33BB01BD5D2C1699CF652C0522CC733D4F331CFA8C066F661E29E2392A857C2817CE75B2E878C4B0DC62D1CDF92350C0238576FA1E94769077C12A0028B0045E9278A33B9E67C46865B37E8C5A87697329CD5881FF3432D233D8D9C3560A1065896D6061E632069F7D684EDDEA244406074BFD6B3EEB367A6AE24D5BFE541D8237573FAC539FAC6CEE7732F33BEE8E97288F3B4BA5B5C1D2DEDADE5669B0BE161F2CD561794647E5A5D6FA4F4184F76FCD1E21C9002E2F797D0B9703D6C21971F612060CDBFEFEFEDAE8FE543F9E3CBA363A3A3636569B7AB9BB35057BB65F1BF5C76AFE58A351C3ADFB53532FB7A6F67B4112CCE01F8763DFDC6620E879E7A3C548F5127475BD3B120A853647529987BAFEEAEA434389DA8CE558CAE2F52EA8C645DD9D36CD57F36F9C486FA9B70A5D74A9E31701D1BBDB9F76A9AC078D6F0E6DD6CF4C7C726677777772E2CCC9BE8C42ECC09EE9A09FD4FD9400E63EA74768C!
4D1B2BE93D429A655430B4C8941FC0041F8D39349204A2596A0A51C5B019CF067F0AA6E46882D5C0AAEEA643240513168E2FC6278ADE886729BF5BD0BA5709149B9A2308DAE89ADA23B05E4689A910F375D4832C0C7C2CB105F7B7B9D50D8230E16CB878BE45879382CF906832F0CB758E41B536412240936DA353E7EDC85D3EFE7C6053DF9F5F5E8DCF8CAC8DC38344A0F4B35982EE1EB8E7030423F60B6DAC9EE9CD59E3C1E39C7D2AFB515779C9A771CFED51C5EDE71FE8C7F67434EF7E045460E600BD7F34C818CFBE310FBEB6E238F733F4FD7A9C71F6758621092FD14ED1659666B56CE66C56C6DE136D62D499DDA29B6501F0DE074AA7FEA257EF6A70898FDF6D626219ED4C4B2D5B88D8DF23E08F28E4F7EF9BB33679ED3336B6E53135D980C9F58542EBFA735EBB6BD5078D34BDD48A99E92F8FAC6A231F2ADF7EDB79E27BF77BF55535AAE77E9D3AE901E2BB5DEF75E8CE3AFB73B56F9E1DCEDB3991DEF5B3CB939B4090E3A73A6E338A7835EAE29304AA01D2D757F91F80168404CB84E1A8275032D11000C29CA8926772DE04733925A9200813002AE70498F349F873D0A72886F5D913081021D655A86625AE5AC5BC995860E074A9DE1CDCDCE527DE859389C2BF684701800C43B821F6E29F98DE2069D45AD211A4C5D4B2DE05156C48D155D1EF4399F5ECC38567!
DC65DC571CF0E1A5CC572F9EBEB4E41222851C9659AE9749AA14450137D373!
3CA020E0
69707078F71B98E418F74AEADADAEBB8492CB17A22B962FE4E7E0ECC1BD9F831BB532D83338CE92337865ACF8281C582333D125CA78270A672BFA7DF4F1E383B942F4600E785ADB3A8492D93AF523CB169F1115D252D639B846776F4D665071E40241030BB9B6F68F8363D284FF8F50D16B2BFF8807CCCA269C44CC1022C0CBE8CBD9975340CA146F017C1A6335E2A61F2C35B55FE3E5A9A92DD053C7C427A78FEF3EBFB03D3934F45C5CB3CD21E3C6F0C5F71DBB93A598723754EC0C698BFAB7A1BB891B2798BAEA0915BF0D85E4F7EEE289855AF5BB4F5F7FAB579BF57A33D6B7F1EE4A5F24D65BFEEA4D62510700C3CD49F8671227DA9DECA8372736B0FCD4CDA9FBCB46B0C1E5D76DA63BB2304086B2AC01555AEA4106187B90A2814B4237618593008F0D1FCE20CD002D768858D01674410EC84BA59F67AB5E0C56225EAA3F1F389C2CE5E0BE318E09B84C6752D3296EBA7887DAF423ED89DE965D4F84F558C69459CCC0F02900AD691A11BF54DAAC6FD573836BF541F18419B7BE3970886B79316573EBFE0A70D44385BD8A43BF33B7C27BF2FE60A9E4E73A6BEE7A4F8DBE117BDD59A18AD51CEC3F766AEB18644E092AD79D999B231A1D8820B00C80657D3937170536E6D6813EFA5B4B058007D05CCA5C5F1A594F3FFDFEF1E3EFBF7F3C7E0ACCF1BB6383837F22649E01!
49EB14DC2E7C78E08A9E570F19104EFC9F06E97F1143EDBFB551CAEB95C1B1F106434D6BB88D927E1640C27B840E2209BD1C1818207EA65A44D3689B8F06819B29A0A936465B363A48688D42685FA2DD829EA6206A1244386C37F5B7972EB5DE977ACB9A0D4FCDFBD7D4E2BFFE376D3E538650FE4F45FC1629298AE1BB77320BB5DAF0D5DBFA467C77B25EAA64CBEF621BE7FB7E18BE3A7C35A38187F0B2A5E62447607574343B5A1D1D7D096547318471C834D0458698B607B06C0F16B17575013EF7090C92534AE3232580B4B38CAB8B8B0F52193180DA7D9D5E1E30A6F35E5DEA8C98B90DC7C3B95C053EBE2977061157211B3E5C30F3480044303FD11E69402BEE4E2D12592C6432F5E45212100214EB4340D1C0CBFD129C11E0643437E6FA35A7414EF259AE351E1B5FC95106AD003125E6CDA083FCD55C8993334A6BF5BD7ABDDEBF778C333E9E810E7EDC9206AF1FE126AD1D9B2D8DD6043CFEBA65A6CD999539DAC639337D003AFAEBF7E9BF7E1F4D7FFF57D018984D7FFCF3CF3FCF4D7DFC1F7EFFF1EF06D7C7FFC79F8E7CFCFB8F8FC0027DF4F1D19B34465B832B4CC73E9E63DD59FF37209E6F668F9D128F0D7A9AD815778CB8AAAD897D65FEF6E000AEFED878BF0C0181413B724AFC3642666A96FEFEFE284968B4F60148A3104363BC97AA496E14C44D9D7E7FA9!
834E9990108BBC68D3FCEE4B70CEFC725937EEEADE88A6759DB8753DD16544!
0D2F7437
72F7DBA08C35A4EA96E2CC9CFBEA4A77772F40D20AC7BBBFDCD8B83A5CBEFDAAEFF6093DDC1CDA6EB69ACDFA6EC72588EE490E529F78071ED9018E8C65814DD789AE5B89AE13895B5D8B89BF641E103FCB5C7A70931722351981CD7942203C21169E00613A6D1C01418BC8EB424606234E404A528C544A4B6A0BA9D4023CBD1481A3A51E4DA7A6356010504D3D3154E6EE9E3C4AA5F03B3D2DCF98D6442159651F4476B83759AF9772955CC3CD8D0A05ED9756DC863BBE220882596BAC8B1C01C2D8E795CBB18AC70F97FCD5C11CB71EBF3307DDCB72E575520256BB7F903DED7FDAC75AED6F6D1DDB1FCC8D96D6C62875FECC1CC29CB53E36DA5F5BE56AAF71A802233D0756F4F1D2E3F52DC6D9D9920BF07C338B0B00C837DF1CC5757A58F4E1218D67E9649DC2C9373C39F5CDA96F82ABA27AA089A09CD756C4B9DFA2BFB746779E12692BD047B24159D7F74785690223360A8F9EF64B0477FF6E2097208478BDB43F5507C8DEB74844000E1044E78CE1C670B1FB1274721CAEBCC1D21F4DCB5C4F6432F79470B015C3AC2862BD6151BD7567FE6A5F335E89B79A7BBDE5779F7F75F5CDBB17F3E787AF9EC80E0D4D36E37180A8034CF4BEA363BFD97AFFC30B654728E741E244177F325D29DA2D486B914042323A5364AA6085D21B56863F8F9EE8FA93C0E29C6005F689CCE2E!
2755E7B0058F035A9CE715D5E7531B5C067E39569C4A6A7811DFE62A39D4C05E4231594C6F4D34C86416546A6BD9EE26A6E1FA45ADF7B1967521E86D11FAF81FAE1948C37009B5A0E42773C571B6F908E6AB5C11CC3D73E736BFE6AA9BE06BD54DACCD153CAE54AB081EC915E1F2F612967B7E0A9EFB787BA606B8CADAC8C8DAF5B737333E3BC340E5268AC37A0B1C6E75845BD0E04CD51107D7930789335A90374EDFBFBBF39C2E6A5A30178009B23474535AFFD69ABFF1BE8A123841051F50D2EC3893F4288EC5317F50F4A9E04607AD90F3F9E81A30FC0A18A2272E9DA0F1C055E3F3E3A40908CEEEF6EC19707AC4AA32FF7EAA3B9DA684B48B956ABD672B5AA5FE3B5C6A54A6F6F139ED9E6E485368880A7F00FBDADC9163C7C3D7F5785485153096D2799508736391F853F00519C78D2BFBE77BB2BBBB9198FB75AB1E1CF4F5E39775E7971F6D3F987F35D21725BA9D46C36773BE0DDEF764C407B6F3C54EE2F827C16353A66C4CE7D60E53E16931EBE386ABA78F6423230738B421C8BD74FDCC2CF89EB8BC00FFC42FC2CF27791A70010A0D4D5D505682E3E209B3D5A5CBCBFB3FC68F1C1FD27DAFD4562E46980A1A799A74091C0683A83DB253E3EE2ACC0FE6CC173DBDBAB3F5B835FEC8F414CF9A3A51C5C6B7F14C433068305CF96C4416F7A14E85819C4C2AFE4722BA!
57E58ADEDFEF0D65E8965CA4CE4AFB132A404E7ABB3EE4BA478B03EC8FAFC1!
EB651601
1B7D8C7D3BFB6B2DEA09B03FB5203A86AA3CC64AD49A707EF8B8AB959C7FD8747065EF6EF4B9F227002AB7344F0F30D63853056B37F5A835CFED31445D7D6A923125D84F325C387689EA8C8A0C9E0BEC31DDF920022C0B856630409A87949A534756A0BFF836122089FDED19618B1A9BDA997877BE01A20061E27E38C4C7BF86EC3E78EC1356640662C0B62E574B3092B7661FB372AFA62B3D27DB115BF147BAB85BE35AEFFFBCEB7A9C4B2913C6F3721993E6CA0183CEFE1D7F3E78673B8BA19DB78F1C72B27C144891B9F9E9D4F9CCD44706B094C54EF983C0D61DDD1BAD4BA78E9ADA5603517401F841140232C8353AEBAC822DCD395213A52E09404E8E63AA592AC3B98070C743D7102E7C0D122C19459D45320B34C17A50DB171FFFEA347F7979FC0F97BF0E8FE936598C0B4C662BE5414AE8DB6A4E9CCADE71DB510EADCDB3EBCB0B7DDBFF792551FF597FDA3B941EA6776E7B9331147EA2018DAE79E2ABB4EA3E136627E6DA5E10FF22B023819A3965B2BED879FEDED5110797370ADDD11095A97D84048EF8D511C7F0D8EF6A9B5D2DADEECA9B5F1F1B57E606890E9857E5213BB4E39E785290C2C2A288199B453A7EA709CC6D9CED1803D1CEF072EFE8455FE134D0F5B63C7FBB7BEE9EFFF3FD9400DA32483ABDA15BC83A27E70FA276934C3E5D1FDFEFD41416AB00DCA!
BF0EE2D65BFB023E58B6FEB5A9FD41B85E80CC98E4C8188EB64CE6C7B06D8807FAE748FBAAF567A908C189F265F73F9CFEA563F38BED0B1724F94A140D6D6F862B177BE3B16A7558FBA258CCFFB77F56B584AD0EBF78DB04BEC47F1B9ADC7BFEFCF9EEB5FD2E80E85D7D6833660DBF3877E5CAC9FF387FF6D3B39F76BD86F5DBA9142B9DF152BC39C9B1A0A73F99A876F75EEE5A523422E281765F6C58EAC103FCE22FB59CA240EAFA608C009987E010983B70CDF513FFD396B925085ABCFE9A14F3681A7A48557546B8354A204A714247DB613C9C6937C8D5FC381DE99E95D2DEECCD8153877BDB37610E6EEE95F6F6364B72F0ADD4D825BCE237D61DA7E1BA31D79DA1F7556EB8808DA40C4943FBADFDFE3D5C6E588E3BE7C23FE75895BC3357D00F1CD79A9370A335A7CE39BCE8E65D778E9580CEF8E8B197DB7BA5354AABFD2DF1D1FA07C7576A5831A6A9FA99AFEADFC2AA8B82E95FABC365EF7F76EAF0479047FFDAC0A997AC6D0E3CBC7E3E0E826950A69C014B9C33245B7F90C990713170DC6181C704546B2B63126E5A191D9449424C9B703C1167340CE6A4D16D74104EC016EDE8FACC7A637C06479BB9F12510C2DC18B45AA3E15773EC64ACF9B1060EAFB988659BA6629A5FA69369F3CF7D974E77C437872E9086445D0B9086C2B14BCD8E78AE57C984BF880FFDDF!
BF1A7A97575494B74D7871A02A36374A4BD94033F14F5F9DBC5CEF2D0FBF48!
BEF8FCCA
C993E75EBD3E7BF6ECC2FCAF8E960A89CDAB544AF58E8EDD339F7CF2D9E572DFBCA62CFFB4F84070446E218188CAE98241028032DC483B0F32F0F2BB322712276E25009C13346634448B8BD4305DD709A0C5B6B64941162D68BA1D89648BF1CDCD66335C8497860B439343CD7A3F73D020995C69BFBED75F2FB1ABAABE16A72FB542EBB44F0355C27A820D1A6EAD942BC57157C8B19C586EB389A7E2A16EA34C48391B4A3ACDBCECC19C63BA16CBDEDDBC9FC7794FCE1DF15CA6FFF30712BC36CD031CA9CCB7D003AB4974806BB5B725501938C559092FA936A0B9FB07E1B21D3D7A73EB4FE24105AD85CF6A92391D9406211836E10EA046C470FF14488BCE7A0D1020B9D406818C1A4D2CB9128B7F60E24DCECCCD58EBCE3ADF027680B8042B833E84FE4A2E685E0194383F06528C01AB5A3B1436539D9A6A4100F9557C724BB51C8781515F4A372BAE1F1B8FF13B37FC1833468EB571A9156FABE9212904914B20965E7EF14BAFF9F5AF8F7642FABC914C7821B56F83E1C8E7DB93E0A1434E78E8D8CDCD7FFDD5C9EEF2DBE1E13F0E7FFEEE3F7EFEC7AFE65F9D9F3FFBC64CE84E8645F5955CB8D8AAC3C93FFDC9277FF8ECE4ABA71A98A88BFC42CA01F7C03BEB3A0121035D031C41D2A4161F88E9229AC84929068D08994C80A10C2E40D968E28369BA6930B21CF1C3B970693!
38EBF5211FE7D28E657FC4AAE148EB30A7F9CFBCEC7EE2EAD4DD5F1B7B7B5B7961B77395A8A6532738E83E3CF775C4A65ECE38AEF86AAC558BD5471DD2C58A9EC580C8DEB0C429A4096C3ECBEBEC41689B47E60C1438F1A3356DA3C603B45C1B45868E4FAAB9040E2F3BB0001603637238DC97307D4486BFDC7A6A45A12EF6D643DE8393D26860A44317210FD320A45148D5AAC011A1C5D9BA20A9A7DC912EF35800AD8C0AB313440937240FAB30A16A73670ADE76CE0379D36CDA875904E1F303B333232C7DE0499CB668D14A438A420920B143D2AF1AF159A5D3A9BEE0C98185AC782DD32FFCC627D2BE264011756C73A969236ED03DBC2AD41B05E57F4E1DEC9E71F301458B3494EF5D8F47E6875D4DF57B57BFFF47FFD9AD2324AD7BC7ED71BFEB2122EB6B758ACBBBBFB72F79B7BF3AFBE7A313C7C6EF8CA952B9F9FFBEADCB9F94FAFBEB9FD02AE78F296E78518B4093727CF74C8F7827CF287E1D73F290F32F4ADA8981F6849D2905052A6EB2F1971D6F8D345350480256E2512013981AC08AD070F3399874F1734DBF3F9F5457E8C3D3E7148E2C3BDB89FAB846888FC982B0985ACE7441C29FDE13154C736C82331EF420F199664BDB0E8C65C9E8F586723340E59581F15CF0AE1F187F57008AFE0013F606E131CA42B56AC7EE89B82DEB45EC08AE095F0120E16CC591!
DF7F02A23A61F64F3FD1E1F8E196B1EE7E6AC198EE518079E1C77A57F656E8!
4953CB8E
68EC3B12B1C10317373D1034E76686F732CC597628DDAE0B159BAEF532BE37358F5B92FBF8C324737EEF7976A2EE1697229012616DA33A69406B6A1FDCCB453AA3BBA9EE63B0C6A08EC8265447596815016EDB1D2834545A3B9155871BC286DB1355780081453061DC4D8034B66BD2CF765B019D81778591CC46946E1D25AEA87E717AE4945ECD005C1D2A42440C2A6DB5D2EBF7DFDE99DD4F594954ABC49DCC8E8A9C443F681C5F1530C4D3F1CDEF87CF88F897B8957DF1143F4CBBEFAEABF7F75FBF6D9AB6FBEFA2E9959D26E79C56278B3182E0DED4EF09BAA3F0188FEB7372925057FE901344FAA8BF649807302082119D1DD5A0CE887DE7710A05E66E6958569912C8389004B3C5EDF7D7E58CA550817E088E627E604E8898522D2AFE0A82E3F379884AA65DD0362E4C061053C131CA6A1AB5EDEF5F2345DAE035BE4F738606EC3749835310D434B26D37A524B7297E96CA95194B4B690CA18A61135F3AB7E34E2395EC11871B1A0EE489E79B0190F80E44A58858023B0785F16002136C7EEC372B9E3B5FAB1C1F59191FCF80AAB554D02A2676A7676CF1FB1A2D12F018203E97B768386F8C167A76E7EFCFBDF7F3450EFB1A0BD0CD38AB4973A0FE493D9C0472A3B114D9D6BCA0FA8E1778958D2A3B8CD345842C0F7AC8E30F71C72F32B12283AF5ACFF18B47B094716CD98!
B89CF8B74E23FDA5825DB5312775D77F16BED1D32C9AE08EC34D0222EC1385C51454463F952BCD21E286566AFB792075B687D44C267196CDD0374E6846481F7E387FA3EBC5C3B3092B149EDC84350B7F7B22031376EE7CE2EC9D85E1E1E1CF373EE7770E7F75FEF6BDB39F26DE9CFF092A3775422D86605A4044ADF713C0D0277FF864E2B3CB571538EE8B0C112ED370D133833262AC87AAF8FE82B60CC03017A6A752CBC4916DDB5CC148D6F6188E6E4EC6F80D2133B65D2E97DDEEAC5BCE498D7C3507B79AB5E8A6A5460036A04AB554CFCD3A1EF64234CAAA0E82672634C2BC3F401355795C9A1EA799B1EC8CC9DE82211935EE23D30EE2E1BA9E0492F0072C6763D93E66670B86CADE2E5DAC69D15DAD6F43AC630546E6581052B0F26C3285A79627DBCCCDC16B1B87B698835201DB8DB387767D8485882CD576CDC29C5A889AE69C946C835A0253760063062A6A8C5B055D8BB2B6921D869AC9A911D4F00700C901FE1B40435B9BD6C47B02C39A409481275952B6A0F32FAAE233332666A9EA88C91AA6B942211D85BF1A3DB0A2107233B0852019266DF78E0E0C0C1CEE9546C7628D19FA6438A6F0AF80222E03F64C506A8D6304AF19B10AB69DEC83A7CE814224A1E3ED1AD9CDB071E7D3AB5FCD5FBD9D98BFB37337A5F53DBC7727F1DDC6C304D3B13F34E34321555F58!
4824CE77DDF97A3E39FCF995CFDFDCEEBAFDEAD5EDDB895F61DFDE9C4F2D27!
B4EBB7AE
87BC10BB654BBDF1898B9788A2CF2E5EBEA2DC077A52CBBA81B5B28DFBF7F5A0C491990F160FB5F3AEF7E9673114BDA327159B5BD6CEC62AB158AC52DFDD6BB5E26331270BA440B0C4C838000AACB40D536D381E1B660DC3B3596596F53C2BAAF0F0D10D0764A38E1846B45D1E20AD6E3248886D26CC8848CC3A95028283C8E482840D168025C588180A894963AE5FFA2D0D3DCA5E5C9655AA8EA303998E3762B380364F731AA2F8EC61B1ADA86C700E4EA051A2D11136E2B3508D7F732157B5582C8F15C672DA3AEB5A67C035308064A7E87454C53169B2E680EF40074AF3B9CED5BC5A907A462CA71DB5DD78BD99F3988736892783D99E026C6DC1EA91B15A3820F81959EB42B5EFB0A8BF6765DD9457D0D3EC14011E4DC7E42FE8C5B294002B903F8A01551461A915B9478AF641D1728429A66DEB5A9221656068B3295389AE5D1B6A6E868B6AE2EC3C88E85350911E5D5CE8EB3A9B78F32EDED7A5512B878BE1D088FEF47CE2EAF0ED7B9F9E1DBEF2F6FCEDDB70EA1367EF7D9A2160CF2F3C4C3CBAF56BE2578DE62FBC59A9B626E2172F7EF2D9679F5DBE7C59D15362CC1E504D4B06FDBE64281E521DD15B239A169286AE4458E40159170AE7B2AA1BDFACB8D962C5CFC673A5663C570107456C7C0A2BA99B7D2A750BC915679254257C58975D2946F476490976B096D2596!
1C2749CCE966D564EAAD31AF31DD3016AA0DF17A8D9811EEE233DB9904A4A7236A94BFC8099144D2990DA1556A9908BB860D023AE839DCFD41BF1C1A31F8F29584CEAA7A3582C1EF86C4B1E71E7B01040DA2A2CED5A29E444D967C1EE20CB31F07877D555A9D9A7C53C913CBD1E974D445C3D5A79C27C7A2935CD5237A052631F46412D700C247E75AA1F23205E1E8538CD872CD901605E1A36CDC0939652C2CBBC5BB40D03682CBAC255D392AA3DC007BB17C0163184E7E210C575F818AA0DC867FDACA9877C853B2BD51D038A5807B27B1CDBF3E7930051C87B7DEF1E3CF54FEFCDDF79F4AFAA612732B6DD1D2F9E4FB08199FB5ED7C03BE7CF276E7C7DF54AF7AB7B894CF26157D7AB575DC93EACECF9370F53DA2D88E2134616988BC5AAAD56ABDA3DF187893F00470ACB1497B11A99FB5A0AB8E19A49D851815ECEE29FD1518F41BA87E29BF1782EC4E4BE88229A392B12CBB16A48576C0B07435A81BE534869B060CD6204FB30199421114C9AC2CF1A928E235208B80A2BCF441C094ED4313E4A4ABCBC699290F6B85DC39614124CCA0B7BD86D06AF28AC0FC16B4A6E2E09F02FA40452A9871AA0AC4A710119CB36C4CE59583052FEC82A1D34561ECDC166C0AEE556739D502230753D7ECF9C19951E4300415A13A26468595642805834A971407E0502040FD080039E7F2!
05431D524515D6F23083036D8E916804437FC704FA8B81A0643B39C5CC043F!
BD93EB8A
284961C64C423CB78151E3672C23CB82907130E278526CDD09768DEB50531F99110A4AA098AAE54E0E44F4EEE9E39F30B98E8F0F9D0E450E85BE3C4A789A5D737BEBEA3E3A32DA61246442FC7E2E68DD7DE50E856E6ABF3E7C136AF5ECDDFB8F7E9D5DBE7AF26AE26406AE75F75BD3EFFAEBBFBCAAB859F741D9E55E6442A02260AC5AABDAD5625465DF4D91F3E5392CC763C483D60125589E01DECB03CC4C61B02D1C43C2C7B28EB6443A11884730C6EA00F14A95987AD44A0273504689849DDCA462C1BBAD9B158838D8344D3930C16098B0098D30F6995C810411A9604C48729AC24A2992419B19640DB89D2820150A6360DD521056DB0A0FC970ABB41B1E3E9DC2BF4D2D8AF2EE852F476884109B2BF0A38898A01EF51A4A768DC020C5CC8F7C7657251500909BD5230A9796145802A0B0B47DA92F4716061A3542E85000A021316694BCF0200E6E5F9A8804058B54BF8E3A99C6BAC0A64E419D3C240F81F06294EE31374AB30E239525168797947A5B28B0A4FE905D15A9A3EA20630D5C526EA2CE192DD268C179414B341D634C4ACEBFA028E237C661E374637B4EFD064C7F15D60E8F9E1EE5013CBEE194FE7CF1F8E25CE5E2F868D1B3712B75277F5BE72C57B3D6F87F4C4F0E7C3E7CF3FECCA80883EFD74FEECBFBD7BF7E636DE6BE6356CC1F0958DCFBB9E66B4243C2F!
A624429550C8074E7BABB1DE5ED1458AB6F8008A879587CBCB3A2C4E4485E989853C408870B175A94D0460C03CF4CEEC88A5E8B614A245F875D6937BCFB7EBF54928B97A299E8337E664FD622C42836604D28FB65AD71E667EE2CE7928B440248881B269C274F9231F3D811DE3110FE717CEB033A263514C62BA5D5B0B7C2583E2B5A414C7690B3C0689CB8740E643AA26458A753D2782FFF1A120331DF083C9D6102C9B35C2C835DC35435CAB76055B54E23B0784BA017B05374A5A800373A41109B280015F906CD8BF06E321674BD37FBB5D238768E90041BA200BAB9F9AD64D8E87B080324A6CE93610EB58E454839C0A99847B55F905DCFC10F849D1A37064545276DB2B15C762696989C23D99229D938B1934B3A4F7DAF04C23AB1437879A1D1DA73B38C661136604FFE0AE9E499C9F2CBE4E9C0815FFF561267163C1D3DFF67517F5F9D7DE7F4D9C3CF9E78D8DC84C396B2612DFBD3939F14947F77745991F840FD475EF55D7ABD70B0BCC7EE14749AAB16225DCDB1BAB562ABDA7CFFCC384A2DFD7F4E524E8C756011F308E9B851315B135D356140B6E73364BD800F97C975216029F5B8DB80CFCE010126366A61732A905F8E03AEB89E8C005F88199E3A20B176B86DF640083BB8B85FF945E72B394366A228D7183E77A8689C52F18DEAA67448318384142492D876300!
19DEF23095799849099AF092643EBE6CE003C01483B5028DC1A6528BC7BF15!
5DC2D534
14913E62899666432B7BE197521CBE81C5912743D6E874A94C7A51D437E0452DDD2E78596AD7A80446ABED1698C1B958BEC7C1033F18B800C646A08035F1F95955853F36C0B531A6173D70135FF671D0A0452445036B6ED8104386D41DDBB633628BC0568825D14E42C2C94014AA16DF98616F4E3659B2110F0F6D16E1D26432D8A399C48BFAA6A5DDDAF1BE7CD7D7F5EBAD1DDD0615E99F5E0F1B89964CA11918B8194F0EB74659F5DAFD8665EF5ED1D0125FDF4B74DDEE8239637C30934924BC1EA0A752AD822D7EE8FDEC9309580AAF12AE30DC94651DBC144AD3A306361C582F37E2D84A605014B117D9AC83C7796C182718922C13826FB02436C6A4C863C1AC94F28BE4A176C2931D7672D85CE4941C3760338F68B175C14ED031A97BC5CEE26A311FDADC2C86A01852A9349082F7FD30C51F46391F123229D1D901CD2BE2EA6A0B0A085DB1C14AF4DC3CCF4D4A1113B4E78807EF9E2B94F757C3B96269AD54E2C8B103AE3B65B6F6FDD3A7A9BFA69700ADA5BF02618511F06DC1831F2E8E9F00465410169526897DD82092C712DD126D24D0C9401DF18AA016F750E299241F7A5A8536C4709FD4496901B389B0A6AA82C964BF022787042EA9B09920D594F80AE5813C43A16BCFC322693A5E84B42464CFFD419928C289457F86E7651D3BD40B28B5CA59E595A1DFC85CCD3!
4B743FA0DC5EB3BF9EEE989444AB737DE6A5D9A17364E0C0D0C5CDBDE9DDC0BE74FCC271EBAAEE7BCFDAEBB98754280E0C2AB8517A9875D3067274E300F3FBF08C7BC37DE5B817BEE56CA5F5DF98CCD8BB452FAFD65769E81BF235624E25618328C57C1A31A5925F5130300FC007A28C2D60E1A3A8365F9AA03A04129B56EEEC6DD889D16FB42573E167201375BE1C384734061B62E56DB54E4A362C9E1638C78D01558B8B6771255E1EFAAA6F614BB9115234F01A0A70412E010E10F90338C03504BE3E8C4EBC36F61FA1ABB95415B1E993607257821279BE5248D62CECFB3D1DBF1D8F596CB757A0E4D8A295E1B633C96950F3121F2EC59C9073B45A1513C8BEF8522859E792071ACA821811D8795DF06E8A20D06182653C6548637EBCFC279B5AD838C68C82D3E1BDA1CBA70380421ED108B60B269780C7AC06999A5206812351CE6ABA3DA07AA0B2E40493D0E884F0CB9F19BEA0BF847D39EEA5917AE8B9D0E7C0E207709F21B2222498E33CD4CD74F7D2C4E3C33F5CB6E4747ABD77E984ABC1ABA10D2E6874F9E7CF70EF6AC6BC18E688FBC70B8E82DDA77C510A432A97BFFF44FF798D4BAFD2616A3AE81EEA9F6F5651612A9143044CA5F54A0897AABBD151F06AFFAC3FFFBE6A212010D2A3BF60E558702D503B28CB8D03AD9CA6655CFBC16719CA48B0E5222C02086812!
6D09767478AB9906DC64A71DFADEC4DE6B26EBC957327372B0ED88B5C46055!
EC91521C
C8138BA6366DBC7620F88A369AA1BCA42EB86F25E282FDD42B233A5CE082EEF88FE94DCAF5B40B41F724DCBA1336B04C6017CAE46008C985FF4C3CD5CC4B4E1FAB98E937BBE773854DA2C95264BA5663D5ECCAAE246C170155487CDB4F4FED242150706FB25554395B622891E462D95B27E5A139F891298DEBAE8611EE4E976C78B198DAA2E19D30A5A290536128F48058EDC6329F384ADCB6434299E4A7D5050008119D82CD15AE02A959F0966B3A00B27699C8B446E9B965C8EA9AA59C6846CDD8D88536FCAB42BB8C1100926BD7D580E5093ED583C9A98B9C4C32CC7D2B57397273E39DD71FA4CC7E9C98EC98E78C84A25BAFCE262E2CDBB2B337D2F6EDDF9FA9FBAB2458FB5D5A16F53FFCC94FAAD5B8944E2E14644B4C3425FB51266D1C76EAB0FD29B4E37F504B4C2A2150B55AAB14AB558099569D6628A07C3B343977B9991456D018ADFC935EB4D37577F7E58774D9089B086C98016D65FC56215E3592392F500A958F870AFE4671DBFC93C59AC34B9572A7AA2A10048BFD92C864AC55065331E02BB152B4528F1700C4F0BC19A72348DC5D86D541A5A3944619AE4B3A49B79BFC7CFE58A231C9CE2C7C3ECD28EABC0122B1B0FEB3899BC76F4E8CD6B753FEBBA4426F38F1E241B63282E5B1E99ADA26658C0AB3DD6A5E7950A866217662B08C104EBCF031BB23B9D62B0!
2695A2C60049915D24AE13F8EC81F1894ADB648AFE562AB88B6421CEE4F4F4924424D252D59B963B087691D701F6E8A2E1F38E5874F90AB0950586E855A787D21DD73D705DC1D23F9839D51B69F76B2AED1047DBB5D04D2D659A4B1A3E32D31F290006C081C0B33991065AC994CE5E5B79F759EFA54BACA6EFE8A877D4E3A142F2F5BCA1CEBFEA3B7965A3EBC68D5F6FDCE852E51BDF40458F1277E6F193B8936004B202C51C8E7740964FD681A1EE72CCD313DAC24F549F382A166D37DB1DE3560C95A1ADE37169EDD192CB5A6A9925FA7656AC10B8E8DA909FF5EBCF9F5738A641B1B2B61AF361C9D862167163B8096FD60EC5F72AAE1361F4943E980A86A57E52550702DD96948E082AB6810431C22034241143514EBA470EC0AEC6FF8572B18C0306D2286375F6D917742BEB00B62C0300E9C47C500C7372A118DF85CBC67CC919E949ABB49DC3551C0EE9A4C96839E892A9EE929B770CB649CA4F3A1DC46CC4F2D166A6D2623E96043F26A9496D478AE8931782CB74CEC54B3784950C2E7AF46F8E1A1334055DB4B221DD738C0E4978000FF63C9952ABAE167B82F64C430206F21F824272B18B7AB4FD5A5AE04A027942835410F48F19BF1599F9544F2E818A6C8B078B65264DD1D9D0605880B41452C03D7560E8AF5CBE340126EAD8DDFD057068B905E375A234747EB8EF!
64DFAB7B5FFF7AE34E9751F942BE3AF08B2FEEA6925C3FC3F8C91C7E180B77!
869B93DB
87BFEC6E4FEEEE76BC6FB5BAED4857467497BEB00073962D67BBBBB1282CC9AE84AB5585E2061A37128BE8CB8A57ACC045576D27FE1C0FC19A552ACDA1A1128C6391438AD8C71101FFC26FD3D8D421110A4E173493C9A5649ABA3AD956D514CC3468111805CB0E7604AFC3FF06FB443C978E38E74660059C9EA2EF167BBC02875DAAE3ABA567AC88EE7143AEBF1262829F7DF51536A8FA6E2C2816E0F5D83A19DEE28992D6FDD166CE61D281790D46A6C94F11CB18011AA8469E4EA73FC49DA3818BC5ABFA7410E6A457D803A31A344E0670310380F05151BE3325FA9B13C6AC87289874F082A09820356F50751B74E53DAB00739D574DA15B106E81E3A908360937C02606F8D40BE4E2A8413B0B2E26B4027F745A72810C8ED13193341004254C85CD6C87655078D0B959584AE2B801C372FFE313034096331319BE72B9B7B777E2978E5F3896A1A3A30A1F2DE1C787AF9C7C771E862B94995F0C7D288B0D4A417841D7DF0C87379B4D7ED9220034797A17722A16C9865E7765320B415825A59723D92CE44D1654E401263EEB7276989FBF2FD1C3E5642AA97057F0261ECC9162255709C121830D027181962206BCF062251B099C36C7C9C6628E6D7A10D8A030CF85DFC6610E5C5CB86516501AB1859ED85A1D723D8FDE1DFE7DD6630A37776D7BE8D9662957EC2C853B4B7B170!
664DCD5D1C3C3FA6A6EAD34585A8D8F023A78FD08D8458A667842E0A4979E2EA5ED200DE0B8312BBDA4BD584AD3B261E7CAE32D4EA511D2D125705730C555D7C44289841588048550102423625A037E31F843A326F8A124C20DC493D6261F3A58ACF208AC5890FD63F25E8B4AAA580F1A9E28AC18F7095C3AB93170EF65685294A6079E85F05610BD3618230A3D3BFC2FCF2F0CF9B8ABC063D608AC99427754F543117E28463B60B397169EE2F0D5F8B9CB4CDA46E443D3D5B8F2EE5DF7E54B1DC7772189F05B31F485C4BF6D6CBC9BF92EA1A6EEC1406542E1FFB4F94560D036C948C5F0A631DF556E35879A439393CD78ABE378C7FBDE58B71B0B17333F25242AB7907A90D1FAFA224E99B1204FF520B2639C0A02D4EC286C5B5464A215A77D506DEB66B618B23E847CB2C53874AA971DDA7443110E0061CF3DB4B662C2DA70948CC3F1205624AB2A425234613C74247A830B6A30D6882F2D0718BB6665808D1595209C69B02BBFA718EBCDE56A1CF264393D79A949B4053569D20DC4C05376F1C33059D64CD6AFFAFE0C54109CB474C4873F592AD5622CF2ABB188205EAAEF3D3F2C85736E3EF72CD7E38A5B166530CF518DE81251F03830666C5E92A201014D54B26FED009029216C2D70B709A22571B32425037BF7B708E307AFDDC06721F57DC879146893F57664A91D0E2!
072253824D34DF8607D9A09643DAA10BB050F9AB1733337C280B5CA2ED00F7!
A88E10C6
66FA420D696F01765B413298F577DB7CC7A2DCBC1B9EB66ED2B27BB7FE89DE8D89D048A705A31F537E75F6C94DF0D27BC2F9E7C6D780B52EB2ADB175F0C0DF11B71C39BC5BE8D583C28DA8FB79A1DAD6AF5872AD6BD184B253212A613EF916E79391B8B70A8279821ABD035A37616071F9EBE26792DC3CEDA3AC84991CC455269AB1B460FEDE0D370C60C6F84BFEFA89206648ED054600EB38C571BF23AC98770D1C9C3663BCA9C645084EDB5D851318F73AAA2C17C3956FC41E1E8EB798B86E1E080C3179DFC38EB199DB2EB06856C71B7BEBB57AFC2A2B9D97C9929799B08C39685C9AB96D8640B0115CBF1C16C17E1B3385B2BD4E371728D189D361C64591FB705B0F63F6FBF2D704A9278342D1202E22309B120F721498974FBF98F7FEB949B0E9C7F29270A52AEF27AE9C7BAF6B7FFF3216A14BC152D20B63629E259D3F0B1531F941223D1D8CF36871EAA129F632E8081795B663AB2F2CFCFE128B620654B0E6B65B129572E5E662BEC2FBB00D1EEE464CE565E9C1BDEB8924C589B43C6D75A26A1FCD6E511FE42DA64F9755143F5262B9A9BD86DCDDC0FD5DED6C4EEE91640A4DD4B4A20196BBE9C62FEA98FF595D023911040C4DE3276B302178091EDE1BD72A09E243B24464AC75A0290702425ECCE1753948712E562990F2DF55252B02602DAB014A60A99D3B0C49229!
74EFF98F55662338642D465B1AE3CC102875C32C38219FD94826B446C0C6D829A595526EB594731B25D61583C789143C9AB4046305D563071CE566838AC91ADC7C80AD08728A974A7BD706068EDEBC796DEF196747165D7C2CA9EB51473E64B45878A8B7C7A5E96D4FEA37A5AC058DBA848B0872F089110D38A41DCF6A8F24D4DB0BFF982F44042DD1C1E4E24F8BC449EBDA87446A3B8146C9C34077C07FED84DC0777F1C3BB11B0C9ED2999C30441A607FBCA1001682A491C79114639C03C8DF27ACCAFEF1DEED67DC706A6B2DC47C973DD97395FEFF8F3E3CF81A18E561FAB158737D25DDF8642A9B35AE6ECC3E226704316925AFE4D96634B67886069335EE96DBDE738B4DD8E6625A4DCD06D3B021F4B675C5555F17E8821CFA39E56826C23CCF8B201FD1306AEEC9D2447A429CB6C9FD6239EAD33852A94148001A792374EA6520B4C8A2DB0E490D18AA4184DA9FB81F571B211DB967C896D644B87718F7530DC0B06C5968C9781E62EA834339615CA7BB0671EDB7CD823D4E3E6DCF5DC2A563E4D5F63C6E22CE7191356CC94A823C98945C67C1DD140328CCF290BD793F1DD2C08CC713C972858D2825403B50F0F7A39CA21AA1F1303D3A9A73FA79E4E07E1C0252EE112FB2BB990421212B869E743983B0985E0EE450B0193B12035208CF6DDC1C5B628C22794E19770CB!
03E07D0835B573CC6DA79DCA4834D19288F820CAB9A4056F1980491B74E70D!
F138F160
3D2D054622111D9BC545D81BD91827E7B96C42F31B8DB2637D75E587F7AD782B3EDA6AB5E2CD7AB33CFCF9B9E1869D4A1442776F7529DA7CC286140A6F4A9FEC2451D40C2E041D15F15213727CF73845F96EDCB3E79349B09F92C12EC9BC0E627E36E7302A86E72986D4F3ECC8E0D81DD0D2A2145CA7EE2F2EA6349959C44E680E7751F8B9F5DF9898F9AF00570B1C9096840583039D4C0F2B7D9148399B7521C37331902C682FDB1373E3B990631B600B85AD53FEE83E244C95532CBDACA9AB2115C24A05B6BDA29FA56557594A0C0327E4C34233E84695BB0DC8B066645A2105A4C3D190D27825E354ED8264FA39815E4B2DB17E60418C4410A711EC4CCBB2A7F5E9C0F810572A8751EAED5BDA290D2328FF48B7DD354E8A2329498AFF6F3CD4DE92816B2D990953A5EEE5BB51A258F782E4DC41BF72CA8CAECD4C1CAB8D3837030828C24887DC90871D55CC554312B4C0D1C52A2789FF704E0EA5CF8134027036A5CFD2E128E8D7B3ACB9EE72C3ED9E8994673614BBAFAFCFF9F2CB2F0FE61A2BA3B53F5EBE58EDAD542AB952295EC9C59BD9E1E137A97A723EF1EDD0317D7E31F37AB818B4EB8B186AB2F72CCEFE334288DD1FF556C7690EDC031BEDB662CA1D2D99D66D32050E5537A24B4E49EA90EC88F284F60C38DAD11F4943A25C95A2C6657EEA9D0FD782B1320F326C7!
0656FA20C1BE21411182DD576227A7229751EDE519F2AD3AE6C386DC07F2BEE73ED1D8694A95E80A9C63E87D10D1CBDB6EF378005CB88C0DD909C8A09539A053959594FDCF6248E3E8B05862AE700C5420E87B2B355A8419F3F5E6AE5A0A981216625EC20342455EBED12A36450A0112867313140C1F487F48378EE8119814803078E487CF16F7AE571E0794DB7E3025258C0509F4C0AD018B27C9C0E4016D4680495289A1684051531F6C199002B22A5100CC628021F87DF71E1789EE757C2153F1672C5A962C490418DC88C681D12CBB81361038CB39E5D77DC5AA973B4F46CBF55CA8DC75772D2585E8D81772233E5F24CB9CFEA2B4FBD9C9D1D981D3832F6AEBB6FE3644747BC63F217B8E9C54A68F8D5EDD7B1A5F91370AA8CF93B775E6DC4658CDAB6E028BED96E616CB25B4D30D4EA8035A4283FBEDB91EDCA6C60FF7EA9A459789E1E4EA7EEDC482C4E072387A09C53EC33A3E56585B5A6A7EE071B5BE9EF2FDF0F46CAB0F29AF5FA90DECB0BD2511DE178073DE84F84E8A1E2E6B434D2ACA4EF1533E2E6E2B92C135C1C9A678A0587E66DE65AAD6AD9F52D6B43677CDE513D97472783471EDC26CAC588450D24B063245F2EB93D312FC23E074A23503947D63673BEEF489C488C8A68345DD23432782429B9DA69065CD20103B16C5246DAB4150F250E64C7E2D354500!
CA7B535499AC2655A24B2290146D1447ABB5E77E9838009C2D80B12850BAA5!
E7EBB44C
79497A46A86B138067B288E298D03BD195CE0C701A4ACAC23552230544E23E6365CB8967B5340091B86FC6A2D3716DF9FAAB3ED6E7414D0A9D57225B8A0A5D15A994DD4393AA5E57275F728870270DBEF3B1979D77DF2F4190EB43ED3D10B4DF4E6F6AB37EED34462E1DCEDD7AF1389D71B4D316041775180A021AA6A9051A904713D4126028676773B5ACA0D1C9F1BF80033D6C697FF068BB39439716BFE44A63DBA4C5BBCBEC8610A8FB4271CA8D76E9196C6FCC5071A7BA271717A0150D2858B65DA07ABAED95B14345EDB70F461F3186DA46D8195CE429170CE2B8D8B17F368683C990FEFFA95F198A3A7232EC3CA7834BD3BCB5059710641AE18A22175E65EC0EB04941833800F1FAB942BFA31200AEE60C4F5989163CDB169188199737D07877E4A02E252FE0707913546D42AD1A8889FD4D274BBF6222DD7A7839CD663B84EA9BF71D06F7C2493F459942694958ED2196B27F9A6833419E92D19546E2AB6F09094EA9A7ABBAB40AA3A9901933D27139D652A18E3F5128E33980651183FB469CDA55BDC69603FB95510352C37DB7EC7802419DA502BED4F4DEDEE4DEDD7F7F7764BADA9D1D1AA5FAB8DF9B9D1C1D2D4EC918F0441B35BB3478FFEE3E5EAE5EAC9CB9C588E6DB7D55152365EBCD8A87EF7EAF5958B57FA1A39BB6B38DE24F188949659D7F54D99D7B0598AC7!
F1DBEA00F800A3E320A26AD7D31A0444C361C7ED8CCBE911E04AED44E2D6AD1399C5070A29E6512A680FBABEF8486B73508AC5D6F7F5E5DF20053C65389F08EA4855B4CC890732F92395027EB280894DFBC1BA549BB3AFB03B586CA43098E442ABBB4140408ED1A74BCC21A665B0271B604C62C1D03C8B6521A198415A2194588F3E6273682CC0E6B9125684E10A226A70B6A4622512625C142873D95492C5ED7EA5E299415CC6D4DB019A0FA9329A30A12112929626A53023ABB77B4FDAB809E2820C359A51D61549FA755AA72BC544EBB42E834403D75E0B8808EE8464B8A4C645C2F3164FA523C31494A88619EC00D666B2704E62D13A6BF782DA0E0900E13336665828E7401BFFD9E4BC017F4C66A0F5B7A65E1EBE047C464BFB2590D168A3E68EF91CE3305ADFAF033532971608E2581B9CF45EFEECB38B273F39137C7D4247AB59B295F8C46EF9695FAFF5AEB5BBFB51FDD59BEE49E9A0DE1EE2F487A140163581A1401C6DB6288A263898F1527757B556CDB546ABB1B18E3A8C696FD58DC5AABE93F815562D7547A1A1CAFC8503CB385E56DDE13810DCF6E00127F0616F3F9059331C92A64742215B5F4C2D7675A5025DCD6F20A2CF0E6652D84109474EE638720F713EB19755831A69D106C60792B1E899DAD284E7BA2127049B9C8B17E1F647E0F8CBF79FB0B7281B8A!
31526D4BA64931D35CABB4FEA1165909C24E5A32B5B0B4B420C511E9B4B6B4!
9086025E
10FF7041AAE1D281044A89AFA34B8921F86729954E3D968A0D2D70C5C14892667F4C8FFC03EEDA3E5650BDC8E229CAA3D487749984B30B23150A1AC710B1833F4BF887617A2B289152706C04BC26090C253827882801F9AD16544311871EA649DAE528EA9919C71F73C74661AEF6A7765F9E027E5E72F4D0E868307B8F03AD3898080288D3894647FB5F1E69CF393E2243FA6A97FFD7CF3EFBC367A799C63F0D61D38C77468CCD7A2B7DE27C3AF3CFD30B6F0EEBB7CF0344F5FAF6A460A8D96C8A1CE26F1DF434B407D3061875FC02633691EC02F7B57A73FB031F0D5CEB18F5CBB06B769FF556CB74FD7ABDEB6BE5D12310D1931D2F1CBABBB3F3E4C923CE3FEB022DC95C19321210B4302D93679615E86C45F68811CA864224666359FBFF38D69A068DE9749571202F0B5650257AC018383D23EC37D6B2452286E58654697AB1A584356B2A5283CB9D9AF55485F3D53C975DBD0EBB72A4588012C2A2E2086C551B3F81829601925CE805A9E6162B62324B63B302F7435A4363438684712405FF58D39D428006786651C82260AADD210023F718ACD00ED704ED651F3A31D27FF3C8A23B1C01A97A613631483F143E4652B7DB9A5A7724642F89E980932403661981FAA72B47DFDE16FAB1AC0FA7118EFE000171C8CDFED43E48A7360A03864BC174CFB13122A9C5B98D2F8309695!
3539CE638F561F0EC471F09923E3F0926FAECD2C4C48464CE265BE1B0D975E375D79DF93B274EFC7AE3C61D6D3AF155F7EE64BD295C144C74D896B6FCBD60C0C3E42EC475B3C5E74F749F7D5D1EAB56C7CA7D1B1B658822E5ADB9411D0CC658482E266E29DAA3D4BF500ADDFA0B677CFC0597E07B2D2E709875EA415730EA41E21A6C4E93CA232F1E97AF8FB139B358D3FF1FD666EF0425D34159BDF81F74DC785D9C408083C95656BF41424758CA5D74681765E69E127C979AE195365D8636F5D402F7AFAA06BB5D5E3198D6C78082388B32E18F185916578C752EAC54818B4868D9A12CC7F4699271D1821AD4C055A3210AEDFDEEDA850B43798AEF2521A6E90FD5861F10974AFD4C5692795CA9EF4574A7D2347D520E34DD1E504A474D7F08D5C53726B134702E2B1A0CE543922329E90EE24B0B184897A63B93A5EA96940211505650F10A27762E0210711CECA83BC6E9C2A36BD7C834044F302196B36283B1B1FBB072B8A597A387F7E993CDCAC43F8E5AFFF8E5B9CB173FBBF4FE121CACD6C4FBE67E0B5EB291CCCC43C118C5D0DDEBF712A95422F1C7F7CFEBCD665DA0235F6725A793937BC0D01EE43463DD1DC73B3A2E0DCF3F9DA97603D8FBA363DDE519AB0F5E51C4E4599F2ED5A51C3144397D028208EA4813FD93641B3545CF7D3A3ACCAEE9F17025A41AC15CFDF!
630594E96E5523EC19A2EDF179F28A9B78D448A513D5D5A77D8CC1261811EF!
1C3224AC
997E801C028D6A5BE5526D0AA4CED8392BC18FE5BC408FC753C2F39BDF0A13A3FD58EB02FCB7CDBB6A934581CAB4B27096F62C093AB8C4B4F25F8033C487448C28CC1C0D1D78B4B424F30742966D168F0A625774ECBA731D6C8BBA78371B651A9329B9E5E6A8729B5767D22EB8804C52971F0C52D1471644B4F4ADB5594DB9341348911A4E4523AE88136C5BA531B72760EE3A7B99A4B66A9F98DF27A0382677FB497D0196BCC7457C71ADDB56036632F7E00A4EAD85877ED626DB4778C7CB50520FD1F477ECFD1EA47872F5FFEA19B6D3DEF7B4B956ABC371ECF42777E9DD1BD5028BCA9DEBAD7F5FAC68D9F7A4145AD5253BC7AB2CF9E7CAB95FCECC2A783A4E697E35D7A37BCF070ACDAC01BA8F6D6CAD81AE5C88CBD015B1CB1A54005C2FA2FB7382D6F71F191F86627D884FF4033646A1A982024C35E8321C4C17874320159099AC7DEC14599C02FF5F1F717B4A05D91C7ABC6D105060391D4C312EE01B3E811232872D382A24FE90491E357A24E7A505C9FE2D12D90F929E827A3F6697B4DCBAC9EDBE1A4D2FF39DDB510144AA4161E4AD4616181B228788DE9C00B6BCF826C575A088252D3EDDA31B0959011EBD220A09D62B8D4AE666C4FF0977036E5D2E3763707EB132517965A0862527A3295CAFC94924B413974D07519E41C83B0343D30D646386E242802E2C9D28B!
2891645A1243ADD6009DC618EC193411CD5A832763631709245EE81EE3069855E5C2D8C5EAC58BB82840E368887FFCCF53FFF9E5D8F0F0B09D8D54ABD52C1CE510EB051DDB78F0694A33BE0D15C35F14F5CC032D92636CBAD96C7190E7E41E634393D78825426A77F7CCE933BB677EE99898E8BE32BC91E903881AE599998D485FDF4C19B23AD267DB1BB6FD564F27A3CAA3C545D8B013B7C49271D222C759E1200770531C54740B325AFC1999AB0F129019E9C10A720CE37D612E0DCC207CCE1D2D25C0D217914ACB576988C7AD8BDB953694806082E333D93ED7E8DD4811FF8792B5549B78DA9227D8926DA1D67E270437FF6932182DDA1E3E1A3C43ACD907E3242432CD5E20F5713BD6184028F573EA43F14ED036C65EB7E9608AA4C6826F4F15EF5E8B0A06255810547D486163BB72BEED9349F17832609E808102191DD4D107825BC473D9F59C06E7C34004B98DF572A3E1BB7ED567BD945B636048FE1A1C8E561EC3DA95819E2AE0D33B2AC8E96EC8F5E062B5BBBB7A11BF81AD6B34D6A19DC6AC87DA23CDB0CB596CA162CC0F5994FD0F13DA137DE7DB6290BC6FD6E1D673F4030DD7248CD8241C31E6D970E1F92E6F3EBD7B7AA2A375F9F28B5776F235E8A73CD3DDE8EBB336FAFA80A4B2AD0CB7EBE44C45300449B4D8DEEE2F06B33B1F08BD1811151E132C0B04B4CE!
55D3EF07C36053C16C4F4D0BA245CBF489920A65437A696929CD8CA80F1FDE!
ABF98C97
F9312BF267A6266C8676207FE4BF4BFDBEC26F1DC9468C64D0C81094A327831644AE46206C02C5FC012C01072D4B245DD60958934203439A6359B290FC2D74DDC6D16F01208285DCD3CE940B5CD2ED7A0E498FF07B4482725A8D134AA550AC501CB87961B3C7613D34B31FACC87EFC214EF45B5C8960497E50DE8AC90487DD069474548A7B6AB191DE2A7B0D7EC757AE95DB3B6C95EA75060C7330628E0B48B9632E7004588DF9B4618046B59A1B6B9489A456AB0516EAC6ADD5DE1CE8A87AB1B7DA8BADD5EAAD8D556BC254DD0DACDC8EAE3DF1F8B5407E88BDA6F034CEBF52F4FFBA63848234476913D8E91822628EEF9E398E336C67AE1DDF9DC475E2697777027AE8E2C5936F12CA4697D55DEEEBEBAE9637824DE97BAB2495E1E44212DCA1FCCBE25F40438BFF821F39E95AA4A2D674D586EC5DDE51652CB58CD89743F6C1876F6E101ED7850C924117AF19C9BAB1AA5FDA83BAFBFD7F808B706DF6E6CDA3D78208EAC0FF4FD6FB85C6956769823F1AA22087D8224A9141D09A0B7E98A2033AFFDCDD7E58C676BDB9F5A025C1F5600699862C37186C0C09269D2CF861688A7DEA87A13099030D363899E5FEE3C68D3F3714FF6F8FBA2DEDCA118195ED8A4C3BD3AD32E5209D92C7D44C45A9D9ADACA73DDF777E37E4EA95336D5996645971E29CEF9CF39DEF7BFAF8F1D7D0C!
91B916F4F9502698393FC262F501A311F8F06800F10978541DDFC1A1B0FB42E0DD2F8742EE80B4C1F65F27051493B0F43B4F9124DA11D106D6B315BD13C482953EB33651AE683A202AD4B716068078EE0B3795E816469E5124958015BFD7D3E076090E07A5BA17C5D278CDA657036967052CDA9B580E87FCED92B187D41AC69E78B77F7772E538FB207AB29480B5E9E201D4D24984AFDD24462A6541A0B123A90AAE20AB89D4C5C4491C4905B724BF8EF8B35F9A39214B07E493EE2AB6ACB9F4B362AECEE56DC7E6534FA87ACEF04C5DAFC6F258BE2227E7FE3D1A3733FF8E10FBF91668CA54B00D037DFFCF04B8C16BFFCBDF4F5BFE7EAF5A76B6BF7AF1C5F484CD43A2839D58933950ECDC80F09A3A026EDD9319EB22867CD574747CDDFBE7A351CCA7F4D8AC8768D94AA61434D62703C1B622B8BDA453E7FD7F3F36C80D589A4935ED69FCDC6078FAFFF097C9ACEBCF5BF9F79EBCC3FFDF2CCC7675E5CBF7E6E5F5235E83D8FBF06556C7D46B67465BCDBEF4BFFCE0E2C4E5B860D0E26B97C64EC1E029A8F74EF0394B72828DAD4E86295886D1B4763070CACC013F0F51CCB28E363F374231672E483FD87A747D07A85B18DB923D9671E64DF3002DBADBCA3D249E4CE7BBCA2DCE4C8E074868433458E0B25C514DCF50D579E77B9885BCE2283A8441E5110B818716DDC9F104!
68F7736BE1ECB2B975B3D4CA5A5B917BC21C1D472104A5063772E4FA41FAAC!
A2F075F4
BB7F4F5B3AF4AD26C3FFBFACB03292F13FCA18457FF802F93C901820C594A7E389B685F51CC76663B3379FE66930B5161EECDE3C2687D7DB6FFE8C96309996FBE7C7A0E75ECF7A864F09EFA215EFF81C0218DA18BF74F2E0C825ED52C0F0E4AEFBB932ADAFC8F8C402E235114D4FC1A94A27EFBEAF3F9DDF9DEABF97CEF7389A226720D14A83DF466F2AB2620F9BDCA9CAFE02CAA0DF4F70D46CB2309A183D9B83F193FFEF2273F3973E6CFBEFCC9D72FCEFCD33FFDECCFDEDD7FBCFFC5417FFC93F7BF1A5367B9EF82242D1840101F9E91F99D2A4847D87C7132507046865183A3BDB92499FF1F8AD69E9A43478D74642EF93812BB0D8F194DDE2DF2631E4AFCB09DDF662BAF9DFDC34DA26592AD952BAB1B5B5F239920C84E99F879DE7BAFCE39A3AEF4FF5EFE436360FCFCE057BE15314E18B4796045D3B9B5045BCCCB72CE822401E1DB20DF88FE787C3971BEEA4DA0453D46108197D0C21216175093FEC4A4979D966059C121E974EA4C9CC9A4E41EBCFB6CE2542F4B6A78DF7DDF1D1FAC6D7C21A969E29490B404FE4ACC4D2F27411098D6AE04D0C6CEC66CEDA0DFAF45FDBBF19E7F3776A47378F4E4F75F5EFFE10F7FF80334634C412C623F04F908C3A11FFCE0DFAFC11B668196CE496B5909276807557D994A2C2DCD72C9F1B291E0B95BA9DC8D7FB7371C7EBEB7B7D7!
983B235A33E4EBFC086E0C140ED1F148D723B5013B7EB8C1A22B77C7FD9E4038A9F04F5F7CF1A3C9177FFA78FFBFEE7FFBE2F1CEB7D7F77BEFEE1FFC3B69249F8DE5F9E6F47A6EA597401D2E1CF008D8E2E5B49FBD5390A66863777D17B620955965042D6D6B7FD4B48BBA53F0119D2EB8BAC4E30DF955DE3DF455B5D6D7BE3BB073224B0FDAF4F20E7F9B70DAD3A5862AF8E374CF7FC00E6C53AF87144E3105853AA4B7664BCA84AD6B52E2283EE16C9E138784879D4E9A83329FF200189822CA48AB03F540C7F213A95DBFE6F965DD7CE4E1C200958E432302EFA4E53897A709457D7AECAC5BD5563A95D45F75FA935635732E4B70B5A6F52AF352BF374D015992E947BD527DFBB0EAB8FB1B0793AA3B3B70BF72A783917C5B6F7860B582FFFA03C68CE4A0A736867E201D196EA8F334B4B656CA3A5B85D9385B2612C65236D736D620ED9895524475D57104E4A666BED790E0F9ED5EB3F13BD08AEEFA436F3E87BBD99E009F2136F773751AF26882D680F08261FC40DD4199902035B87DAC49B31ECC84716B7AEE7F7AB2BEF3A3515FBE8091A30242FEE676006122E98637031D3763AE5390A63383E123E417B0C54450CC95640038162A900E75F7A2E7D1018344CF224E136483C708E05C068032ADDDFD8D19073CF29EA3775485E6BB90B4398FF7FDF67C8C923421079FF2!
27D407C24028F45B5859C4B4B401ED4AFEC510C8C1677F10D4950DA9DB150F!
438D0043
2FE9B77677C62352E37A4ECA7D5FCBB4DCBEBCA5EE93175DC0E165D62BF4E469B77EE6FAD3755475C857815D27B54C1209F5A951D5246D9113213909A7C93DA72AE0AADA730F24CC8C7CBEB48749A5DE2E48D499E423F3519208629160DA0E1646B296EBD68BA15F3D987DD17BE954EE8E867F90525E18ED6E3CDBF897673F78061636EF8A103BFFAB34F5D8BAFECF3F7806B4BE56F5475B4577361B91AC34719C6AA924BF54ABCBEA7239ADA6CBA531E9D2EC01140DF7E67BF3B92FC9A82950089E2D1E0D38BCBD3DB4619D76A3CB0CC40AA3021E731EB292EA804638158CE356783C8698C24FBD02393473CBE48B98DDD4DA83060CC632FC3CFB265FD9285A3F3954F4956DD2D587A9110081D950D1A1A85A6A79366D36361BFC433F6715859D4118E86184DD23E35EBF60EF307B057F5B59238A8D5BE07E7ADB38F3964C29081863A0C8DA72CF6954A2CB3F6EE97D55DB4432E7341AA099FD614A2145D31A8D771E491B21D5090CB4DEAEC05BEC8D534EEEA11F476E48EAA1ED7750DDE1BE3CEA09580291D3491041A471F6DC998B7316D2DBF1A9D15E24BE36D7F862A1A4564D6C0C4E8DE01453AFD54D2D8AA2C3C97D0143FEE69D4BDEECC946E9389107A6B2571E428FAE72309364242FCF78E1F87B891C0B856C165ABB58F5BD56F182B4E7499022ED4883BF7426D924AD2!
E530144124729FE3758E293922680889E0BD4A306376473180E371B219417407AD44175ECAF2CD0487B648B0D68239D7A0FCF337621DCB06B6FC2C18E2AB0819914300EEC1BBBAA718568F5247C869C33431BD2405C4AF30F7DFAECCE026F91C2D6D09D073E4D64F13746470D0E95AC2E1F24D6B04B4B2CBEC5BA240874D5BE1AE3049C6D72D0B48DB70475E3D713DD6D91658281A0E112C3108429A00777558762A4A999BC1B031A02D50022362D799C13DD37838F17F384497AB3180C07A9D70ED944F221AD5E860368D2F0DEC3293D42033FEAE0D680284392082534500B71BD27588B372E298E17CD4764024828219AD26A0B55A6E44E7A68C16BF5EC60230BC29B6134D918B78EA196B7BB5BF09B733CCF2BEEFAB3271244BFFF92AC211E5D63D7F62F92BD0ED6D626CBA95FC82E5C35A398071EF2A91D472207396932434BC82ED12DC13BF86E3C1FDA291143A8D9DC1CDA67EE501A35780BD33E4FF053AAAB6985B94C16B611D2939AC8CB878764F9F1313B7D94399CA43C3F596E6D729674B037ECE03D9103631FD6E92892C0A85DEB1D4A212EE62BF46229CF52BCD5DC41A78F1A5B0134F9F0B7AA98566087979C78235E3ADAD421A2B02E4EFC1AAEFE1290BEEBAAA089265B5AA35F4B55B82C8F12F472020411C39022B6F2AAD9460C3178B40BC43F1538DA9732E3B!
7C07872A4556C6508813E4F75533EB74C7E0F6D142841E112805BA7F77A5C9!
7F20A31D
5B959E0D5E1902AF194A4FD3E29A22939E42D0E9EA06AF8513DD8AE4FB981AB2F53296452EEB249589B4EA5EC4CD69CE83F87E996998C526FE0C24BA87237FC4358A8C8CBA852D99DCDE0D5F103D430E6A167985F0A1A5A4AD20EE3D1D6D94EEA1BC7B4A698504F33C14682EEAB82C4AA2638AC3DAFA58E19F2256C0EE91E346C5AC31FCAE3EF214531ED18083E482CEDC9739FB3A2B06BA78FD41EDAE4D6C1A283D58819C2E91C76E3B1E6BC07B1C4ADAD975B85EAFBA9611FBCFA2A405AF0520FECDF18E6058EEF1EA093DFF31A0D9B81388FC01F35EC4A961495B4325B872000A79018E218129C71B602D919B00B490B93F768499FFD3EB818C9653A17C3FB60D283CFCAAF937A22FF832F06F20A95C7C145417AAA53520A1AD5F97C1A7F573CAA6485D668D492FC16F80F9C969F4FE755CC0C850B99C6BE1559D0E74560DDD7AD6CCB92AE82409726DBBCA0C1895F4AD226E4AE30356809C894E043E78718AAF34B22A892DA6670703D4DABE961307DFBED6AE9FEDA24DAAA0DA2403E7DB435D26BD7CABC33C7448C8194555C89A47FC1B6F6D9C6813BC9A0083C35C6D92D94E3776EFD620B6AC1522AA730FE953C27F008432263A43DABA6F072F598844222A3E1DED07B4544C40C812AE3F39196C78873229D1671E02805A76BB7D9EC956CA5B0239E285C6CAAA268FE826A!
83090CE7844A53C24851226F8FF3C242CCF800BAEDB255F208ACE5719E333ED0AB71084954A62D7823CC69ADA78B111D7A8703558A24280513D5B4D2D8129E63660FD2BA619ADE47DBD8EA7DAD53D1FFE5AD33DF7E3DFE4AE08884D1AFA72D9E2639FD035C6FF794C50D4D5C5629A223D20BE45F9F68061E443C46343E9CFE085AEA7C27544AD0F34D6C09693AD9F60200F23A251B88AE3021DDE65DBDFC5FAD6CECCFFA9342DAC3BD7100559D40FE4002A8150752BAB874A853E91A69090D9E695505A37C848D40AD78EDE4ED2BD3D29A1B464147CA113302CA19FE1FE973D6C6115E04EC8F04BA4B48B93D8997245B5FF76F145A377FB1953ACE2435530168075F1E1C6CCC0E66EE5AA6C9289B651247123973BCC0AF0E2969682B99C77D6CA709AFA172B1D96EA2CF6FD8E7FE2A0BE492C0FC6D146AC76457A63A0D649250CCC32A18367387334F01B42F512441B1E7AB1B1F1DB23C72070897432D9BF9DA82182B5408D4F0EC66F8740EC9E1361EE5D45EC8796FCE8AF0E0B0E0A6389CA2D4AC1435A75F39D87F7AFDAD8FDF3A73E6FAF56F7FB2712071F5175FF56884D0D223D3C403419C6F0293F5C194A507294AF293C1E1120EE2019570F182BA86BC007957A7D5DFD9194BBFDE835045DDCA4B72FA90E728F910DCF422C35C6E05562657274FE80083200A20F0E92502!
F52D913BA0702AD6E81F1946296A1AA094A4A11A965A52E16A9DC393C9E4A4!
74502D7E
B758083E90E019CD0BBB95CA7F1CE90B79ED6FC691B44459864B2F9338EEFA7A25ECF4CCBD5F6CB9955E1508CB540F9E3882B9CC52BA90AACF41A37C714680F5501EBA57E5B0F98A658D91D324B00E2DE5BA21BDEBE8D1B973EB854653D71E0DA684D4E16385879C5C6C289985ED76070D74C4355460F7A4F65EA4B1899FB5BAD9E5095B2BC4CE10AEAFAAA4661F67DCBFE98AACCB0F52649513C0BB2A724B848F5AD8E5F4DCE7E643B118758BED0F2F5291C728B45F7090E80C590D7AA0B1E1405CDDD4A3ED6DA96C97D3CB2DF4CAF57A5DD2C0D82DE0DC1D9925C53D93BC3BF492805DFE5AB2D268DC4B54D231A853D4068FA6D4BB023C4724385A38D3833197D1EB005636BB6A931405F2653D4128B4E27A4825CBD40F1C879C6D4F1EBC7AB81D4435494D357FFB78DB3B945C05712B42704FD0500DF92EF5AD168A91C62C91CEFB231345CBEA415582481E9D65264DBD8445618E491C4035F211744A0AD81A4949CB2492DC11D52E539366D8D2C6CDE1E8F0F6ED62DFCD523338C461E177DE85283A0E2E2C3A2F3B5124452D4139B304907299252D1C76E078166EF2CD160C93C1131E15CBA1DAC3DA4716439C860A9483BAD60EF3F68548A91BD85CC564D2F05738B8E1D3CB4ABB7A89A13D18590D01AEC3CDCD21DE99D9C5D3A888F17FCC4FC1F8EA6A129300DACCA1B5D7D!
59C448CC688D1457E18E90D0F8588D3C08A6A20944CAE6FC3A1F203E303F3C6050AAEC9A30AE390BAA96FCBFF5284D0F46F6311872A2338F8726FBCFFAE2BF8095342E98E12434C8D4B1A42630708AB959FBF095801B5A1AE640F345F1C851192431A907C737974C2603B0C91CC785FD0956617458F5ACD871E753F24CFE1D31881F4695C03C5C691B4852FB1957C643413A52DB056ABD30413C7741A1D4FDD6AF57EC9DF8A9C8A23C50BF6F123EEF01F3D5AFF8FE02553DC7384B1030249106955D2502B1B4325A422F97F34B8746FE0ECBAD54842C60402ADE457F936069160ED886A8BF2FD0C9B47CD700FCCD83D06CEAADE68A3BF19DA8131A64598363207CF0154381B6EDAB56CBB03F1743A3392D046DB459DF7B0E10B69C2D846BA6AD3C8D1D7500C1B82C0866420EEE5840EBB85B5F5AE9137F0F9E2DE7A562B348A1D82250F831A5273FD539155B6E1BA018DE33F6A8C94F16CA8B1843F20C53E5051B8401EAB00A27DAA5D1CF7DC9E1715369E3CFDE5A38C98A8E58EDDFFFB729FA7615F8CF50057AF0C539EC8B5789BE8AB5B82A37097D423090364673B4CB75F08E699E1C308A6665257FB596A258505362E904E314C081066F2751D022B098E863E1A668F9A7DF4AC9CBD99C423583E2D41BE40D741B43CA95E294DCCD6AD09246A59B1E695F5471BEB8C1FB8542!
38C988F3078E06D45DC1A41C04AF294B7E98FBEBB7DAB581D67D5E2220888A!
6D9A7D44
C3AC924C146030657082E88B73747293B2A379B7B9BF6F0034AA1E50EBD5DE1488DC7B3DBCD77217C8461AEC71C8410E3EFF8167ACB20A8107AF4B5E684C896A14EB1C338B2BF6562D944F012619F8610B9ECAB63DBAEAFC425C5555DECD4BA3A3B8F7389FE42364A61AD2DCF123C0AB179435D4C49877CF61BCD46A1B15C681203FCA450C1A811EF864BF7FA6A9C14624A14248551A23AC8F0A56BFD739DD252ADC9F85D88B7EDE37C79021FADAC0F69944445BF14EF701587E192F4FA69BD7E8C4C18684E24CF45329CE4212FF10C3922A605816F08CE57DC1E38DB9C2BE0E92E8FA164AB01A38AD725104A6304210749143958E9F652CC89268EB92C60783219A4553329A5FE566D3637334944957F28C4BBBC7A7DB40E38E4EE567EE432BAF014741C3B5EA9ECECEECEA025D9DBBA7D331498B42C86F265390EF118BC55169CC31102FBB69C1DA98D62138153C6215AF346590D163BC5223C818186F090D3E2B558060FBBD354227F33A788D85133A4FD5430B871DACD853A68F67DB75271488A880D032286CFF5E81D2706018682D69A6C1A79F943295D2DF57DD252EC9C654EECD305369B332BF9AC7FD4620A7CBB36F757049F7CA2A384B8403BF38077BCBC0AB3CD38E3C824905994CF74210C28DD378050834EAB51B992CBADCB5F3C7DF1EDA3038922BA5D538CA307E9!
449FE049EB998400A750025E705F1F2141F12F4A78AE829D0DF078E08C9D5E2109C270DBA7742A351BF005D7D9AC492E9267FC36FEF3F9F540D60AC324AA5960AF96625B0BAD945236E94DA41157CAD8C0544D7DD232175EBA9E070BC375B465BBEB1B8FE4BF5D8C2470572148BA40990D5780355AB7DD9D8DF57105A249855B676F466E2F9B0EF09C58A6817E4B6B1E47588B70218FB26F680C0C8AF551F9A8D9392A7718411D2D411D6625B5CD437E293661F00A6358A95F4D6220241AF0D7907D90933048E2CD51386CE8011B034A738E0F51361CBE6BF78E6C823D9904D2AEBAA5633204A0D4F5F341A22E5BE65CE6038551B104FFC50E4E0538C9C6AD7701F347D84990AFAFF720D1292332B017A9D2DB8F1CC32B0CAD69E8A40A59D6A3D6A1129D8C6A1F42BCB49538E39D31794F506596F0D9DEDE3EAC4F25845C325A6982889742ABDA82D7998E9C692215ABA18B8E8A20739BF850872B08FC05F5855FA67918C0178D5767D8BBED40D4232540C626C0A9F670578CDE0E1FD5ABCCEC7DB9E17980FC33E49D2EF7DCF164E760FCBEDBEF5D762713678A52560BFE7B20687CD9F2E449E67F22296D26656CFD11A2A84262DAFAAEBBEB56C0A371F4B65262A9621DF4909CE698A59DED847E493251475A32234F4E43197B342ABA00F01AF20FD61B8F0E5211E07519D3A1A6!
D4B1A146D18DA28D230CF8F202A48B05C45018DA8B6B9B8AF84EEDD3CCD4B6!
EB8EB0E9
6B8B160311B1D56FDB01A4AECCB0ADDBF3DF58A5720E243F0C4F4C14F6E174DBE140892CA3025946162DF924EE77F5A6281C7494E16C19D09E76FEB16A2BE0822420E559BE6D7092C0AE5C9A705CBCA95E40AF9513C75660475F2E3B972F7FD57FFF8B31E83FE000D1D60D75882F46008B1EC0D6D99E53ED95324EF5089868B0CD6F1C1E045FBB48DF3C48E41179CFC7CE4EC0C8CC1D8F27805B4EFFA02F5F57B63BEE4F9C02C6E064B7B5B4C197CF2FED4114212161129A7F0D02B7A79284A47FAAD702F4FA0F03E337E256FC49A041C4648408A199ABC4D06C77948D67EE6EC143D720D928ABB0D397E7BA408296B9E5A5261B39D341E42D3381D7DC4946569C5E320A1A7073443F57FB1302C98E71B45C3501616080D6B07B05EFB470D97842140D9976E465D8E06BFA3B41444873F2D509528B8DD2B2EDE431E42448238690666F0F1909B9267FA3DDAD356C198B3974EC1A366E3CCFB5146D2C794D9C331F3B9E65FCE8A985BD890F70C236E2B4505E1B41CB943F122408B5BF04FB22032DB57FB9F7D5F8FDCB7030BEFCD70EC9AAE3777FF293673B5FECD088F50BBA807EB1F33E48D05FD12352AF791964788D52BBF58082D311DBC4BA97F022ADD55211C6C4D75880660DF900918EAA3DDE6246DC8225095722C6E8C4AB0E50EB7949804F1C4453DF19F7B29D0D08AB4CF!
0D75A3D4230349C6C02C608F61453A4E6A6678AB5D0A304DA4C65AD24525C8834CA53B33F9BEDBA6E4FF074A5C2516445624B9EB152F69CBF1F6CC99378D2738CF465C6714CA0272D4C455148631E49A739B75A87D6CD21ACED392BBA0195077FE8D1D2136F39A2112361B2CE9274FDD5C0589288FA74FF86CBECB03DE434801D59B3C3E0D36B1F8E0E622E5314370F9984B8870DF3F121E7D9D2E46F2299349B0BCF0A24E5447E5DA5752DCD5F756E0289D6BFBCFECB31F5300948FF48FD45A70381B1676876E522CD325C6252F567ECD3637EDCBF3C1EBFFBF8F1CEC1175F4DBEC2B1F241EFFD3104EDBE82E8353CA105C54EC6F2DE4F9FECF44782AA71DD2DFF8F7676C62076B03963D786FA23DF794892F6905020BC0CA126849AB4D3312750F045AB9B7F46F1AB6F07F5FA47DC662028B88CC55E5867DFF8A06C7CEECCC767AE9FF97863D493484A532A57B77801901DEC3FDB787CE6FAC6441EF92A863841D48C3ACF5F569BC16C7796FBBDEE221D65AEFC3E9B64EEEE38731D5321CEB67EB0E8FC2B1B157F708C8ECD49824EEABA41A48E46989B60D92141B4C0E364D71EF94BF98E943200EC907DFFDC1B16F52056D050B1182E9AF86D518D62431A0E876CD1D0BF373B2442365E331975F71ACD469784310EAE9904233E7A2B421933935509023DA050303C57F6BB513!
35C3563284ADA44414C525015B48D212A015292BFB9E07A2C06ED06E5A940B!
94879785
A68D71210B21F507FFC41063A6C92AB7E58B93B0095F770D90F0332F9E91D69922EF7705D30DE799FE905CF73E7B22370158F4B2B51E5D11EF93E692BBB4CF674AB951590659254207D9D7021002325AEC674F1B26B693FE75DC30A2BE5AE0E590944819CE1EF71A122810118D4A3CF19C2D1E0C6AB8E4F4A09164710B1B681184DA534C66D51D2072D1496B7D4503458BE9B60305806BE5399CDD61147B40E9E610F2B58DACD0450CDDC7E56F052EC6289872A2AE9B9BB91BE9C626025CF89A0A337133C5E1160A4B35F79036E3B8CCD42A12E618736A4421D4096F17A1BC6D4C5D096370B91DACD8E226EF4F7218A58376CB3876B1218A1A2ED75F7BAFEC6A38D4AC1D8B505730358DAD88A6BD5CA891DDAE735BAAB2266994B0567F7971FBF75E69B47B311D58D133FB5AE1786FC5762D0A4E7AAEF0264FFC1D6CDF0947247741E7D0F160CF0A8B3F662140D4E72C54E7F53C13BC4C90B0F0A23D434813919A8AB33E976E4519CA630F105A1B055DAD9998D75D2085DA424ED416F825F971A011118E19147C019703749AF0E3C4A9C19BD5944526124F1F754228CAD92892EFC38193541805C961A922303D242888CEA447975366F7817DAB128144FA8A372FA7B7C9796520617133FC596755D7F6C209A1046301FDB9DB999B479900B422EAA8C60F18BE9D1EEC1645A936FA1!
FC057EAD9D653C1984644FC8D96FA49DD2DCDBE3B05193D0AAAC793A76D4976287D6E6B67869CCF047BB39E04051AA16DB3128D19022A65E3F5AA842AFF85DA8825351F8C60559D75FED437437E635A093CA9E4C972ACA37D2B61BB39AD8D87D0647821E97A8F2CD2D70BDDA1ACD767EFC4212FCF55F4A6A864DE92EFA1F291CD847405C3A7E27A12C5E7EEEA1D29DD0D2579DBC78D47B07A2ADFF08756CAA17A774E234756CC5C88B9E48B59AB88A611583D06F4CC77C1A1E2410D5B176879624010D90B5815324452E63A32B311097EACA1F21C30D0A4EF664B68E3D9C00A59AE53B255CFB4A494CE9CB80A841AB88CC3391AE520358C92808591CD138695DC90BF2C192364C10DDAAA5319F583040946CC459A280227AD8F59DAA64241CBA644C4215F045249C66A5D2B56936922072D26248EE81E440C9ED5DE9C8223CF11B7A98833951476387ABB372C86C543E22326A1E714ED4B17245CABB6843324487466D1D1235D4774F19198222B90708B485131CEFE7120C8A52A4DB02B14DBBB0467E5F2B6FE47ADFB364479F2C7D2EB7D5A533887BA8D4AD7484253A4D2D71D845767CFFC90B1C8FB02059D1E784946663938ED565901FEF99F7E43F2B0DC348D793A1074A478951AF540D1A9C9EC9CED3A72FAEBF78FAEE789C39CA566B5167749CFD35DAB724F5727B49A586!
055CA0A2E61027070143DDB4464FE40193E6DE87260E76B475A389AB95EAF3!
81936A1F
F106C692D174861D099E25BD51D6227FC530D180D582088935BE7499CFB112E11783894C12C1E8868E3AB7A220850BA26420C53D5C95910782856B26CF0DA78099B6FCE98E24AA47F2349CDD9720AABA95385D06572F7139BA10F82351D0EE4032265AD1B970BCC81CB4B7C75216F20C4D5AB4A3B2C5464D2D5CAC5F36882C26E2DABE617B7FAC4004404382ABF8DDC36D9219B085024701D33035BFE39007DDD42A13294A88E74E9C8F993186EEEA7615E0C70F4CC181FE154DB0E45B12DB0586EA65D763E8D450E41649DCD11B781884418F848F2FCEA037374F4FCBB48DD383D76DAA4D53DB35B72C0B7461115F161C3D86E2F1B39D9EA1603D907362E5D77B68E67AAA15E973DB466FFA805F896F57ED8115E0132057505A2BC545D190018F219B90B1D83256148BFF30D8470482664099463AE52ED628512871C858D3E41778D6F5439998856A8BC125A9673BE25C19BE9F411045D122F8145BF45D898F755430A9672C6C82A0259955613A851226700866D3782F746CA5D2152CD9CDD99F5FBA0573187421181316DBCD62942319C923587B94B598E9C4E80F77B4DFD7B7EFF91C23623E2DC848E1B4C6109BF837B620F258CBF72FCB76F6DF1D7FF1E4F1D73B3F7971FD6767CE9CB9FEE35D3CB0508AA788AE1F933894F7F6738CA0BB3E27D19A4530FF2964153C677044A!
8EE47A32C516999003C57D3CA976085EC1F9F3C3DB75F71F850E280D22BAC9F7BECB6E09A6A682AFC1E54C91FF854CCF6E94BCF1C04CD0FFAC1A8F926DE099704211A68048C81442BDD331E0E1E863569DF2EAB5AAD9AFC6CB36A610889BCD58AEB645C5B1CE261249758B74855FF430E8E9DDD1F9F6BA986B2C10C203F73E46C29C5F81985A946FA36D5280573B9B3FD738F67603FEA2C3435A007C436EDC86FEB9A935252EEE41317668FCFEDBB3DCE19B0F9D795575095462D955CB4B1B1B10E70B4F16F36888C76DD5EB6BBB15319F946F0109AFB5DE2EB4AD677B2EAF1F1D55B26BD74E9FB14BD4DF4301C009508508D1BB49FEEA0CB8A788B9FEF3CF0024FF1F99E05446089A0FB2A76DAC4D35496B57C329BCC7CFB042AE03B74E6ADB7A01E7DFDCCCF5E7C7B46E0F05B1FBFF5E37D175B195E83191D36B3CA34888B48A2CD594180D23157627136836F03A6D3DCC443EA580F72F82879BCC0361C3147DB120D810E9AA16CE7388E5D9BD95131A2AB50481E40B23EA68578FC007EE7FFF023F94EF50AF08BA1158B3C4FF7A105FEF4F1FE4ED6F2C967FCEB14F27989FEC52AE3F9918FA2852D3F309060A6940BD73A332F1B32E89B8C04AA8E526EEA414F84AF7940BC13103B3DA0FD2DD6AADBCA47530F40A94121C86B60BAF6D0F5E10C9BECA4A4E5669C5D2327D591E!
3B80CA18939B5FA88C7EA98444138ABC52D1FAAA9FC7F488CFE3DFBB64C900!
E7210A26
87DC7CD5CD7A91C485C0936EA6C3939D131CBA0509D3993E39FFFFCE7974C6191661E8D0B17E1825A08F2D091EB6ED965A6B90A1F4546774777E3F99EB707AEACC4D0BC817546B3DDE03615031F3BBC56522A0F1AC1B46815461B4FFF1251F3D699337FF2F119C1B84FF7C7CE54AD86B0218EADC578DE7FF9BAE7D00B45DBFBEA7AF55F9D2A6AA20FF1AD90A7786134C361632F6BE9F6147CBF8F306601C74F9A07018258097ABA9D5247058FDB159A1EC47000462BF66F1EEDAF8F470F723718887BF6D7F7D72BD293F17C30E1A397C0EF083445DE0741AF0D3B55ECC346BD161AC1DEFAFEAC87D518D4B255A2280A0312A0D84A44EC8C01BEB6EBC029E1B624B60864C63AE5A81318D9AB2E01058C53D67E49437E602C33D3A0736F155295C6422EF2A51BEDC369A045577066367C7BA7F2FED516DB43C76EF7C12F02CB312A9E98D8A1BFD46C437E20905CA96299BBBE36438B3F595C2A7EBA14DCBC4CD32A79B0CBA074F5D2CFFFCB5553885DA7E345834EA8CAB01EB55F23BDA7471F6D3C65A2E1FF1B1D69D4EEDCB9C3A83A8216E81CCA691DC958E494B1076FA8AA63BE17EBAAE88E49E9DCE1B8335848B9598B2C1B49F5A394C72D816D407C82217A985B2D99791CDBC37A2ECD24B4E6460D0751F7688EA41B7555FA35EAD1CA41119FBF7CB0A1F993D4C3683BDAC6681A!
86A198F2865E1E440980B37ABEC007425EBCDCC46CD30AA3C3F735DC8694C9B6F7462F0E6B526C5C79A78B532232095B851E749125F18DFBD4FA47B315C03B8D920E7059424AC244022280DB75FF106329A840932BAB5F36878904555C18D306DCA8983232216924F61428A907CAD846A3DF9BED8CB3CC1D530B1EEF20E82988899452ABDA97716E2E5F2A4A594DB2D22725D791C747904E46AD108E16DD898B2C349A641367EB96A49DABFA437FA9DDBF7AB6B870785DB82511B4000A4EFD7633620F8D265F7E2CC240EFCE74DF717474830233E5A38E826DF46B0D5D87352D7D83DB7CBB7790CFD38D73FD8E9C818AA4E2E5A945450A51A9D933C54EC5B53AAA0681A41907FC459B9E40D06726F29591E6CFAD11B5971F9278BA7FA7108D8765606015F59382D31B8FFB7D2868C37F534A41C1A98CDD07F4768E572A793E4DECE35C1C36198D7EB4B3BBFB8FE358CD165866D0E0D42D91441EA4DEEE78D4E33E15654BB10C42092766C8100035F5C4CE66D2C4F29478A35848ED0440FEF42352D050FD12CAA5E9F9EC88DB4FAB68A90B328263F28578099470009452E399FACB7AA12D301FD74375434B431D6BFBB0AC323C13D18167E0D51415F99FD65249D20517BB7ABC480C952A6E7FB67180A2D69F0497C2AB3FFFA397AB6E357027F205C6263545D232A2C86AFBB4F522!
19A568111A1396EFDC61E034CBF916F64E59C0D0B079E36855E5DA399DD0B2!
EB552624
DF9306B94066601515B5EBB5F7627409616781FE6A240F20AD42E39C1ADDB586F6B65DEBF2129061E4E7467BC4ED507F4CAC40B49EBB7192A0875D7804510BEAFAA798DE51A44F7EA656D583D683DC04010114279E35C38BFB95DD1F8D609547372ABDD40D94514B561B0791B15E9140CF21C819B7819E25A0DFAA073A1FA2F4998061982DF31197762956C44238CE9993F65F3E2621288ED26D8208E6E8B427083EB291A423EFB43019492C6940E47E551C4FA3C4253C38D00072129E70E7374CBC89432C1D4611B615C7DF9F64183E636EBDB1414C0D97DEBE5B9224545D7E7AF5E73783A362B1F8FDF79F2EBB8DE7DF3FFF7E9196A64BACFCD3743B312169DD752F6A6019177122C8118AC13951B37C275FBF1E491875EE34BDB93F6C96F77290F4C68011E56FC431B0C4535BC331B43616810A4E81240396171515E72B8E0E1E88D4662CA62EBD8424A763AE27B55DCB38B36C5C0822D9A53C1164CC730D2FA7FC90FE474D48D5AC03DDB84E3E21478CF8563EB0A36D69A9DF2B8CE843853BFB84CAF89B1442536B5F2B8E4EF5864D55EBF302958134C6EEDCEABA31A1CBB4A54EEA7306B8193EF59C42237318B55B62782BDD909B0B3A5F6B127B0F5F1DCF847C381D187BE9410C84271B731DCA179CBFB2023319E78F7E8D5188404CB0DCC5AC801A917479C33908055124F!
AAA238CA380C01943124957AF9D40ABD5C140D11DEFCE0E50D81C672201F40953D056A328C87B043B454E6BDD49A956754730AD0FAAAD26974FF2E561AA230F7C6015C7DAA00003581FE52B7C2963124285BBF11E2ED0A86F1D7638232A968B4D550BD1E65EF98A4048BE925CED8935F8B364888D466957518EB10AFB345EC8B7ED1A0DC84AC6E6359FFB109D65B34F536EBFDEA97272C8ACB4725D08BDD4DD7FB2EE52C718869EBD043862846F137C6D6D6C7BB97B10376556FD557D9EE921049DD84DAABB516E8867B2F9B64EF50254F33C59491207F6A96E3904D6FAD1BA88FA347DAC9B157B24E14452703AA5E2F5E09ED9D3ED8F782D92E2462DB65C5D3CAB383CAC630280FC96300D59694AE62A9E4EFAA1018F5740A0C1481A0EA9E41B06FC38B5A588C808C0331025EDE73FFF3B29689843A37DCF60219E49045DBB6A8BD8A5A2D70C53AC3C0AE01BB99551E960B9EC490A922F214BBF03FB23F236175DF8E6C9B34A87CBE05C06A9B13CA22663482540EFACB4F7B05DB34B7B9D53E7449046C39637C83B3A05632F3AC01E2344025DB7AB96F72A73960BD6FBD8DA752DB9286FC3BA4C035D1B8F2A7587ACC3E0524264A081881D93AF5AC723775CC92A63DC978EECE64170504FBD778D469D9A747834E878C34BC1D7C8A853D6BC00DB60689C0338BF17D3C21633516!
D8EEA890E2931AC444486392720C87993F8AA7CDA9068FAC1F1175415A6F23!
54D938F5
8C5300CB087D9026E62CE9AF16A41625F7A00142F6CE0CC6A36C17F2DCE3EF0360C0CBD3A27D98898BA679C16478958DF23037AE143B48174797A082664DDD4123D8C0BA243465774F5534139DF7F8A6E2E2B490A72A64B14310B7FFEEED63D9EFAC5606D8D30071867B3B5DAA164FA9124D24CAFC174EF40C1039621089C62196C80AA51D29A9D23014102A88F08B257ABB426D8B1F12893E0C7EB5CE8AB1096374F47950C4207FF6F3C9AFDE52F7F3CAB14E6BC86956F7233D0C1CEA033E8740651F85DA8845C2BE73037DEEA225F9BFAC04EB01B5A2D945FCDF32C70B5361ED11483C3A6345BFFE62FCF9CDB71A84DC22D967CB79C4A1FFB2E88DA1520F3A202D2A66E2306B859F71B8C89F8C1B8327A874BD9D13B316C81D58D5EFE9052FED0B0A50D69F680E6E6EF7949E19DDE68D47A4F9FF076F0205F4F5DCB93AF267669AB9EFCFAD75309A17A32FD756B02CF28358F702CC2066504164A404B120F11FB502A5FD8BB58F47960B7F18B37BA01236A0EF234B31DE0B229C056404A299267042981BA150540B4517C1007E561C4D9F571B1B8D070B97AF593EFBFFFBBABFFE7D5D3005A2E9D0CECB2D0C78170E1EE0833C7CC5D2B5D90A7AAFC486BE9C0DE74878BB6E502454AAE0F03904218404D9D15497756CEE746E56103ABD95077B1A1A0A4A2EAA5592ABEEE491BD2!
C135F6BC4677FEDB4683C73FF979EB8277684DA89AF912DA238C0C3B61AEE761813A4FD8C237C8FF0DAB8FD7F05501A41B9324E2C705D0392449A4704C4D6293DBA2262A1E51E825232CF04D5C88C94E4D55F8D50F28A64F2D52BB420354825A8C359CF21EC45EAE4B0D1E8AAF426C5E4C5606501CDE41C923C97B7EC8433152C4041B1BF5D4C32163CF790716DC19D45EBF1A7FFDEDD36F5F7CFBE2C5F517D7BF7C0C3B48487C60ADDBD7E33010407C45E20229D211696C947250C287923EC81EE2E580F790771FDBD1366F97F01F86663E5853F8001E14E14605336F865BA003491E3BA7A6E62F0EFF55F3A521F5692ABDD9DAC17D832183275905AD33166A9288AAE79D42E1AE00EBC3001E0AA8F2032EBBDAA1853351D82876A43D2311ED8366F3F35F1DB1880D7325621B58927B8A79CB6F396758927542563B226B7F4FBD4140289BFB9B0DC151F02E52672250D07C3F2CAF8E8078D601A9086FD8C85523A0C4C6C3572FBF41E4E599BC1AE4329F8A681D4AB27044E054D2C0822BC84B3A6A03C903F756AE6B8F6DBFAFF67C5A279074945808B7A0D3D861D0F8A9D49680558A4B27358DA963DB4592D07BC0CD6CC1EB38906F99A49751841ADB08ACB8A04CB4F3A76738707DEBAD9F3DFEFAE99FFDD9CF5E5CFFF8CC336E4CF4A48825906C1FE48D18AF0144F327A3FC69!
EDD3EADCE96F03E0D7791C4EFB091EDAC23B180EC21254CA444AD25996F04C!
6AE0D708
DB703FBF0C78A4EA4BE00583EE32587C7FEBAC8D9E4FBEFFB47B229172DF754BEEFD83D2216E7FDABE53985314C129946607CB433C650BE9F4D8DB8A382592AF8573C2A8113549A897EF5BD8F60D50F551F98357CDA3A30F9AF861331290912E43C868ECBC31D506F51AACB5FCCD1A050C87A107DA1158471A6A561702AA31D0A98105044FFC716A8650C29FE98DBEFC7E53FF289786B54A486CEBA0C9C843D758BD2C8D6DD274F754184918D9D3B2803E633E133EB9CE14B973682D06E9827D9783AA566C555F29F71158EDE91810D77E2205D1A885A82F2DD3EA6FECC318EBAFA960D64AE8EAE7243DCA0C492C15B0911DC192EC8544D19F9C39F3B3173FF9D39F3CDDD8DFDF11CC9FA8C796D45B34D9E3110808ECC6D8DA2B7EE1298847A39220A0D03837728287F05A4DF718443CD2B5C1FA1B4F161D39E48751B8D8A7AAABFC5295CF9056C151C341626424665CA2A1D871EF63FB319300BA7F70BF74BF542AD5A2656D117A4C3DD05D71DCB5C9855A3A8AE712E65E510F78167AB503390D3DC69186BF1B79B139FAA06C69D637248A241BDD40A7CF4C74F406CB68F5A211D5C979B01DA41C5E8758209EEBD2E05E0DD1D6E1757FEE8035DC1C0E79F08A2CB527B587AF6FEEF1167F731EFB4DCBAAEEE64AD55200E75688950721C632B9C00A50B1169AC0041C4BF1CC02100!
94B2DCC8DF219939F9BDB797E4EEA56CF1A6346B347B3BEE3C8A30BD0E5A043B2C2420C567A1A01F01446E371466086BDBB03024A058A3154C1E55A02D4A2F792F7925F3B740A7AA7F5CFF21BF465ADDE4499FC00CF04927010D0AB37BBF242E233F99C1CC1454A08ED75B94CD9568722F6B89C7924DC91608F46C633AFED80F76B1150CA249318D978F26CE3DCB90D048B23A1B5ACDE2F61CFA1E14305A2B57F810C238268EA3C79E6BAE01415A056D6730ED6A617A4539B179C34250E89F40C9D173E8DC8B313679C62F8E60349431F1CE147B92C3FBF3962B441A11089F81B90DBE625CD32BC2582687A1E575AED9A9BDE7C4F23C7F221C366980B3920A886B042882BA3398FFE1B9BF483F047EBBB05DFCFFB3585DEAA0222AF75796598829BB3BBB3BE631F84783CEEA3BD292855B41E024B48967FA827A81214ECB3B49532569A3C3F8645188674B9F5FD956DA2CA5A51C6931F67E1AE0E60529A02EABEC590F59F22CB155A6893F0A0A20B7BEF231F669BB8727C8F47B02D6EB2ECCC51558A6C2AE549220F5C25BDE8DC3061B7073579C4046EFB51B6223219E51F4481240CB0A50D8C0DD9797A4667F99069609C898BED584649B30CE47A9E635F599EDCBF5F42F8DC9F414AEFA7FF82184204953E3C98A6076BF7DD783E97AEB752C926A535F7DAD47547F2BB34FD4E4!
D0AA80F1E5AE7A0E6C25EFCE078E2E8CE1D09A0A3E6AB0FD09D7D7084F2851!
FECF9898
BA4B8F13792A2F07B1429BD8AA5B6195E1986968C2F6F53C0035B592B1BC302A6050F51F52B5AF4797B214F00CA9D7013B7DA38DF564DEA5CAC9F5A46769C8D331F7840F8DD950F6F87CD9B3C6E908F866F19AE4DD1D9A0F4602300690560D09CAC8F210C9EC7367E607CEC59010E6B11FB4707B3C6EAD4F83406822A438BB7F5BE95474BA1BE10E476A192325A7C236EF2F58B88EB90BA6A3D68D9C587FE9C3E308C4DEEFA93D30133D1390644890D8748A0CDC3C176A0109EE0DA32DE546FDD5474EFEAF3B0399FC042732012A89C654E29936266A28517C9A31DD4CC62515B5E81E27556D2242429A8A42FF72FDE3F58D6AA55E28579C13D70B3D2C1DAE4B8DAAF8CEE8EB224DD0A536763D7490256B588F9877457ACC28A9DD0DC8DFFF69520A15F010E4920958FF4F0357F21711F6F3BEAE87FA85088A1D334446DD5A1E69AA685DB78DD9340F286EA0AAA7A357936E2590701FCA697EBCCC81BF6BC2157FB0D1D5A7365125BD56C9F334CDFBA6207507CB26CD2E8E1C3C0E9F7C60730BC14107BE6CC374F9F3E7EF7E9B383B1FB17BD7C087C7A084B569CAE1672148555BAAF1B8E4059199A2BEC1164A03C9084CD545D7BA85602C1A944693E860DA3D25450E1DE4BD4085D3EF13B6E0BE34E9047105B46DD24AD7B8CF12D2911452BD226921169904DC3871E888EF2D4A8!
71F058B702279A495393DF87EB576C25E1040F4188AA064F55A8954B14919516C92BB574599D3A8E40A383FB9080750F2E1E1C082C826A9EA0A8DA21944B0B591FC96AEDE2B29639FD11F05156DCD2AB733D9AD07BC248BBB4A8D10EBBE6EEE7CD0F0444DF917E1EA09AE9E606664547B6EDCF5B7EB668C844E51B4845BF5280D4B1027D1A3878ABFC0AC1D6BC185A827FD3EA1E49DE196A3706553F6F681114E440E8439B4336E5EA734F6B542384EC6D0EA28D1DD3E091487A970F9E7EFB78FF60FC5F05C23E7E81B6E8CC75080DBD78FAF4C5B7FB9CC7E8824FFB2E2948A45046018CED8C555820B0503D233B1707F10D8BFBC4AC9849CC035C698014195898751A8D7632CE333335B2C63C3C6E996DDCD4075CE7C3BA46D78CD669C2B7212480B9261171C8F205E6632270B885CA4C0DAC60FBD0A3412AF3557C2AF167EF7BA93B890EC13DC8A0534E42E3E2301A2C30D38E8098A265A9EA4C46A54A86951995F833886297F0FFF1614DFEEE74E4A0BB97005B3B383F71DDFE688E9D32CA99C0228A02A096453A97611421471809A0579FFFEE7FFCEED507122DD2A49D5E0FD9E0C9E94665FD1136CBA85C78B9213F4020415EDAB41103F664D3DB83B8D1AA3DD3263E0C7F851C845BD7A162EC46987775363DD9CEAD7BEAC3DA08BDD55C1BA71F99135B4A734079F1DD1767!
9EBEB8FEF88BC73FFBE6CBC7FB1BEFEE6F7C7DFDC5E3FDFFEBF153F9EFCB6F!
1F8F1355
E1D0E76FA2E67589F65E8AB995628A5502F4A79255CEEA787A929DD31375C1959B21E99E175145352FF954038F52125CB1F18AC55A154794EB330FC146B2A25691E6135D52D831A21249246151464642ED61DA2FE0FC5189C60A9D808972BF6B656607FE4A7606EF908EF71DB72A4925308751103D0CA8FE423598B4D6BE2249472A970B3688D39B4C1C891696B68D9FA683E0F03F5D08E7D07428549D9352E9E4D309EE3B2240BD2231119B7C0A0834542388F40E793D3252C27ED3FCCD50B1F5D1AF5E69EA59054E93CE8CE1EAB7A1C09832C2A87C83B9869908AA300A9EB5C029666AB275D7D4630BDA10F318222295B01932090D57FAC3F2DADCCF35F4BAF6C45095FCAD729A3EC678B623185A8FCE3CBD7EE6E9CE57E3FDC7FBFBEFFFC5C6FE573BFB1B5F6C483D93B4F47427D95655221DE4E590C72AF1DB4BAFC0E6340B96345FE5B7B3B9D6399093EE5F8C8D04B539F3F26CE4591DADDC4D28B5AA13AD96B71D175ABD9DA71B23F452F51C00F3322D4D029CB4FADBDBC79EA18DBB4F26A4844B5018BBB813C26028DA265F17EF628C34EE31928BD5E7C3AC08E9AC866156EA4C1CF04350BE0EF1DFB1211701DAFAA6582BDD9F4878B87D49367D28334A9B4674B4560ACCCBC3DA477E379666348DAF944E4AC7B56ABAF44392E206BEAE9F70ABE8075D36657AF1A32DBF0!
114C20A56301152D1D10D5C7A68140DFDBBBBEB3FDEBDBBC751A3F2F6B99755A5F9A15A3AD9AE9DC52CD4C4C47E1E94E9BBF1FC0DB123CD48908855733E8F57AFFC6C7BFE50A96AA05D5AE6A3E97A56A1D16E41288CE4A41CC59169EB5466889777C7E327DF3E8579C88BEB4FF79FFCBB194C9F1CB6FB7E5DCD1BD4F1C71981B8BC42442BCF2CCBABB7EE32417E651BD8156CAE0941F9F65316819E241A9F675891E6AA40AF6B6DA4DADF40A159DA479D14F213E7B40EB07FD37A6054FE3801BFDA8021E48C377C0E1E3979AE93E1444963E3BBE3119B7CCDA1FAA1DB0FE1EFB60D6A7FECBA1247C912A81A90C8E2A1C5220A8BC1B4AA5068765FC0336486051441AEBA74655A9DB86B07D894B9637772E5A454BDB04C71CA229F26A94A568E80AABDD5CD1840357FEA14C33835C3DF7CFEF9ABDF7CFEDF5E49259354C4291188453AB91EEE95FF883E4BD89CAF52870AAD1138373A76F8681113B5432C66F2ECE644151B2030EC4BFBB6871F5448F3AC521A0921FE288335168D3D410188C90AE8D2ADD8CF058B826065DCE129C30677A669AFC0BB093EECDB7E3D1C782952112F63635DDBEA4151A24326E2DB586FFD82DC5856338EFE26647DD2025630D4C74DFD5CE44DC9B79A8472DE253EDECA0FD9708CC2806A01B41DA5255A2CED79AF32EBA576569A701EA43D9AA4946!
D893979C03AF568802E7F9B6C72E841E84A0CAF600B190C3A21C6D602D80FB!
715B54B4
F3A6925C79273962DF760E3D9869B5575F9AA71D4F9543AFEC9C94F21737E70FFFE7DE89DDF5FFBE9DADAC9DB88ACB5D2D41394E864AEB37CFBE04AAD27850DCF3E29F16500B945A733C026B458C4C1217CBEC8D46F4B413347C83EAFE6FF63F81B0EAC25293186B8CAD7B1757355CBCA0AA0315A94562A7C630B4294DDE12BA10E23C3A6BE39DC6C48AE82E68784D0DEDEDE5CBA482FCCDBFE954187B74715D9387671B92A4DC1088FFBBC1B2A78F12D19B1CBA0898D7D28E59B1F3E7C085A6C580F5AE32CF160DA41D310830B8C04DA193410875D948AA2E517DC513E3B53660AB16EA4C1436634170D9E9F9B89D0752175A88525C8218EF269C3A98C777E5A69DD47481E0D95BA019B64DE5FE80A2AB4B2EC544C9347291C08EC7818811094F5AA50F7930CCA2A0550846C17B12F345E587CA88A47ECEF3F321C75D7797D924CFF198BB7D481F87D964A354A251579D17365EC2F82E5879287AE947EFA57124788A49FAEFD5442E8C39393830F1D73B8AC3A5E8C23B46AE964F2F6852506DD9EBF34616AB60661883D7A085CA455ACDD864D70C4B3E5C8FC466AD507C3BFFDFCE8541C44278BF91D3503EACEEA1E04F257653B8E960454D6705140DDB1416513D269F7CE5F8679E65A29D4E29C44C21165CCDA79C47335F530148D89A16414E4B36B7D3B0F8F40A7302A16C3C9!
0F047EEAF05B90F2B282BF29CB20AF6B707CEDF40A08A2D4E432216AAA40A818712DA496D62BB0130438BD8CEC7D9D7C2EB712FB14A29026262D405A84BB99D80A9E68D13316265395533EAF6F3FDDA69588241541F57D122423C92DBEB371E6DFEECF324CA2A2C8576A37E543D9BF2B490DFCA1304A1C34A0B8C492FF1FEF3FDBFF62BCF178A7A7A77D749949279923CF9BA5C2E92858440B66227F8131D1C9E4647972F1E25F217CF063EDBEC09F8352696996B5C30B11B9F2E9DB1F96AAC782BB0B2648CDF1609A76242952A4078DC2A98C10B5A8A2B0E19B1B92712403DD0137ED03A5A6598D99370A99D4AA2EAE1BF349507E938F6029A34BCBB34F3E0D6A3657AB8E610E8436997E58BCA4411B523216A36A2CFC62BD47C36223B02769861769F65843296A5D65D57AF94295E9827E2EE8A4FC6D18D7E113C53A0A02E2598D53FCFCE848CF8D122B5F14E631A381A4E2A5567C4945F1560B183F2EC85790530E9AB034D2435D320E1AA7A66A44B282825B1C142F421062AC7164A05E03263FA82E805CDF4A8216B4CDB0DB250D8A318340B497B276C890383B2FDE4200BDF8F2E9FEC1B36730FC9CE0F531E4DBFB6E5F706012D4FCE0D85BA6F27418805C2D5FC9734651E7F8647A72524DE36E35BB4F387DF14042A80A94940D6AC1F162510CF00C45875FFB7F963CCB35!
875E3435036F10A22C423A83786811461A48EDB6BCB5615E1DFDE637AF5E0D!
8F3E6035
E3F6C3465293CE9EE8CE1ABF9BCF714734D4D9901551D330B232C5769818E6BB7B5DCACAAB37D8BCB1963125E99F4A0BBCB9A720681EE3F4721759879E9379934FFD330D9DB9C95DA982BC8204A11FEBC0476D1824272114E3403FA41BCFCD9C9C38DB4CE7D7A22AC6E7E95586CAA6879CF5680C04615EE594F996C616FA348CDF38753452F20297C4AAEADD8D61B42D712FCFFFC36D4129C140AAD376440E95C7BBB9952FA9766F9CA6131C1BC71FA860FA4AAD4149681E2743BE2ABAD74D6BF6CBEBD7CF5CFF561A892F0E2EF7BEEA5DEE7DF1EEC6E359CFE9F72FFB2DCD442C7DD0E2841A08468D86447DC144D1D64975293D59C9594EE0B4078C0D8B85AC74E016B76AC712709D0E6EED4B17D74AC71760C3EE2753130DAA12D2AC649DEF068301AE581902E4289215E4A13BD3CDC70D76F747CDF21B8988D54CC036176A7A5F2D7173A3ACB54BC745E522A0743EC10E3735829ACDCDEEDCEA30CED9BE873A66B4A4913D79086C14498C6104548020AD3FB4DBF55C4378E583AD4A68BED7B669D546059D160BD0ADF04F17175663D65619EAC86A7650FA342F693D2AC6923199D8C10FEDFB34317108C3F9D1BFDEE5E9D7D63D15380AC34067A4F603B675A82365EA38B2F743BECD6A2AD11CE4F46CBE7FCDB43213D6385708B60FE52BC56790CA45C158E5052933C418DC403!
9D356AB35E9B77A93899AEAD5CD6463DF4D7B7A415D83CA3404CAA5961DE2D8832EADCF236F21CF0FF7C4481B564AE9BD87694015D3C6FB07E6BB97D0A40E1645792E38EEFD8B272F6B299E3FFE32898A5529AC612088A8D3690F3A383E84B610B9618D7607D660463A7A5BB48ECA790C317458915624B55C26243CEA344F37ADCDD761D31F550AA302B7150A909899E8F943F6BDFC32D702C7162D1EED562AF1EAA10E7D869A4068296E784E3B4E226834E0E21888A0AB8AD81C92F2B828D24A43B1578887221921E540B126F0DA5EEE076DB470A4FDF527EBAE93B7EA7CF42C9682E49EF3E4CCC72FC629AE1B0721BDD2F4EC59B9A09155E1B7E63011C5C1EC5522EEE1E459BF3A3ED055091D1924B9F414B7E9BD1C4775030AA20EA248A74BA4B34A648C9CA534F6981971306802F4E54190E27C76A1FB599D5AE57D96E0B4815E45F25ABF474DA2546D37F0F11C567BDADA2300A1F1EEA44B27EB2EA7F7917B0A8E81E39D9361DA2879A8549D46036F2909BDB8E5658E64A9FBD36367D492C7C6384EB1388906834531FAAE43B5FBA2845213E12471843E1FB255460D849B47F6853927FC23DDABD30E9FD1D41EB6A166A4E27AB8E948E792239A6DCE9FBB7E065D4F0414807B79EBC8BA3874E5679C9D551AC4260DEFF48C3F50C534CBD68FB64D6FB6B333DBDF98F553E97!
0F1E883B7D25095F5066E94A545320568E8637014237C600102A8D1F556534!
06611963
F029F4168C9EBD1A6154BD4BB8DD0864D600AFDDD2C4E8DE538FB9C0493B6CC69AD2D73914D933E75817C12318D693923B717BF3142CA354723DD6F04F907473A4180441D10760A3A1DFE2C5A7422DD5E449815F9E42DA63595FB0DECB25F03CA120B90389DAC9241F705E40F7E397910A1190B17791C01620BC8DFEA44D5924069D79DA45877649283888AAA5509C96031888A778A7E26A9A9543BEF383D5F3EFFC4DC2A5607F2D168EDD1A17DC7C30D1D1635075093EEB4238345C76B0C895E0FD503D6B21BFF289086B9601144D0868DF0751B6F6A0F259620715D6C874DF8320A7A89779D392E64BD391816F24B1B328F826FF887F36E638E8D7C9C1FAE513D6CDEB50C59A01F3FDDBDFEF1F5734FF737C68ED9CEC77D41B76B70E307BCC357084820F420AD11DB361EB1757DA3B360BB4F920FC4A5AC4F8B18468E253C067ADE240F4A7F94B28CF12C4DD7BB9CEFE472B3D60434CC03683598366AC08E7CB5C954830F5188656D25234D67DB9AFF548DFA4D271B4EC76DF1331B1B2E500CD584E4617F8EC61EB61968E6C031CB0329B4ED6360773911951491A49E333B45FAB2E03F9F09335A0C20641EDD5904272730A15A3B38A99EC0B9FA2232D3F2649232D44CE64B9CF9E987A56BFF1D07FDBE93A5B54EF3C2641079C6F57145AD220E928D8AC5667B0085AA0EF88D46!
E2E6E8D5F035F291FC7474E3751E373607A1BB1A4A10F035C1C77BCC40C3062F4140B26E370856A038449D628887349AF2B7E037102B6EE064443E5CB38F5FC82AA3D8EA50633F3F8F5547BFA1868C46AFAE139E7FC9AF60F0C3290B1E1E9479947822FF3A50AAA3D6339844482E22C55A9FDB7A1915F9F631DD44EE28E064A6528134420F268890A4D146D0E4DAE7F95ACBB355471F7F0D2D0E9A739EFE2214A4C9A56484E9C92097AAD510930088C0041CE8DB027BD1A91B08B0EB23FD3B70B1911A2A201210475AB40411470C2764A4E8B9BEFDB94EB2229D47488D614565F1931E70C177A167429EBB9EF323AD7C79342846FE49E9FE8717C1FC909E0C43A3C949D5915F9683C5C0934FD06C978B5B9F94AE5C58F69C5E1CA42D73BCB5B538D91A140759DFE009222883E2662C6BCD816624CFFC6EEFD5EBE12BC9429FCBCFAFD19095B1F8385AC9ED85AF30CAF91C254CDAF2BDDFEEEDED79BFF57E8B72D69DCF55D83EA6CA87649B00B5251660BF67EC84593BE0AE37E73D6C77AEABF9389DDBF35834F5B153D0ED18390EA91FBB3BBB2E34BE0B5501CD80CDB15F71B47EF17DBACAC5C61E1946187066E8023D092E041519881C3DA9CD2C4AFFB236629E5DB9E2F312CFA4D9CEA31F9F7B3A93C409441D58F0A42DFF364B61C4485CFD601831DCC2D3DCA2718651835D49!
305F307FD92DBB4EA6723A876779AD8C9E85961D3EFAF2C0030E7B8C217DB3!
A7AFA8A9
46E0AD5800F8B749FA321030F2D434413EE8B9EE5CB9EC103413E9EA235894DBB56A75E292C8385956ABD3292C144BF72F4E3A5AFB062F5F6EDDFAECCAC54F5E62EA24DF996930D8EA04C7B7FCA893B604104832EA14CBC5A2A41FC80A0F78B52100D8DC9DCF7F0BEBCEA6AE5E8FDEE0121DE18AC8B2F78761BEE0079A1ABE0E8752FF1A7B2861AA63AD14A0AE17FB2A5C04B86C105173B0F731F897477D9ECBDE170AA3DD47E71EB92C50E0643249C5529E0AEECEC6971F7FFC384D92DEECC98F1FFB7CEF94033D80A7AEDD6A81A3095500DF426F2442A5B9E0DB0BC491E8725ED723F28D46C61B74067604A4F40FDFB27354F5C1E41AEAD11B85C75A2878F650C8A6244F2F2ABC20E40DC460F05D67C14CE1AF381EBAC8C813D16A0FC70CB44A451EAA1756A63A1B04FD870D3A782178E8D33C93E42F5AA1EC240B724DF2995107AB292A5EE449D82C50C1F84E8B4508B8C5A4351874A2256E5E1DF0AC975227276CCD3E2CD53AF28145F9C4C7573FFBE493932B9F1DA70507E262B541716B50DB2A4AA2925E4D00D0C2DB44224249E3E2ACCD254568E6F3CF250729B8C65C88EC585E77D8130F494A7F848FF2F7B120A91D16CB00CF542886866C9B53A4A3AD0E3D3E3C7B2A0BE9B30662C97876824850EEFB4DEAC57A5EAA420F316635F2C87794CD8A42E5A72377D7E565960!
42CF18FC021A4A380D36D8FF1DBD0AA4AE50C94870235D3825CE451A2281B8DFA4E622FF55577062AF996846D14066B59A32C95BD28B57BF9E0F4D1F77C3FEFD1E441C4298FBABDB35FF3F930D3D63ACAE3497391CD1F76281EF924AD628A23012EB0C65BE267812FF4D0080063106078C07D85C8D2AAAF2A2D3F1C71C2D2A7CE3F0B661D1B749C892B8E025833CFBD5AB75C73DC2C9BA027CBA6CC420717A59805A144897CECCB4FAE9EBF70F5B35B5B01CABCA4F20B83EF6E2D6A5BD2257AA9E3635084E9AA7CE779BB8818EA90ED2398E835605119AD19A323CC51349B79ACED87C3E69176FD2030364262A27663D86614C96BF2E8CEBD95CB260D1AA4515315BEB64A3A36694C2E1F87879C3AFB9C034841F5E91A9E52144D6A1E365CD2085B275064129E1A35D9CEA3A702826F4056C0D71424FF4BEF1F416AA06B896352247A4803B03AC1C25F5AF91608DAC8358ABA437B4CAE24779631CFE73DA146C7B67DD4A9F9BD1DF8791DB32340DD8CE1F30C6C17167159CBA483BFC59292733CC5CFCFD9C4365B7CC1DA6180B508C415B56AA55C9105114A9204BC23204B1E5740150C0A23FE3A90170137D86249144114D3A3CD8FB7E868EAE1A2437B3AFC8E85CD4F99781C79BEFCA119D596B0D19397C9B4541278B4565AD6F0FD8EA43A2DFEEEEA272FB7B6CEBE146CE9CB7!
7E870711CDEF46A1DA074A438B4F8DF159BB46CE91019A1AC2188386A943C5!
4661CB1A
5E719B5373C15213EEAE44A334D41C9AF9BE1EBB08139D26BC9325DBAD7850DA994B895ED72B30B3DEB95280DA5681A5D6B80A79B0B548F94DA7B46A98B3E41359CA77C158AD2B5531831C7D0A60F16B0568A841A220D6C48424E8E51509192104CF96098CCD3187EAC3C02F2F416C8D323FD28F0F3C98FAFD6F66072FB14CC54DB84905B2B2F67D6069C14A843B2D240745FEB0F14DC2CA0EFC2F7225F5F611054342C0E62CC21C4E2561246316A0FF5711691A72D78C4A62C18F8D102473F929EAABE0401120DC6450CA2C8EE1E1621B77C3A34E05643EAD682452B22C086FD22B1363E846328FCE5A6D9942765D5E1C05A70D1FDFB172F7EB8AC559366117FB777FEFC67C7D59BB76E7D5633541AC6E5C8CBE9E1161013BAD4050840AA3214046A24166EC2E3C5EC7D2E7906250A70280F235854317674258B37859426469642023A82F6832D6C70EE28966113C3E1419B0A8F342382483AEA51178CD906CD7EAD2BB59E26364E6DAF3418437B2464A1299ED6B903040EC021AB64BA11070234AA965C1334DAD894837121105B334DE4E556E7F0DE8DC9C520AB35C80538681C9D50B8CFD04E7863637FDD6D211F391BE75E7C73FD2F678F769CC464FBB38A23E8441248E23E3AF778E68CFA6EC549728C9C775D8C392F584DA96C936F3134A24D074C6144831593E40C257667!
8A9C1126C6174C23FFF06A3C733C0C7D6AB8456462B18C0EC91A5E18DA2E4D42891028022EB20B0F9FF3819C3A6981145A3B295247510D834604D1FD0F4F1049E9F24AB536F8EC4AEDF8D36B6F5F3B7CD9397BEFD6D6B1C047A4C49A7FB838B9B015C13C4BBEF60E0645A102A290D89AE988E50C83465C9DE197A3266A19B920C0D550D5F7F770B9315420A44A0F476576F0F415A20A68DB5E10F1BC1A06C26D9E81B07275C024924E8EB21F5D3FD77BF4797DDACD7DCB8C1595C9770276F3117112AD4A8FB62753EB728E1FF187E4F563A019A85A92152AC4A3866717776266B43BDBD8E565103651FA20DBA9A1A6AED0B7C36CD3DBDDDFD8CD609A924151A1C08C92F6B25C4F7B75C3A6BE0F51607B7FCC24BCD578C8CB83876F440E8B56A374D2D7227DAE2431141670E66CC7CC8348F19B13690FBFE0E44B8B932404412F12410270F398B45A5698275966B5F464923A168D9A8E08827C760D18D56ED7E2B40A37FBB50F0F4A57AEA4CBDAF2DAB50B2FAF5DF9F0FCD56BFFC74573EBE6ADB3B73EBB60A4E35A1A33358787930B0B748A66C15163B988215187CB0F8E8B8AA83BE6E8CE1FEE4858DC397A132E973B65DD54C04C0F1948FF90B4B323641AFC5E92CEB061BD87AC22BEAAA859BB7B3A4703C17869C541E6E92A1E82E1A67D07CF7ABB4ADB95AB67859CAF34C9E7!
D5144A0F905C57ABC1665E0215A113698963831FA2E16FD85B0DDB6EF97404!
D7E64A75
3B05084B2CF4668F367A982879CA3035BEAEEA68F080A3E350D38A29983097B2314A300B2CEDC8B710D95330A4B1C92A47AD690C0AFD5C28CB0FECA891638330C7D6DBBA52D1317460278D88889A6427C91B5290E0281671DA23658A2987A3A78761943B67E6692AB04346EE5C594DC13E5A2CEC9B05923F97EA26C165967E352B5DBC7850C285C77259BB76EDFCCBEFCFFFF987E73F79FBCAD9DBF76EDDBA5A7C89AD190C83A3A8F6F6310600882000A2EFF29D69D1720E75D8285DD9E7F1DDBB71BEF7B01D18D8D5B4622C97FFF80EB6AD3FDA451B74A19E1F79E8DD29D7EF116F35AC2F5137F4E78DC6DC0FBBBC2443EF2F107A5430EA2C4C66A9EAAFA9B6150CD3A03E8348C30C1A5D3B0A99BDDC6DA82CA87E04C2091306B8E6F9B9591581A96F318912C4D456C3A4D07294422668BB9F1552CBDA08BD74FCC835762166D7BE16D4509D828F94A5C3DA07EEB47C0536FF583264A4570196F5E19FB686BE4E8F6DFAC01AD83EB85A71A8AC884D056F337430348896A97CFD18F6B0695F401E11D0473251A8F90EF34DC1C318070DD8D7F33D75E81DE5A36B465870ECA334B6E5732FAB84441369F297CBB72F5E395FBBF69F3EF9FEDA9F7FF869F1DEEDB3F76EDE2A5E3DEB551DA78A1032E6E4B0B3B07F2F045E428E18D9DECBAF8BE6427EF20C8BD851F9CEEFF67EFBF9907!
AC482856E28948609E351A8B69E792CC18C0A5E0C4375A2CA7566A4F59E03037BED1C4A779192BA315D11BB9016EEB21885E9A800F92208AE79FCB8DCAB5C5B3B5B091A91FD3F378445CC74BB40CE6CEC8386FA103762DEB11A883D36D441C9CFA9F9466F4D13EB0E9EE8ED101F463E8ACA3CA5726BE85B4D36364C709FA16C36EEFE144113666956C94597ADEE020329A44539C888BA54F12D9A85FA141298ADA1066E311E3F6FA819494389F5C83110D10CBA35942413A48EEB98E7988473DAA3EDD982996810EAC41C9FE5E5426D403CCE851849213352A4B11786BA3E4B41080D07CF252EA627693545553BA97DF81FFEB7F3E7AF5D3BFEE4FC950F6BB7EFDD3B7BFBA620EBB335A73AA557F9B47A72E142E84734A60AD19FA196019371E521C964D196F7D3E69EC048A78D378099A9EA2000690F06C3D2A8A96903DA338991D7EDD7AC647B5E83B60C44CC4D3D24A13C28981B5D9FAAF8DD79586C5A1B58045BA3837C130AE045E65225644B21522BAB483DF68A6AD608010A559F915A15A9405B033ED8E0798030D6450859E959FA60452A32CB5990C13585B4C21D16C795CE9672462CB001654CF7E2B6F8E830D33391A76D1611195463310202DEB44AF9AB59A25D62E59B13EB796D899379F8F876F7C67519258556934BBF66B83F7533A71A5703844B101AC77531687!
C1EE89A63C10819A85DDD20B403031C7D100FA54B8D461B965AE390F21604D!
B1821002
87B77A2C3809631CBB45AADD6CE9FFFABFFF0F6B5F3D7AE9CFFE4D3E2D97BB7EF5DBAF572EBEC67D2E4D7CC34AD0A54ABBE7D7C61C0A75118920D12A9BD5487E62ED0277ADE35C6F666479C2CBE7E756A1503F26A0374C6A106107A7E64259D25498B2F11311CB6D5E79546210DA5A1A1F2A8DB50181E153B748FA1D21A9D88BB547D2D54A4BBE2F0511D3E6C0F867C13690BAF86439E6A944656DCBA81E88C88B33023C02657D7AE736A42F275BD0845FD82F2B05A65E58F353C390369D830DFD45E99032393D83BB4D06628DE519B11E60DBE19CD666E4AAB4DE85EE9515040F94BBB18434B24083EB29D8022EA286FD174F116E52B2FD5CFD775AF1640CE224C9C7DF3F15BDF3811B41D9CCCF899C931B1005B0E821611DD7B1148A1AAE802E9D7B8605B74907930348CB0450907C545945FA868AA93AF5850D6D6E2C2F3DA32F51B917469B597835BD7FEE66FAE5CBB52FBECECD94BF7EE5DBA7DEFB8DA41102DAB907394E03C3939FF59C85BEC01F81FD89DD9E8A14848C3630AE599FD9DB29D452382A448492F85BDD87CDE1DF256430DF542943BAD62962ED2E66E15D8AA51D471A27585A5271155D6B4ED576BCD8632026328AC2396469551C13A93A73A3C6AAC2CCD435BCB7C759EEEAECE60BBBA08EBCE7E7CEE5181468C2A87A5F60E7ED0E5B33468A83960A4C52B0A!
7DBA76859DB80FC12D85CFCC3B0C1DF973BC8B3DDDF0732111CA76904562F807696142EF0565F5AF3847F2D906A87FCE93A71BFEEAEC087F1E0E9416A2FED388A3CEE62294465E31BAAF07D5C638A327E79ECC1C892579DB089C8E50C74A88738EA4F37D8C2F1F3EDEC8F4D256BEF4C5A0A80B325DB0814892BA4FCE9D1B710D62628E1E6D2F19785BC72F8F9720AA2181155FDEBB54FCF3BFF9F7578A672FDDFACF1242B77F713B340B69D03E7B399D54ABD3EAA43A39393EF6A161DD64190BB59A46112A8EBA96C9036D9AD64F484D18F6F620EE2919A8D19DC7E9DD14DB7B7D07163364A4D702895E87AF69CDF99AFD1A4D101B3A0EECEAAFBC9F274CB666E824B9E6250733CA98AE21C5726EA0886C82077765C6D720AF0D1D5DC372921A5E4E4342DCC1AB34F6E60A8D7216231A3249AF46BAB5005D5C3BF456FB4AA41C0C6894DBC184C1860CA7C17644B91A5B49F66E6CA25FD461241EBCC0EACA46DC9181F1CA4FA169C4E90B6817CC9EE62490D0BA0D59B733DBDF83709B15B28D59CF497B30FF83A25B908C76CEBDF8E5C6283F62D1711304AB3A8BD00ECE4376F70BBB1B4430922425CD7E0AD7442C3D2C235FDE3B19650E3787D1EA7435D44F7BEBF8F8C2A786B36E7F30D8FAC52F6E5DBB58DABA74A91C1625886E76F08FBC75F6ECD54F9655C143E974F9F69597!
B59A1ABEF269D716D0D51660248D15C2A759E69CA86C1BB17008A7C5BDE11E!
4A91649C
D76D54AE21B88BF4D4FB5754B526961E04D1EDF66A36ADBD1B4F85DA3A3E6AAA309B8483DA352280B409B3794A4F07B07BCB3DD3D586065869B3D1B073518C46198E2B9C8D015419334AC61993A0BAA6B7AD824EC8091478385A5794192431B63908A5CC2945301C84560EC9B71A925DCB532C582E34B6662C51B613C75C53D76A901EA10B8D3D86F43D0B7F38CDB5D04CD728BAEC8898B30A2DE0A780C3F1C83BBD8254955C2B040BE2A2540E79AF8167C929811D0B4180453AED480288D965619C2C3D3D2FCB83E63B155E4037002AE460A06973EBD36A74A14625D1A038ADFD977B176ACFA5AFBF578C8A376FDF6B6315ECDDBA79F6EC27DFD7A6CB6975BA3C397FA1B63C84501ABEB10D65A930BAB50F824F8747E7C5706F48230FDC923558D88A5872B4DB8DA196B9A3BCD449C35FE49FDA76DF460B22A22C9F0E44010C22250140B318309EEF91CF8324BD696AE1A29670A77DEA4CCC49934754646DD075B0C8A3FD862263C2211AD374B10C94A8903FDEE4A840078FD8CF72D55BE071501C78E18A650892AA5685FC99B99A3DF1461B2933545E13256EBA739F9ADCAB8CE2DBFD2C26E1BD8CE411FBA845BC74D4CE9F8BB6C822E928DCCEA55FF8370FF4EFA74A8B974F0438630AF4CA24760C15ABE47D5A78D5533652622CBAA12204224362497E92CC205D7EA463C6887!
3828EF4090320F045A465976C32C6F1D6F149F5F802A64F52285F965E6E15B72EDDBC79E9D24D89A1DB451CCA06C75BF76E9EBDFAF2BC994EAF4C4FDEFE5E82E8DA803E6CF25FD75F4466EAF0EC89071F80D8E0B9CFC9A80FD5F86C085259BB2CB1A4D00784D90E0FA8C33FDAE4E7A154D698696BC96CAEAE1635F1B46DA2F175D48C1D5897D85E35906176FD460C35ECB58E0AAF6B1163A6885635ADCB90E29472931E8D6123B2E949F543BC7603FC93CAC68F9F6C54D2B99FDF417336834FEF6B9EB0A21AA7948FAE52E6BA795C31B262351AC3568D6625AB9DAACAACE077D8A0C0EADE1EAC0576DB920476E81E588EA5658E502842377381979B3A47512E1312E111893A037202902A3D3D638A229D38D00F9DC7685E2B4BD9EC45387C247708FD9B67B19E51E771CE2598A0B401DDFABE7A52AD812A29FFC0CF8EABB73018FA83406A29661829A226B66FDD3B7BF6B3E3E57259AB4910BD0C6AD78E03985C63765E83BC5109A76DDE0043A20E5541E8ED61AD5F2D673F949E6B6FD86896EF14F35E4DDF019B90E25151024737FEC034F25F6725C227A58DA3CC763B77AA6EE864B0DD6EE6198B601B798B33CB951A6D6EC467CB59E8A9392C7ECDCDD36D358BA81AC8ECAA8AFE8AE4C395C5B48E94489935790640006CDB3D07A182BA9B84619E90ACD6397892B43F0A2D54A!
375623E1CD63707C03E2D750612E8EA8CFA3DE3AD286776F06371586045EAF!
40612478
4814AD66187B9B0676EE4FE046491702D1DF07449878968BC7420A1CDA06E976158BA51E11A46F73BD2BE91051929DBC4334CDBA06EABB14BA464DCB078ED64727292EAF649DAF97B976EDEBA794F5E6EDA89D540E09604D1D5E3EAB47678EDED6B9FD4A687B5DA96A139C422082E1C1F0F06C7D1802B158FB7F99E69DAE320BA2C42D40A1D97C0EB3237A947B9563A848BF494A87854CC2B9920A522D0B1249E625BB34FD36BAC1E742D13F44B6BCA7790BBB626F7B2F25A145AAF079B7AF47BD66C7AAA871EDA4E0D12DD0D1D672ABC66A7BF69BB387925DFE25A019A866253D44B8E1D3673FBD9C892B8D4016DE580651D46FC600EDA1BA111D5FCBD79CAFB7DDC4F87B65BCE3B76E84EFB2B04AD43BFE89456ADA9C586C78A54B0EA3A25230033C3F9015925D4EC81DE5F1E12932594924FF4FDC0D9EE9047175A6E12DDA8511C23BDC596143420BD7A4582C40782CF448E48145AD9604FC5E42506AE9C48323251B829054D12D1BD2DECCB6EDF2CAE3624D14240D1D997D596B46727D76A124CB54F6F05CBA0767C2CE5AE56ABA90B1F8613814A93C37911FB0D1B4AA124A0E251D86D949541D45621EB372E3E70E8B1D79D9B212ACEF0B52EEDAD8F5E835E7C1628497229173B65493A115C82B342971325826A642A05DD61CE4352608D47A0613BB1D03B6DF91B9BB6E850!
739F57B2BA6B43D6964F9E39BB15C7FA1171B814A094D94F80EF2BB719C6B382684CF7BE55F9B02F693CE7256CC3FEADEAC7E681F5075B49A5A3AA189E4AFD9160675386870735B2DCA45C2B5DE9047A1D6974DD45D2900ECB23BD58B335AC10F0040E9F3BD491A26533B49CAC00B24A4EFC0815E6631BD87302BD5D0A6A4C810B96B341473FDC630EB20BBBD5295FF1D3E59565B5EA381C7C05B725139DBD79F6F6ED8EC41F090498756F49647D56CD9CEADB57CE9F54A7D3DA85ADDA325D9AE07071E165F1E585E3C131A9018067D603361CBE71257454BEF307308A8A366F34DF5CCCA24B6B2386F61AD2C5E9A891178CF03D6772CA8150B3D8A67A3A5AB036D7F9B46FCCF1B33521EEE42DDC824E589E2498C8B796D604BA74366F587D492B7B95972CEBB0B732D9A3ED08162F9C2ACD0B71EE84E5B760B20C62916FED0DAC5136D55D102CB8E39EE37AC41E2AC65DCF26C446E4EBF3395AF5DE76B12AAD752B20979B4983EF12E4445AC5CFB659C21A9F91152E94D248713F464268479008A648FDF5EC6235F031D6C73BD3A31B9F2F0C1FAA96B4EE4C106E0BF937D4F8FECFB96C0D818C22EBDF1C8579B18E00C00718750FB63E9510C24BBAC4D0BA78FBF6ED4BB72E6C75500E3923C0926570EFD6D5B38BB47AE5E4DA3579D765ED65B716D4D2D2C66CED09CE66935AB4!
D8CE29B828673AFC812607935147C0C4DC344EFB79A971D2BDC99FDADBA1E6!
EBD3CE0C
E1D568B7ED412DFA3D72B7818721048AB7143BC04C1D651B35B582110C75DAB98D1A43643357B6524E910E2BF1CD2836F362E645A7DAFB2AC98F615498ABCC527DA66B9DD41BF65D1A5E0CE98511149F733918A83AA871A35E1115E42586660C4DB438DFF4980EF5B3B14B56E40B8B381ECE68366034112DB75453DA3F75B9C28452C541B88DC3213D5DED259365BB592B6624995353AC8167F1D940339BC49D641A9F3C249A78ACB095D2ABF574D2CB4F841620B38159C680C6CB20D7C05FD8992ABE6E0922294C5309A129EE179769ABB3553CAE5EA96DE9C70C16D2DA49B377F366F1EC9614AE6B9F4AE9ABD61683495A5B1A5375CF41CEF087B36A92061AAB789C3CE3B198F1FEB5B987B3F891338AA59A49A2B0FD5753426C78F4C678A8583E2AE62D5A532744EDF640F7F98A956C3A9286BD6B00531A21DB6F1D1E691459AE59DB068F6717F9F81FC18D5AA2F1087F67DCC4DB4B35CF3AD3E818B1B19A23F98591E3DB2C6795D91A764EA7A224F63A429AAD74347B74AE5F50CCDDD0A64E6332E4B536A158DB8ADA28B50CBEF63A700BECA94FC465806EF89DDD474FB282B19C6C4D57AABF06BD09EED5228FC7DA714B275688E5743CEB9113A7FE5EBAAF552CC54D1FE86B11C310AFD518914C661C2C45F9D41CDBF9C0230F4DBE1E3FC77F845EDADB452A2B88FB5B4932C!
5DA729A6A3672264EB576E5E4ED2B578A9DFF8FAAABE76D1CBBA26CD4B110220F04042C1750B550BDD30EA6509FC295C1CE81AB459C3F9172E1EDB240D2F0E3812BD224C159722D600ABB588DAB40C8040966A610B0B177A689A03F907BCEBD8F9E918D1919A2249BBCBA9FE79CABF3DB24AB250626E10FDF5F5E2ECECF5F1CB6DBF8CD5598052EDACCB3FDFE31B8FA40C04AE0ECCCF655BD0A660FD5C8F0A8AADF384AFB543DD48C44F0377979B7DB0D5F0042EAA77FF4B8566B2D781F32B525D12E257E85E21F1026CAF641C7AADE8672DF83B44BF6D42832F37B62A2D95ACFA7964EF28475B427D4955F7D94EB5D3CAFA414499A14E04B8D85BCC99B0185C6AB1D147E13A4F229D322F1C8CB54B73F64E3F37E34BF913CB1459053223405D79B6B15930CBC7E8489BAF2F5325D4704DF83C90666A1EB944414EEAF562040A6B003767C720F55B2C99B955C066AE36B299EDBB1C184712A74864138B26999D682097F1FDF83240FEEF27401138AE46B7B9C1FDE2D8EC79363BC087B424E8C48177E2B36745CFCF99DC4B2C75F4F7BC99E34EF96A8F7DFF005C2237B4F5CCFD1D6814F85084203427686127E369A894119679F9B9018C227C98EB89D7A8606A364D3210C4977C854B57118992BD70F2D919466645A919164D481EE082CD958DFAB75E418DA8695CEF8BB910150F!
970E89BDC4CD07D8EE5D0A2F2EAB3035BDE142059396573786A7DBBD70A4BD!
B3A24BE2
99F6D72FFD5F3FBC9B873EB69863752C7BC3B63F3BA21A49AD7DE48D9CE274D9E62026012C4CB03950355319C9EBDC5BC4F8BCD3D36AFAB06BB35BB55B8361B6528CC9E10E938BA405B4847812EB32E54603010544A8124BF5C586DA4371EEF6C6691EF7F419F39144F142942763A5F2CDE1CB767D3B39393C796491BD8D240CB9F5E3EC68F97A7617B7A797A09EC629AEC31E0ED8934C9DB7ED5FAC51B7247C259D59A980C853DEBFC13C81CA542172DA45D7821073492980995034CE8013E48B942C8875899B56C3BD66CDB94558BF9553A29B45724BF9E62426C105F420034570B62EC4ABB15A82058136C49AE3E461581DA9ADA30A1959A5B6E01AD3460221F19541B729548887BE615CC882C4725A31FE8407942D49E51FE0090FAA6098017EAAC48337052E619407BA3D4B24437B091BD83F285B4ABE8941D92A5DAAA049B94BC23874E3A17B2A9F938F342EC0DCA9D75E421D74A18204DAE6F7B6394984341C8710A60D95BD5B7CF80F008A085403D010F93B3FDBF381801591C493C8FA6B0A1631C1F8FC7F9C9D9D9597C127F8F4E8118110341DD9EFE1A9A74C3BEEA4349943EE00F96470171EC55DB012B5EA833137891E1EF349E9536FF1A3D1107FCD4B5FE1CDD38948C63401ED54667D3B159B567D75A0C47A71015D70D373BDF3CAABCD016557E6A7A0C0A586B6F!
0800A1DBDF2F9FDD3EBB5D4E52CBA2F83C9FDAF84EA4360758C1F95E12CEDADD28640C797553E5630E6352359B574DA0590F1A8545EAFB8C1EAA8D9F5462577B160D86FF725927B622BC596B72D26BC61B456B1A44D670514CB1F6533637EEF95489CF9F223205D8A582943B10B44EC3A2F3FC6B9823E027241E60726112200010399BA33803E86BAB801047228ADEBE7DBB8C96CFFF1899CC7E626D221E0EAD45F560925ACFCFFE763C919B58D0F4388FE7F2431C9F5F9DB6EA676A3A3C4CEE29DC40345E06EC46AA931F316939E1D81B7C7121DF2D14F53F97FE98813D2D8E61C83934A3D99428CFAA8B9936AC614124F07873D28987C523FC6820D8DC1F1292885FD749695BAC877C5C980608196AF44275F435D3D92D6F772A8BEE93254BC2757EABF37C57FACF99769F0D210936ED4EB3E42131C1243F8AD014683D510D50389EAF155159DAB62AA6D74AFB268B80D06E63A54120145F4D114DA2CDCDCB7F7CF5FC56EE4922745DD8BE239B6C9834ECDA53D5E09D1C7518B4A2DB1331BF6EDA042354FA45780B8C53597C71872E192019B3670923561E6A9A0C9E2149CF9634138306518780607DFA465D4FC5991A5B089232F77B22A55C1B7E737E368D4FA647F99E1E8FF19B9816159FF74A0CE188DEF10CE38C71B69911FA2EE1C02555BBA2E667B85224C805625A505A!
8FC8F71387D250450A64FCE286B6A32DAD0AC9EF48724001A4F612979D1B77!
48A5F559
A5C36790D588963541B394D66FAB2475F422487F288A55E6C9E0F73554B93E9969326354A96B1EEC7AEB4276A604D10D195FA9B37148977C714BAD442796DA23950ADD945D7C5D24F92AA99423C2141F58DE51D2AA04D3287A36F9B953045A47AD246EB8C6BAE99F7EBE361C6C460123A5AD719696D948DFD25F6C18E7E5015B474A750633EE03E1675CCB26DEF63883D48774C6EE775EDA084C21801082E8BE71FD0BA76684CB5CC34AEA1E6D1E093B8EC20D592065D71C6221D9822DE81ED377D57E48BFD9C78C63E2874EA4808FA5088311C58F61D430874222C6AE63E0C270AFF1CD66546CCC94AD52F28194E522CE26C8753F1E4DE8FDFBF7D60D1A927257FC75A788B42A7FC23BCE4C702F874C23F4D0811C69E1672A659AE1533C886DCCBC081F9D559593DA98D42AE7389449A0BC0CE8810EA31EE88ABAFBF25FA561CEE9B0D51AD7A5DFAA0E0953D84EF3AF3FDD243FD27D3BBF9AB5F47B4175445226493E8E46D8976C120C432068FB17A8FEB19FA97AD3F26128571CC36AA781595B273E2EDB8DDB6A6DC66612FD7EA405FD1FCB863D9E5127EF62498768B36D9A43136D965BD07A744D914D6B1DC41C890F5767E36AE476253505C06661EA93EBDC83A9CFFAFE77CB43967E68354383F8E6BE16332AB9C363FF4EC2EA613B8DA69B97DB68FB9F7FDF37CB28D07E961!
C001A6C70F987AB792C414C6F72F75C6C4AECEAFCBB45921D529DC4C9C1D1FDB21627587322EAA1D5F242959430C9E42510F24C56DB990BFE37D4E530B6167FABB0A6E5AEFB3BB1D5AA30631E0A1BF1C435617E3EA852DE1D3FDDB44F0E419374D770DBD4406F627AB1B5CED050026160788767034C13BD956248D5873581C1B5B993C73FA61F07DCE528AB03B3B5206D56E18D8023A0A6BA2EAEA3C45D37AF96AF6F3637B711B1D6AA53A40331EEDB23165B19FB26CCD9351D59B81FEF3EA6AA589B529FA6F3C357DB85B60B125273B3128189BF7BA7A244A3A283AD6B5837855565E28D1A93C882A24484BD76F3A67903910DB1A1E5349A37E42815D1E6D5A4990091D47949E58E751E93BC54DE9A7F3C2574D01350DD3FBC75DF6CE610D20B323D1D5DD77D60FE7E00F32C986FFFB97CFD7A8B8D5A4130D9502D245025B54D932ED228E87EF8F6EA402B3AC4EA8FA4C48FD12B4272D52D3276AE16998E5CFB003C42C219D4D4A552039CA7282C6D0140ECFF020C00AB15754C0DAAF1110000000049454E44AE426082');
+
+update Member set picture_id = -1 where memberid = -1;
+update Member set picture_id = -2 where memberid = -2;
+update Member set picture_id = -3 where memberid = -3;
+update Member set picture_id = -4 where memberid = -4;
+
+insert into AccountPermission (permissionId, recipient, target, action, discriminator)
values (-1, 'friends', 'MemberImage:5', 'view', 'role');
+insert into AccountPermission (permissionId, recipient, target, action, discriminator)
values (-2, 'user', 'MemberImage:6', 'view', 'role');
+
+insert into MemberBlog (blogid, member_id, entrydate, title, text) values (-1, -1,
'2007-01-05', 'My first blog entry!', '*Lorem ipsum* dolor sit amet,
consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.');
+insert into MemberBlog (blogid, member_id, entrydate, title, text) values (-2, -1,
'2007-01-07', 'I love latin', 'Sed ut perspiciatis unde omnis iste
natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque
ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt
explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro
quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia
non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat
voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit
laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure
reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum
qui dolorem eum fugiat quo voluptas nulla pariatur?');
+
+insert into BlogComment (commentid, blog_id, commentor_id, commentdate, comment) values
(-1, -1, -2, '2007-01-06', 'At vero eos et accusamus et iusto odio dignissimos
ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas
molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui
officia deserunt mollitia animi, id est laborum et dolorum fuga.');
+insert into BlogComment (commentid, blog_id, commentor_id, commentdate, comment) values
(-2, -1, -1, '2007-01-07', 'Et harum quidem rerum facilis est et expedita
distinctio.');
+
+insert into MemberFriend (id, member_id, friend_id, authorized) values (-1, -1, -2, -1);
+insert into MemberFriend (id, member_id, friend_id, authorized) values (-2, -2, -1, -1);
+insert into MemberFriend (id, member_id, friend_id, authorized) values (-3, -1, -3, -1);
+
+insert into FriendComment (id, member_id, friend_id, commentDate, comment) values (-1,
-1, -2, '2007-01-25', 'Cheer up!');
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-ejb/src/main/resources/seam.properties
===================================================================
Added: branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/pom.xml
===================================================================
--- branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/pom.xml
(rev 0)
+++ branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/pom.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>seamspace</artifactId>
+ <groupId>org.jboss.seam.examples-ee6</groupId>
+ <version>2.3.0.Beta2-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-tests</artifactId>
+ <name>SeamSpace Integration Tests Module (EE6)</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <classifier>jdk15</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+ <type>ejb</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam</artifactId>
+ <type>ejb</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium.server</groupId>
+ <artifactId>selenium-server</artifactId>
+ <classifier>standalone</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium.client-drivers</groupId>
+ <artifactId>selenium-java-client-driver</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>functional-tests</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ <testResource> <!-- this takes datasource seamspace-ds.xml -->
+
<directory>${basedir}/../seamspace-ear/src/main/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ <testResource> <!-- this takes themes aka *.properties -->
+
<directory>${basedir}/../seamspace-web/src/main/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>ftest-jbossas</id>
+ <properties>
+ <example.context.path>seam-seamspace</example.context.path>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>selenium-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>failsafe-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>ftest-tomcat</id>
+ <properties>
+
<example.context.path>jboss-seam-seamspace</example.context.path>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>selenium-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>failsafe-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/BlogTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/BlogTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/BlogTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,144 @@
+package org.jboss.seam.example.seamspace.test;
+
+import org.jboss.seam.mock.SeamTest;
+import org.testng.annotations.Test;
+
+public class BlogTest extends SeamTest
+{
+ @Test
+ public void testCreateBlog() throws Exception
+ {
+ // Log in first
+ new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ setValue("#{identity.username}", "demo");
+ setValue("#{identity.password}", "demo");
+ invokeAction("#{identity.login}");
+ assert getValue("#{identity.loggedIn}").equals(true);
+ }
+ }.run();
+
+ String cid = new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{blog.createEntry}") == null;
+ }
+ }.run();
+
+ new FacesRequest("/createBlog.xhtml", cid)
+ {
+ @Override
+ protected void updateModelValues() throws Exception
+ {
+ setValue("#{selectedBlog.title}", "A new blog entry");
+ setValue("#{selectedBlog.text}", "A very very very long
section of text. " +
+ "This text should be long enough to simulate a typical blog entry.
" +
+ "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed
interdum " +
+ "felis non arcu. Phasellus sodales pharetra dui. Suspendisse felis
turpis, " +
+ "ultricies a, ullamcorper sed, nonummy id, nulla. Ut quis orci.
Mauris diam " +
+ "pede, condimentum et, tempor vitae, facilisis non, sem. Mauris
quam ipsum, " +
+ "laoreet non, ultricies in, aliquet nec, metus. Morbi dui.
Vestibulum " +
+ "ullamcorper, tellus non hendrerit consequat, libero erat laoreet
metus, " +
+ "quis facilisis arcu diam vel orci. Fusce tempor erat eget odio.
Aliquam urna " +
+ "dui, dignissim id, pretium in, congue quis, est. Phasellus nec
erat ac arcu " +
+ "porttitor rhoncus. Pellentesque habitant morbi tristique senectus
et netus et " +
+ "malesuada fames ac turpis egestas. Nulla sed massa ut est sodales
ultrices. " +
+ "Sed vitae nulla eu tellus fringilla sagittis. Nunc convallis, mi
at lobortis " +
+ "rhoncus, neque turpis ullamcorper odio, quis scelerisque est
dolor non velit. Integer vulputate.");
+ }
+
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{blog.saveEntry}") == null;
+ }
+
+ }.run();
+
+ new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ invokeAction("#{identity.logout}");
+ assert getValue("#{identity.loggedIn}").equals(false);
+ }
+ }.run();
+ }
+
+ //@Test
+ public void testCreateComment() throws Exception
+ {
+ new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ setValue("#{identity.username}", "demo");
+ setValue("#{identity.password}", "demo");
+ invokeAction("#{identity.login}");
+ assert getValue("#{identity.loggedIn}").equals(true);
+ }
+ }.run();
+
+ String cid = new FacesRequest("/comment.xhtml")
+ {
+ @Override
+ protected void beforeRequest()
+ {
+ setParameter("name", "Mr_Smiley");
+ setParameter("blogId", "1");
+ }
+
+ @Override
+ protected void renderResponse() throws Exception
+ {
+ assert getValue("#{selectedBlog}") != null;
+ assert getValue("#{selectedBlog.blogId}").equals(1);
+ }
+ }.run();
+
+ new FacesRequest("/comment.xhtml", cid)
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{blog.createComment}") == null;
+
+ assert getValue("#{comment}") != null;
+ assert getValue("#{comment.blog}") != null;
+ }
+ }.run();
+
+ new FacesRequest("/comment.xhtml", cid)
+ {
+ @Override
+ protected void updateModelValues() throws Exception
+ {
+ setValue("#{comment.comment}", "I totally disagree with your
blog entry!");
+ }
+
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{blog.saveComment}") == null;
+ }
+ }.run();
+
+ new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ invokeAction("#{identity.logout}");
+ assert getValue("#{identity.loggedIn}").equals(false);
+ }
+ }.run();
+
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/RegisterTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/RegisterTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/RegisterTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,70 @@
+package org.jboss.seam.example.seamspace.test;
+
+import java.util.Date;
+
+import org.jboss.seam.core.Manager;
+import org.jboss.seam.mock.SeamTest;
+import org.testng.annotations.Test;
+
+public class RegisterTest extends SeamTest
+{
+ @Test
+ public void testRegister() throws Exception
+ {
+ String cid = new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{register.start}") == null;
+ }
+ }.run();
+
+ new FacesRequest("/register.xhtml", cid)
+ {
+ @Override
+ protected void updateModelValues() throws Exception
+ {
+ setValue("#{register.member.email}", "shane(a)test.com");
+ setValue("#{register.member.firstName}", "Shane");
+ setValue("#{register.member.lastName}", "Bryzak");
+ setValue("#{register.member.memberName}", "shane123");
+ setValue("#{register.username}", "sbryzak");
+ setValue("#{register.password}", "secret");
+ setValue("#{register.confirm}", "secret");
+ setValue("#{register.gender}", "Male");
+ setValue("#{register.member.dob}", new Date(107100000000L));
+ }
+
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{register.next}") == null;
+ }
+
+ }.run();
+
+ new FacesRequest("/register2.xhtml", cid)
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert invokeAction("#{register.uploadPicture}") == null;
+ assert !Manager.instance().isLongRunningConversation();
+ }
+
+ }.run();
+
+ new FacesRequest()
+ {
+ @Override
+ protected void invokeApplication() throws Exception
+ {
+ assert getValue("#{identity.loggedIn}").equals(true);
+ assert invokeAction("#{identity.logout}") == null;
+ assert getValue("#{identity.loggedIn}").equals(false);
+ }
+
+ }.run();
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/BlogTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/BlogTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/BlogTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.example.seamspace.test.selenium;
+
+import java.text.MessageFormat;
+
+import org.testng.annotations.Test;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ * This class tests blog functionality of SeamSpace application
+ * @author Jozef Hartinger
+ *
+ */
+public class BlogTest extends SeleniumSeamSpaceTest
+{
+
+ public static final String CREATE_BLOG_ENTRY = "id=createBlog";
+ public static final String VIEW_BLOG_ENTRY = "id=viewBlog";
+ public static final String BLOG_ENTRY_COUNT =
"//div[@class=\"blogEntry\"]";
+ public static final String NEW_BLOG_TITLE = "id=newBlog:title";
+ public static final String NEW_BLOG_TEXT = "id=newBlog:text";
+ public static final String NEW_BLOG_SUBMIT = "id=newBlog:submit";
+ public static final String NEW_BLOG_PREVIEW = "id=newBlog:preview";
+ public static final String BLOG_ENTRY_BY_TITLE =
"xpath=//div[@class=\"blogEntry\"][.//div[(a)class=\"blogTitle\"]/text()
= \"{0}\"]";
+ public static final String BLOG_ENTRY_TEXT =
"//div[@class=\"blogText\"]";
+
+ @Test
+ public void createBlogTest() {
+ String title = "What is Seam?";
+ String text = "Seam is a powerful open source development platform for
building rich Internet applications in Java. Seam integrates technologies such as
Asynchronous JavaScript and XML (AJAX), JavaServer Faces (JSF), Java Persistence (JPA),
Enterprise Java Beans (EJB 3.0) and Business Process Management (BPM) into a unified
full-stack solution, complete with sophisticated tooling.";
+ int blogCount = 0;
+
+ browser.clickAndWait(VIEW_BLOG_ENTRY);
+ blogCount = browser.getXpathCount(BLOG_ENTRY_COUNT).intValue();
+ browser.goBackAndWait();
+ browser.clickAndWait(CREATE_BLOG_ENTRY);
+ browser.type(NEW_BLOG_TITLE, title);
+ browser.type(NEW_BLOG_TEXT, text);
+ browser.clickAndWait(NEW_BLOG_SUBMIT);
+ assertEquals("Unexpected number of blog entries.", ++blogCount,
browser.getXpathCount(BLOG_ENTRY_COUNT).intValue());
+ String blogEntry = MessageFormat.format(BLOG_ENTRY_BY_TITLE, title);
+ assertTrue("Blog entry not found. " + blogEntry,
browser.isElementPresent(blogEntry));
+ assertEquals("Blog entry text has been modified.", text,
browser.getText(blogEntry + BLOG_ENTRY_TEXT));
+ }
+
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/FriendRequestTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/FriendRequestTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/FriendRequestTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.example.seamspace.test.selenium;
+
+import org.testng.annotations.Test;
+import static org.testng.AssertJUnit.assertTrue;
+
+
+/**
+ * This class tests "Send a friend request" at seamspace example. This
+ * option is available when user opens somebody's profile.
+ *
+ * @author Martin Gencur
+ *
+ */
+
+public class FriendRequestTest extends SeleniumSeamSpaceTest
+{
+ public static final String DUKE_IMAGE =
"xpath=//img[contains(@src,\"id=2\")]";
+ public static final String FRIEND_REQUEST_LINK = "link=Send a friend
request";
+ public static final String MESSAGE_AREA =
"xpath=//textarea[contains(@id,\"introduction\")]";
+ public static final String MESSAGE_TEXT = "Hi Duke, how are you?";
+ public static final String REQUEST_SEND_BUTTON =
"xpath=//input[contains(@value,\"Send request\")]";
+ public static final String REQUEST_SENT_MESSAGE = "Friend request sent";
+
+ @Test
+ public void sendFriendRequestText(){
+ browser.clickAndWait(DUKE_IMAGE);
+ browser.clickAndWait(FRIEND_REQUEST_LINK);
+ browser.type(MESSAGE_AREA, MESSAGE_TEXT);
+ browser.clickAndWait(REQUEST_SEND_BUTTON);
+ assertTrue("Friend request sent page
expected",browser.isTextPresent(REQUEST_SENT_MESSAGE));
+ }
+
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/LoginTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/LoginTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/LoginTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.example.seamspace.test.selenium;
+
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import org.testng.annotations.Test;
+
+/**
+ * Basic test covering user authentication
+ * @author Jozef Hartinger
+ *
+ */
+public class LoginTest extends SeleniumSeamSpaceTest
+{
+
+ @Test(groups = {"loginTest"})
+ public void loginTest() {
+ assertTrue("Login failed.", isLoggedIn());
+ }
+
+ @Test(dependsOnMethods = {"loginTest"})
+ public void logoutTest() {
+ browser.clickAndWait(LOGOUT);
+ assertFalse("Logout failed.", isLoggedIn());
+ }
+
+
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/RoleTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/RoleTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/RoleTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,120 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.example.seamspace.test.selenium;
+
+import java.text.MessageFormat;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.assertFalse;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * This class tests role management in SeamSpace application
+ * @author Jozef Hartinger
+ *
+ */
+public class RoleTest extends SeleniumSeamSpaceTest
+{
+
+ @Override
+ @BeforeMethod
+ public void setUp()
+ {
+ super.setUp();
+ browser.clickAndWait(SECURITY);
+ browser.clickAndWait(MANAGE_ROLES);
+ }
+
+ @Test(dependsOnGroups = {"loginTest"})
+ public void roleCreatingTest()
+ {
+ String roleName = "tester";
+ String[] roles = { "user", "admin" };
+ createNewRole(roleName, roles);
+ // check that new role is added to role list
+ String roleRow = MessageFormat.format(ROLE_TABLE_ROW_BY_NAME, roleName);
+ assertTrue("New role not found in role list.",
browser.isElementPresent(roleRow));
+ String roleTableRoles = browser.getText(roleRow + ROLE_TABLE_ROLES);
+ assertTrue("New role is not member of " + roles[0] + " role.",
roleTableRoles.contains(roles[0]));
+ assertTrue("New role is not member of " + roles[1] + " role.",
roleTableRoles.contains(roles[1]));
+ // check that new role is available to users
+ browser.clickAndWait(SECURITY);
+ browser.clickAndWait(MANAGE_USERS);
+ browser.clickAndWait(CREATE_USER_BUTTON);
+ String expectedRole = MessageFormat.format(USER_ROLE_BY_NAME_CHECKBOX, roleName);
+ assertTrue("New role is not available when creating new user.",
browser.isElementPresent(expectedRole));
+ }
+
+ @Test(dependsOnMethods = {"roleCreatingTest"})
+ public void roleEditingTest() {
+ String oldRoleName = "QA";
+ String[] oldRoles = {"user"};
+ String newRoleName = "QE";
+ String[] newRoles = {"user", "admin"};
+
+ createNewRole(oldRoleName, oldRoles);
+ String oldRoleRow = MessageFormat.format(ROLE_TABLE_ROW_BY_NAME, oldRoleName);
+ assertTrue("New role not found.", browser.isElementPresent(oldRoleRow));
+ assertFalse("New role should not be member of admin role.",
browser.getText(oldRoleRow + ROLE_TABLE_ROLES).contains("admin"));
+ browser.clickAndWait(oldRoleRow + ROLE_TABLE_EDIT);
+ fillRoleDetails(newRoleName, newRoles);
+ browser.clickAndWait(ROLE_SAVE);
+ String newRoleRow = MessageFormat.format(ROLE_TABLE_ROW_BY_NAME, newRoleName);
+ assertFalse("Old role still present.",
browser.isElementPresent(oldRoleRow));
+ assertTrue("Updated role not found in role table.",
browser.isElementPresent(newRoleRow));
+ String updatedRoleTableRoles = browser.getText(newRoleRow + ROLE_TABLE_ROLES);
+ assertTrue("New role is not member of " + newRoles[0] + "
role.", updatedRoleTableRoles.contains(newRoles[0]));
+ assertTrue("New role is not member of " + newRoles[1] + "
role.", updatedRoleTableRoles.contains(newRoles[1]));
+ }
+
+ @Test(dependsOnMethods = {"roleCreatingTest"})
+ public void roleDeletingTest() {
+ String roleName = "commiter";
+ String[] roles = {"user"};
+
+ createNewRole(roleName, roles);
+ String roleRow = MessageFormat.format(ROLE_TABLE_ROW_BY_NAME, roleName);
+ assertTrue("New role not found.", browser.isElementPresent(roleRow));
+ browser.chooseOkOnNextConfirmation();
+ browser.clickAndWait(roleRow + ROLE_TABLE_DELETE);
+ String confirmation = browser.getConfirmation();
+ assertTrue("Expected role deletion confirmation.",
confirmation.contains(ROLE_TABLE_DELETE_CONFIRMATION));
+ assertFalse("Removed role still present.",
browser.isElementPresent(roleRow));
+ }
+
+ public void createNewRole(String name, String[] roles) {
+ browser.clickAndWait(CREATE_ROLE_BUTTON);
+ fillRoleDetails(name, roles);
+ browser.clickAndWait(ROLE_SAVE);
+ }
+
+ public void fillRoleDetails(String name, String[] roles)
+ {
+ browser.type(ROLE_NAME, name);
+ for (String role : roles)
+ {
+ assertTrue("Role not available: " + role,
browser.isElementPresent(MessageFormat.format(ROLE_MEMBER_OF_BY_NAME_CHECKBOX, role)));
+ browser.check(MessageFormat.format(ROLE_MEMBER_OF_BY_NAME_CHECKBOX, role));
+ }
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/SeleniumSeamSpaceTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/SeleniumSeamSpaceTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/SeleniumSeamSpaceTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.example.seamspace.test.selenium;
+
+import org.jboss.seam.example.common.test.selenium.SeamSeleniumTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import static org.testng.AssertJUnit.fail;
+
+/**
+ *
+ * @author Jozef Hartinger
+ *
+ */
+public abstract class SeleniumSeamSpaceTest extends SeamSeleniumTest
+{
+
+ public static final String LOGIN = "id=login";
+ public static final String LOGOUT = "id=logout";
+ public static final String LOGIN_USERNAME = "id=loginForm:name";
+ public static final String LOGIN_PASSWORD = "id=loginForm:password";
+ public static final String LOGIN_LOGIN = "id=loginForm:login";
+ public static final String HOME_URL = "/home.seam";
+ public static final String SECURITY = "id=security";
+
+ public static final String MANAGE_USERS = "id=manageUsers";
+ public static final String CREATE_USER_BUTTON = "id=newUser";
+ public static final String USER_FIRSTNAME = "id=user:firstname";
+ public static final String USER_LASTNAME = "id=user:lastname";
+ public static final String USER_NAME = "id=user:username";
+ public static final String USER_PASSWORD = "id=user:password";
+ public static final String USER_CONFIRM = "id=user:confirm";
+ public static final String USER_ROLES = "id=user:roles";
+ public static final String USER_ROLE_BY_NAME_CHECKBOX =
"xpath=//input[contains(@id,
\"user:roles:\")][normalize-space(../label/text()) = \"{0}\"]";
+ public static final String USER_ENABLED = "id=user:enabled";
+ public static final String USER_SAVE = "id=user:save";
+ public static final String USER_CANCEL = "id=user:cancel";
+ public static final String USER_TABLE_ROW_BY_NAME =
"xpath=//table[(a)id=\"threads\"]/tbody/tr[normalize-space(./td[1]/text()) =
\"{0}\"]";
+ // these locators can only be used catenated with USER_TABLE_ROW_BY_NAME
+ public static final String USER_TABLE_ROLES = "/td[2]";
+ public static final String USER_TABLE_CHECKBOX_CHECKED =
"/td[3]/div[@class=\"checkmark\"]";
+ public static final String USER_TABLE_CHECKBOX_UNCHECKED =
"/td[3]/div[@class=\"cross\"]";
+ public static final String USER_TABLE_DELETE = "//a[contains(@id,
\"delete\")]";
+ public static final String USER_TABLE_EDIT = "//a[contains(@id,
\"edit\")]";
+
+ public static final String MANAGE_ROLES = "id=manageRoles";
+ public static final String CREATE_ROLE_BUTTON = "id=newRole";
+ public static final String ROLE_NAME = "id=role:name";
+ public static final String ROLE_ROLES = "id=role:roles";
+ public static final String ROLE_MEMBER_OF_BY_NAME_CHECKBOX =
"xpath=//input[contains(@id,
\"role:roles:\")][normalize-space(../label/text()) = \"{0}\"]";
+ public static final String ROLE_SAVE = "id=role:save";
+ public static final String ROLE_CANCEL = "id=role:cancel";
+ public static final String ROLE_TABLE_ROW_BY_NAME =
"xpath=//table[(a)id=\"threads\"]/tbody/tr[normalize-space(./td[1]/text()) =
\"{0}\"]";
+ // these locators can only be used catenated with ROLE_TABLE_ROW_BY_NAME
+ public static final String ROLE_TABLE_ROLES = "/td[2]";
+ public static final String ROLE_TABLE_DELETE = "//a[contains(@id,
\"delete\")]";
+ public static final String ROLE_TABLE_EDIT = "//a[contains(@id,
\"edit\")]";
+ public static final String ROLE_TABLE_DELETE_CONFIRMATION = "Are you sure you
wish to delete this role? This action cannot be undone.";
+
+ public static final String DEFAULT_USERNAME = "demo";
+ public static final String DEFAULT_PASSWORD = "demo";
+
+ @Override
+ @BeforeMethod
+ public void setUp() {
+ super.setUp();
+ browser.open(CONTEXT_PATH + HOME_URL);
+ if (!isLoggedIn()) {
+ login();
+ }
+ }
+
+ @Override
+ @AfterMethod
+ public void tearDown() {
+ if (isLoggedIn()){
+ browser.clickAndWait(LOGOUT);
+ }
+ }
+
+ public void login() {
+ login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
+ }
+
+ public void login(String username, String password) {
+ browser.clickAndWait(LOGIN);
+ browser.type(LOGIN_USERNAME, username);
+ browser.type(LOGIN_PASSWORD, password);
+ browser.clickAndWait(LOGIN_LOGIN);
+ }
+
+ protected boolean isLoggedIn()
+ {
+ return !browser.isElementPresent(LOGIN) &&
browser.isElementPresent(LOGOUT);
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/UserTest.java
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/UserTest.java
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/java/org/jboss/seam/example/seamspace/test/selenium/UserTest.java 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,146 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.seam.example.seamspace.test.selenium;
+
+import java.text.MessageFormat;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.assertFalse;
+
+/**
+ * This class tests user management in SeamSpace application
+ * @author Jozef Hartinger
+ *
+ */
+public class UserTest extends SeleniumSeamSpaceTest
+{
+
+ @Override
+ @BeforeMethod
+ public void setUp()
+ {
+ super.setUp();
+ browser.clickAndWait(SECURITY);
+ browser.clickAndWait(MANAGE_USERS);
+ }
+
+ @Test(dependsOnGroups = {"loginTest"})
+ public void userCreatingTest()
+ {
+ String username = "jharting";
+ String password = "topSecret";
+ String[] roles = {"admin", "user"};
+ createNewUser("Jozef", "Hartinger", username, password,
password, roles, true);
+ String userRow = MessageFormat.format(USER_TABLE_ROW_BY_NAME, username);
+ // check user list
+ assertTrue("User not found in userlist.",
browser.isElementPresent(userRow));
+ assertTrue("User not in admin role.", browser.getText(userRow +
USER_TABLE_ROLES).contains("admin"));
+ assertTrue("User not in user role.", browser.getText(userRow +
USER_TABLE_ROLES).contains("user"));
+ assertTrue("User not enabled.", browser.isElementPresent(userRow +
USER_TABLE_CHECKBOX_CHECKED));
+ // check new user can login
+ browser.clickAndWait(LOGOUT);
+ login(username, password);
+ assertTrue("Unable to login with new user's credentials.",
isLoggedIn());
+ }
+
+ @Test(dependsOnGroups = {"loginTest"})
+ public void userEditingTest() {
+ String username = "shadowman";
+ String password = "password";
+ String[] roles = {"admin", "user"};
+ String userRow = MessageFormat.format(USER_TABLE_ROW_BY_NAME, username);
+ browser.clickAndWait(userRow + USER_TABLE_EDIT);
+ fillUpdatableUserDetails(password, password, roles, true);
+ browser.clickAndWait(USER_SAVE);
+ assertTrue("User not in admin role.", browser.getText(userRow +
USER_TABLE_ROLES).contains("admin"));
+ assertTrue("User not in user role.", browser.getText(userRow +
USER_TABLE_ROLES).contains("user"));
+ browser.clickAndWait(LOGOUT);
+ login(username, password);
+ assertTrue("Unable to login with changed password", isLoggedIn());
+ }
+
+ @Test(dependsOnGroups = {"loginTest"})
+ public void userDeletingTest() {
+ String username = "mona";
+ String userRow = MessageFormat.format(USER_TABLE_ROW_BY_NAME, username);
+ assertTrue("User " + username + " not in user list.",
browser.isElementPresent(userRow));
+ browser.chooseOkOnNextConfirmation();
+ browser.click(userRow + USER_TABLE_DELETE);
+ browser.getConfirmation();
+ browser.waitForPageToLoad(TIMEOUT);
+ assertFalse("User " + username + " exists after deletion",
browser.isElementPresent(userRow));
+ }
+
+ @Test(dependsOnGroups = {"loginTest"})
+ public void cancelledUserDeletingTest() throws InterruptedException {
+ String username = "demo";
+ String userRow = MessageFormat.format(USER_TABLE_ROW_BY_NAME, username);
+ assertTrue("User " + username + " not in user list.",
browser.isElementPresent(userRow));
+ browser.chooseCancelOnNextConfirmation();
+ browser.click(userRow + USER_TABLE_DELETE);
+ browser.getConfirmation();
+ browser.refreshAndWait();
+ assertTrue("User " + username + " missing in user list after
cancelled deletion.", browser.isElementPresent(userRow));
+ }
+
+ @Test(dependsOnGroups = {"loginTest"},
dependsOnMethods={"userCreatingTest"})
+ public void disablingUserAccountTest() {
+ String username = "johny";
+ String password = "password";
+ String userRow = MessageFormat.format(USER_TABLE_ROW_BY_NAME, username);
+ createNewUser("John", "Doe", username, password, password, new
String[]{"user"}, false);
+ assertTrue("User not found in userlist.",
browser.isElementPresent(userRow));
+ assertTrue("User account enabled.", browser.isElementPresent(userRow +
USER_TABLE_CHECKBOX_UNCHECKED));
+ browser.clickAndWait(LOGOUT);
+ login(username, password);
+ assertFalse("User logged in despite his account was disabled.",
isLoggedIn());
+ }
+
+ private void createNewUser(String firstName, String lastName, String username, String
password, String confirm, String[] roles, boolean enabled) {
+ browser.clickAndWait(CREATE_USER_BUTTON);
+ fillNewUserDetails(firstName, lastName, username, password, confirm, roles,
enabled);
+ browser.clickAndWait(USER_SAVE);
+ }
+
+ private void fillNewUserDetails(String firstName, String lastName, String username,
String password, String confirm, String[] roles, boolean enabled)
+ {
+ browser.type(USER_FIRSTNAME, firstName);
+ browser.type(USER_LASTNAME, lastName);
+ browser.type(USER_NAME, username);
+ fillUpdatableUserDetails(password, confirm, roles, enabled);
+ }
+
+ private void fillUpdatableUserDetails(String password, String confirm, String[] roles,
boolean enabled) {
+ browser.type(USER_PASSWORD, password);
+ browser.type(USER_CONFIRM, confirm);
+ for (String role : roles) {
+ assertTrue("Unable to add user to role: " + role,
browser.isElementPresent(MessageFormat.format(USER_ROLE_BY_NAME_CHECKBOX, role)));
+ browser.check(MessageFormat.format(USER_ROLE_BY_NAME_CHECKBOX, role));
+ }
+ if (enabled)
+ {
+ browser.check(USER_ENABLED);
+ }
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/WEB-INF/components.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/WEB-INF/components.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/WEB-INF/components.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<components
xmlns="http://jboss.com/products/seam/components"
+
xmlns:core="http://jboss.com/products/seam/core"
+
xmlns:persistence="http://jboss.com/products/seam/persistence"
+
xmlns:security="http://jboss.com/products/seam/security"
+
xmlns:drools="http://jboss.com/products/seam/drools"
+
xmlns:web="http://jboss.com/products/seam/web"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=
+ "http://jboss.com/products/seam/core
http://jboss.com/products/seam/core-2.3.xsd
+
http://jboss.com/products/seam/persistence
http://jboss.com/products/seam/persistence-2.3.xsd
+
http://jboss.com/products/seam/components
http://jboss.com/products/seam/components-2.3.xsd
+
http://jboss.com/products/seam/security
http://jboss.com/products/seam/security-2.3.xsd
+
http://jboss.com/products/seam/web
http://jboss.com/products/seam/web-2.3.xsd
+
http://jboss.com/products/seam/drools
http://jboss.com/products/seam/drools-2.3.xsd">
+
+ <core:init jndi-pattern="jboss-seam-seamspace/#{ejbName}/local"
debug="false"/>
+
+ <core:manager conversation-timeout="120000"
+ concurrent-request-timeout="500"
+ conversation-id-parameter="cid"/>
+
+ <security:rule-based-permission-resolver
security-rules="#{securityRules}"/>
+
+ <security:jpa-identity-store
+ user-class="org.jboss.seam.example.seamspace.MemberAccount"
+ role-class="org.jboss.seam.example.seamspace.MemberRole"
+ />
+
+ <!--security:identity-manager
identity-store="#{ldapIdentityStore}"/-->
+
+ <security:ldap-identity-store name="ldapIdentityStore"
+ server-address="localhost"
+ bind-DN="cn=Manager,dc=bryzak,dc=com"
+ bind-credentials="secret"
+ user-DN-prefix="uid="
+ user-DN-suffix=",ou=Person,dc=bryzak,dc=com"
+ role-DN-prefix="cn="
+ role-DN-suffix=",ou=Roles,dc=bryzak,dc=com"
+ user-context-DN="ou=Person,dc=bryzak,dc=com"
+ role-context-DN="ou=Roles,dc=bryzak,dc=com"
+ user-role-attribute="roles"
+ role-name-attribute="cn"
+ user-object-classes="person,uidObject"
+ />
+
+ <security:jpa-permission-store
user-permission-class="org.jboss.seam.example.seamspace.AccountPermission"/>
+
+ <drools:rule-base name="securityRules">
+ <drools:rule-files>
+ <value>/META-INF/security-rules.drl</value>
+ </drools:rule-files>
+ </drools:rule-base>
+
+ <web:multipart-filter create-temp-files="true"
+ max-request-size="5000000"
+ url-pattern="*.seam"/>
+
+ <web:context-filter url-pattern="/content/*"/>
+
+ <persistence:managed-persistence-context name="entityManager"
auto-create="true"
+
persistence-unit-jndi-name="java:/seamspaceEntityManagerFactory"/>
+
+ <event type="org.jboss.seam.security.notLoggedIn">
+ <action execute="#{redirect.captureCurrentView}"/>
+ </event>
+
+ <event type="org.jboss.seam.security.loginSuccessful">
+ <action execute="#{redirect.returnToCapturedView}"/>
+ </event>
+
+</components>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/seam.properties
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/seam.properties
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources/seam.properties 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,3 @@
+#debug is explicitly disabled in test to avoid JBIDE-3623
+#Thu Dec 31 16:24:37 CET 2009
+org.jboss.seam.core.init.debug=false
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-ftest/testng.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-ftest/testng.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-ftest/testng.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,34 @@
+<!--
+JBoss, Home of Professional Open Source
+Copyright 2008, Red Hat Middleware LLC, and individual contributors
+by the @authors tag. See the copyright.txt in the distribution for a
+full listing of individual contributors.
+
+This is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of
+the License, or (at your option) any later version.
+
+This software is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this software; if not, write to the Free
+Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+-->
+<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
+<suite name="Seamspace example" verbose="2"
parallel="false">
+ <test name="seamspace_tests">
+ <parameter name="PROPERTY_FILE" value="" />
+ <classes>
+ <class name="org.jboss.seam.example.seamspace.test.selenium.LoginTest"
/>
+<!-- <class
name="org.jboss.seam.example.seamspace.test.selenium.UserTest" /> -->
+ <class name="org.jboss.seam.example.seamspace.test.selenium.RoleTest"
/>
+<!-- <class
name="org.jboss.seam.example.seamspace.test.selenium.BlogTest" /> -->
+<!-- <class
name="org.jboss.seam.example.seamspace.test.selenium.FriendRequestTest" />
-->
+ </classes>
+ </test>
+</suite>
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-ftest/testng.xml
___________________________________________________________________
Added: svn:executable
+ *
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-integration/testng.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-integration/testng.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-tests/src/test/resources-integration/testng.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,17 @@
+<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
+
+<suite name="SeamSpace" verbose="2"
parallel="false">
+
+ <test name="SeamSpace Register">
+ <classes>
+ <class
name="org.jboss.seam.example.seamspace.test.RegisterTest"/>
+ </classes>
+ </test>
+
+ <test name="SeamSpace Blog">
+ <classes>
+ <class name="org.jboss.seam.example.seamspace.test.BlogTest"/>
+ </classes>
+ </test>
+
+</suite>
Added: branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/pom.xml
===================================================================
--- branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/pom.xml
(rev 0)
+++ branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/pom.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>seamspace</artifactId>
+ <groupId>org.jboss.seam.examples-ee6</groupId>
+ <version>2.3.0.Beta2-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-web</artifactId>
+ <packaging>war</packaging>
+ <name>SeamSpace Web Module (EE6)</name>
+
+ <properties>
+ <!-- filtering property for components.xml -->
+ <jndiPattern>java:app/seamspace-ejb/#{ejbName}</jndiPattern>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+ <type>ejb</type>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam</artifactId>
+ <type>ejb</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam-ui</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam-jul</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.ui</groupId>
+ <artifactId>richfaces-components-ui</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.core</groupId>
+ <artifactId>richfaces-core-impl</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <webResources>
+ <resource>
+ <directory>src/main/webapp</directory>
+ <filtering>true</filtering>
+ </resource>
+ </webResources>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>tomcat</id>
+ <properties>
+ <!-- filtering property for components.xml -->
+ <jndiPattern>#{ejbName}/local</jndiPattern>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.seam.examples-ee6.seamspace</groupId>
+ <artifactId>seamspace-ejb</artifactId>
+ <type>ejb</type>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.seam</groupId>
+ <artifactId>jboss-seam</artifactId>
+ <type>ejb</type>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xpp3</groupId>
+ <artifactId>xpp3_min</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-impl</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-digester</groupId>
+ <artifactId>commons-digester</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.framework</groupId>
+ <artifactId>richfaces-api</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-core</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-compiler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-decisiontables</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-templates</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.jexcelapi</groupId>
+ <artifactId>jxl</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>jboss-seam-seamspace</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-resources</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+
<outputDirectory>${basedir}/target/classes</outputDirectory>
+ <resources>
+ <resource>
+
<directory>${basedir}/../seamspace-ear/src/main/resources</directory>
+ <includes>
+
<include>jboss-seam-space-ds.xml</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+
+ </build>
+ </profile>
+ </profiles>
+
+</project>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/resources/messages.properties
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/resources/messages.properties
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/resources/messages.properties 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1 @@
+org.jboss.seam.loginSuccessful=Hi there, #{authenticatedMember.memberName}
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/components.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/components.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/components.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<components
xmlns="http://jboss.com/products/seam/components"
+
xmlns:core="http://jboss.com/products/seam/core"
+
xmlns:persistence="http://jboss.com/products/seam/persistence"
+
xmlns:security="http://jboss.com/products/seam/security"
+
xmlns:drools="http://jboss.com/products/seam/drools"
+
xmlns:web="http://jboss.com/products/seam/web"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=
+ "http://jboss.com/products/seam/core
http://jboss.com/products/seam/core-2.3.xsd
+
http://jboss.com/products/seam/persistence
http://jboss.com/products/seam/persistence-2.3.xsd
+
http://jboss.com/products/seam/components
http://jboss.com/products/seam/components-2.3.xsd
+
http://jboss.com/products/seam/security
http://jboss.com/products/seam/security-2.3.xsd
+
http://jboss.com/products/seam/web
http://jboss.com/products/seam/web-2.3.xsd
+
http://jboss.com/products/seam/drools
http://jboss.com/products/seam/drools-2.3.xsd">
+
+ <core:init jndi-pattern="@jndiPattern@" debug="false"/>
+
+ <core:manager conversation-timeout="120000"
+ concurrent-request-timeout="500"
+ conversation-id-parameter="cid"/>
+
+ <security:rule-based-permission-resolver
security-rules="#{securityRules}"/>
+
+ <security:jpa-identity-store
+ user-class="org.jboss.seam.example.seamspace.MemberAccount"
+ role-class="org.jboss.seam.example.seamspace.MemberRole"
+ />
+
+ <!--security:identity-manager
identity-store="#{ldapIdentityStore}"/-->
+
+ <security:ldap-identity-store name="ldapIdentityStore"
+ server-address="localhost"
+ bind-DN="cn=Manager,dc=bryzak,dc=com"
+ bind-credentials="secret"
+ user-DN-prefix="uid="
+ user-DN-suffix=",ou=Person,dc=bryzak,dc=com"
+ role-DN-prefix="cn="
+ role-DN-suffix=",ou=Roles,dc=bryzak,dc=com"
+ user-context-DN="ou=Person,dc=bryzak,dc=com"
+ role-context-DN="ou=Roles,dc=bryzak,dc=com"
+ user-role-attribute="roles"
+ role-name-attribute="cn"
+ user-object-classes="person,uidObject"
+ />
+
+ <security:jpa-permission-store
user-permission-class="org.jboss.seam.example.seamspace.AccountPermission"/>
+
+ <drools:rule-base name="securityRules">
+ <drools:rule-files>
+ <value>/META-INF/security-rules.drl</value>
+ </drools:rule-files>
+ </drools:rule-base>
+
+ <web:multipart-filter create-temp-files="true"
+ max-request-size="5000000"
+ url-pattern="*.seam"/>
+
+ <web:context-filter url-pattern="/content/*"/>
+
+ <persistence:managed-persistence-context name="entityManager"
auto-create="true"
+
persistence-unit-jndi-name="java:/seamspaceEntityManagerFactory"/>
+
+ <event type="org.jboss.seam.security.notLoggedIn">
+ <action execute="#{redirect.captureCurrentView}"/>
+ </event>
+
+ <event type="org.jboss.seam.security.loginSuccessful">
+ <action execute="#{redirect.returnToCapturedView}"/>
+ </event>
+
+</components>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/faces-config.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/faces-config.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faces-config version="2.1"
+
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">
+
+</faces-config>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/pages.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/pages.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/pages.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pages
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd"
+ login-view-id="/home.xhtml">
+
+ <page view-id="/home.xhtml">
+ <navigation from-action="#{identity.login}">
+ <rule if="#{identity.loggedIn and authenticatedMember ne
null}">
+ <redirect view-id="/profile.xhtml"/>
+ </rule>
+ </navigation>
+ <navigation from-action="#{register.start}">
+ <redirect view-id="/register.xhtml"/>
+ </navigation>
+ </page>
+
+ <page view-id="/security.xhtml" login-required="true">
+
+ </page>
+
+ <page view-id="/comment.xhtml" login-required="true">
+ <restrict/>
+
+ <navigation from-action="#{commentAction.saveComment}">
+ <redirect view-id="/blogentry.xhtml"/>
+ </navigation>
+ </page>
+
+ <page view-id="/register.xhtml">
+ <navigation from-action="#{register.next}">
+ <rule if="#{not register.verified}">
+ <redirect view-id="/register.xhtml"/>
+ </rule>
+
+ <rule if="#{register.verified}">
+ <redirect view-id="/register2.xhtml"/>
+ </rule>
+ </navigation>
+ </page>
+
+ <page view-id="/register2.xhtml">
+ <navigation from-action="#{register.uploadPicture}">
+ <redirect view-id="/profile.xhtml">
+ <param name="name"
value="#{register.member.memberName}"/>
+ </redirect>
+ </navigation>
+ </page>
+
+ <page view-id="/createBlog.xhtml">
+ <restrict>#{identity.loggedIn}</restrict>
+ <navigation from-action="#{blog.saveEntry}">
+ <redirect view-id="/blog.xhtml"/>
+ </navigation>
+ </page>
+
+ <page view-id="/blog.xhtml">
+ <param name="name"
value="#{selectedMember.memberName}"/>
+ </page>
+
+ <page view-id="/blogentry.xhtml">
+ <param name="name" value="#{blog.name}"/>
+ <param name="blogId" value="#{blog.blogId}"/>
+
+ <navigation from-action="#{commentAction.createComment}">
+ <redirect view-id="/comment.xhtml"/>
+ </navigation>
+
+ </page>
+
+ <page view-id="/profile.xhtml">
+ <param name="name"
value="#{selectedMember.memberName}"/>
+
+ <navigation from-action="#{friend.createComment}">
+ <redirect view-id="/friendcomment.xhtml"/>
+ </navigation>
+ </page>
+
+ <page view-id="/pictureupload.xhtml"
login-required="true">
+ <navigation from-action="#{pictureAction.savePicture}">
+ <redirect view-id="/pictures.xhtml">
+ <param name="name"
value="#{authenticatedMember.memberName}"/>
+ </redirect>
+ </navigation>
+ </page>
+
+ <page view-id="/friendcomment.xhtml">
+ <param name="name"
value="#{selectedMember.memberName}"/>
+
+ <restrict>#{identity.loggedIn}</restrict>
+ <navigation from-action="#{friend.saveComment}">
+ <redirect view-id="/profile.xhtml">
+ <param name="name"
value="#{friendComment.member.memberName}"/>
+ </redirect>
+ </navigation>
+ </page>
+
+ <page view-id="/friendrequest.xhtml">
+ <restrict>#{identity.loggedIn}</restrict>
+ <param name="name"
value="#{selectedMember.memberName}"/>
+ <navigation from-action="#{friendAction.saveRequest}">
+ <redirect view-id="/profile.xhtml">
+ <param name="name"
value="#{friendRequest.member.memberName}"/>
+ </redirect>
+ </navigation>
+ </page>
+
+ <page view-id="/pictures.xhtml"
action="#{pictureSearch.loadMemberPictures}">
+ <param name="name" value="#{pictureSearch.memberName}"/>
+
+ </page>
+
+ <page view-id="*">
+ <navigation from-action="#{identity.logout}">
+ <redirect view-id="/home.xhtml"/>
+ </navigation>
+
+ <navigation from-action="#{blog.createComment}">
+ <redirect view-id="/comment.xhtml"/>
+ </navigation>
+
+ <navigation from-action="#{blog.createEntry}">
+ <redirect view-id="/createBlog.xhtml"/>
+ </navigation>
+ </page>
+
+ <exception class="org.jboss.seam.security.NotLoggedInException"
log="true" log-level="info">
+ <redirect view-id="/register.xhtml">
+ <message severity="warn">You must be a member to use this
feature</message>
+ </redirect>
+ </exception>
+
+ <exception class="org.jboss.seam.security.AuthorizationException">
+ <end-conversation/>
+ <redirect view-id="/security_error.xhtml">
+ <message severity="error">You do not have permission to do
this</message>
+ </redirect>
+ </exception>
+
+</pages>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/web.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/web.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/WEB-INF/web.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="3.0"
+
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+
+ <display-name>SeamSpace Example</display-name>
+
+ <!-- RichFaces -->
+
+ <context-param>
+ <param-name>org.richfaces.SKIN</param-name>
+ <param-value>blueSky</param-value>
+ </context-param>
+
+ <!-- Seam -->
+
+ <listener>
+ <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>Seam Resource Servlet</servlet-name>
+
<servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Seam Resource Servlet</servlet-name>
+ <url-pattern>/seam/resource/*</url-pattern>
+ </servlet-mapping>
+
+ <filter>
+ <filter-name>Seam Filter</filter-name>
+ <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Seam Filter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <context-param>
+ <param-name>facelets.DEVELOPMENT</param-name>
+ <param-value>true</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
+ <param-value>.xhtml</param-value>
+ </context-param>
+
+ <!-- Faces Servlet -->
+
+ <servlet>
+ <servlet-name>Faces Servlet</servlet-name>
+ <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Faces Servlet</servlet-name>
+ <url-pattern>*.seam</url-pattern>
+ </servlet-mapping>
+
+ <!-- Content Servlet -->
+
+ <servlet>
+ <servlet-name>Content Servlet</servlet-name>
+
<servlet-class>org.jboss.seam.example.seamspace.ContentServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Content Servlet</servlet-name>
+ <url-pattern>/content/*</url-pattern>
+ </servlet-mapping>
+
+ <session-config>
+ <session-timeout>10</session-timeout>
+ </session-config>
+</web-app>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blog.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blog.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blog.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,60 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{selectedMember == null}">
+ Sorry, but this member does not exist.
+ </s:div>
+
+ <s:div rendered="#{selectedMember != null}">
+
+ <s:div id="blogMemberCard">
+ <s:link view="/profile.seam" propagation="none">
+ #{selectedMember.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{selectedMember.picture.imageId}&width=90"/>
+ </s:link>
+
+ <br style="clear:both"/>
+ </s:div>
+
+ <s:div id="blog">
+ <ui:repeat value="#{memberBlogs}" var="memberBlog">
+ <div class="blogEntry">
+ <div
class="blogDate">#{memberBlog.formattedEntryDate}</div>
+ <div class="blogTitle">#{memberBlog.title}</div>
+ <div class="blogText"><s:formattedText
value="#{memberBlog.text}"/></div>
+ <div class="blogFooter">
+
+ [<s:link view="/blogentry.seam"
propagation="none">
+ <f:param name="name"
value="#{selectedMember.memberName}"/>
+ <f:param name="blogId"
value="#{memberBlog.blogId}"/>
+ #{memberBlog.commentCount} Comment#{memberBlog.commentCount != 1 ?
"s" : ""}
+ </s:link>]
+
+ <s:span
rendered="#{s:hasPermission('blog','createComment')}">
+ [<s:link view="/comment.seam" value="Add Comment"
propagation="none">
+ <f:param name="name"
value="#{selectedMember.memberName}"/>
+ <f:param name="blogId"
value="#{memberBlog.blogId}"/>
+ </s:link>]
+ </s:span>
+ </div>
+ </div>
+ </ui:repeat>
+ </s:div>
+
+ </s:div>
+
+ <br class="clear"/>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blogentry.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blogentry.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/blogentry.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,74 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{selectedBlog == null}">
+ Sorry, but this blog entry does not exist.
+ </s:div>
+
+ <s:div rendered="#{selectedBlog != null}">
+
+ <s:div id="blogMemberCard">
+ <s:link view="/profile.seam" propagation="none">
+ #{selectedMember.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{selectedMember.picture.imageId}&width=90"/>
+ </s:link>
+
+ <br style="clear:both"/>
+ </s:div>
+
+ <s:div id="blog">
+ <div class="blogEntry">
+ <div
class="blogDate">#{selectedBlog.formattedEntryDate}</div>
+ <div class="blogTitle">#{selectedBlog.title}</div>
+ <div class="blogText"><s:formattedText
value="#{selectedBlog.text}"/></div>
+ <div class="blogFooter">
+ <s:span rendered="#{s:hasPermission(selectedBlog,
'create')}">
+ [<s:link action="#{commentAction.createComment}"
value="Add Comment"/>]
+ </s:span>
+ [<s:link view="/blog.seam" value="View all blog
entries" propagation="none">
+ <f:param name="name"
value="#{selectedMember.memberName}"/>
+ </s:link>]
+ </div>
+ </div>
+
+ <ui:repeat value="#{selectedBlog.sortedComments}"
var="comment">
+ <table class="blogComment">
+ <tr>
+ <td class="blogCommentor">
+ <s:link view="/profile.seam" propagation="none">
+ <f:param name="name"
value="#{comment.commentor.memberName}"/>
+ #{comment.commentor.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{comment.commentor.picture.imageId}&width=90"/>
+ </s:link>
+ </td>
+
+ <td class="blogCommentText">
+ <p><s:formattedText
value="#{comment.comment}"/></p>
+ <p>Posted by
+ <s:link view="/profile.seam"
value="#{comment.commentor.memberName}" propagation="none">
+ <f:param name="name"
value="#{comment.commentor.memberName}"/>
+ </s:link> on #{comment.formattedCommentDate}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </ui:repeat>
+ </s:div>
+
+ </s:div>
+
+ <br class="clear"/>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/comment.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/comment.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/comment.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,89 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{commentAction.comment == null}">
+ Could not create comment.
+ </s:div>
+
+ <s:div rendered="#{selectedMember != null}">
+
+ <s:div id="blogMemberCard">
+ <s:link view="/profile.seam" propagation="none">
+ #{selectedMember.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{selectedMember.picture.imageId}&width=90"/>
+ </s:link>
+
+ <br style="clear:both"/>
+ </s:div>
+
+ <s:div id="blog">
+ <div class="blogEntry">
+ <div
class="blogDate">#{selectedBlog.formattedEntryDate}</div>
+ <div class="blogTitle">#{selectedBlog.title}</div>
+ <div class="blogText"><s:formattedText
value="#{selectedBlog.text}"/></div>
+ </div>
+
+ <s:div rendered="#{commentAction.comment.comment != null}">
+ Preview:
+ <table class="blogComment">
+ <tr>
+ <td class="blogCommentText">
+ <p><s:formattedText
value="#{commentAction.comment.comment}"/></p>
+ </td>
+ </tr>
+ </table>
+ </s:div>
+
+ <div class="commentEntry">
+ <h:form>
+
+ <h:outputLabel for="comment">Please type your
comment</h:outputLabel><br/>
+ <h:inputTextarea id="comment"
value="#{commentAction.comment.comment}"/><br/>
+
+ <div class="buttons">
+ <h:commandButton action="#{commentAction.saveComment}"
value="Add comment" styleClass="action"/>
+ <h:commandButton value="Preview"
styleClass="action"/>
+ </div>
+
+ <br class="clear"/>
+ </h:form>
+ </div>
+
+ <div>
+ <b>Seam Text Quick Reference</b><br/>
+ <pre><code>
+*bold* /italic/ |monospace| -strikethrough- ^super^ _underline_
+
++Big Heading
+Headings must be followed by text
+
+++Smaller heading
+Paragraphs are ended with a blank line.
+
+#ordered list item
+
+=unordered list item
+
+"quoted text"
+ </code></pre>
+ </div>
+
+ </s:div>
+
+ </s:div>
+
+ <br class="clear"/>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/createBlog.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/createBlog.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/createBlog.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,84 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{selectedBlog == null}">
+ Sorry, but this blog entry does not exist.
+ </s:div>
+
+ <s:div rendered="#{selectedBlog != null}">
+
+ <s:div id="blogMemberCard">
+ <s:link view="/profile.seam" propagation="none">
+ #{selectedMember.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{selectedMember.picture.imageId}&width=90"/>
+ </s:link>
+
+ <br style="clear:both"/>
+ </s:div>
+
+ <s:div id="blog">
+ <s:div rendered="#{selectedBlog.text != null}"
styleClass="blogEntry">
+ Preview:
+ <p><s:formattedText
value="#{selectedBlog.text}"/></p>
+ </s:div>
+
+ <div class="blogEntry">
+ <h:form id="newBlog">
+
+ <div class="formRow">
+ <h:outputLabel for="title">Please type a title for your
blog entry</h:outputLabel><br/>
+ <h:inputText id="title"
value="#{selectedBlog.title}" styleClass="title"/>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="text">Type your blog entry
here</h:outputLabel><br/>
+ <h:inputTextarea id="text"
value="#{selectedBlog.text}"/>
+ </div>
+
+ <div class="buttons">
+ <h:commandButton id="submit"
action="#{blog.saveEntry}" value="Add entry"
styleClass="action"/>
+ <h:commandButton id="preview" value="Preview"
styleClass="action"/>
+ </div>
+
+ <br class="clear"/>
+ </h:form>
+ </div>
+
+ <div>
+ <b>Seam Text Quick Reference</b><br/>
+ <pre><code>
+*bold* /italic/ |monospace| -strikethrough- ^super^ _underline_
+
++Big Heading
+Headings must be followed by text
+
+++Smaller heading
+Paragraphs are ended with a blank line.
+
+#ordered list item
+
+=unordered list item
+
+"quoted text"
+ </code></pre>
+ </div>
+
+ </s:div>
+
+ </s:div>
+
+ <br class="clear"/>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendcomment.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendcomment.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendcomment.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,84 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{friendComment == null}">
+ Could not create comment.
+ </s:div>
+
+ <s:div rendered="#{friendComment != null}">
+
+ <s:div id="blogMemberCard">
+ <h:outputLink
value="profile.seam?name=#{friendComment.member.memberName}">
+ #{friendComment.member.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{friendComment.member.picture.imageId}&width=90"/>
+ </h:outputLink>
+
+ <br style="clear:both"/>
+ </s:div>
+
+ <s:div id="blog">
+
+ <s:div rendered="#{friendComment.comment != null}">
+ Preview:
+ <table class="blogComment">
+ <tr>
+ <td class="blogCommentText">
+ <p><s:formattedText
value="#{friendComment.comment}"/></p>
+ </td>
+ </tr>
+ </table>
+ </s:div>
+
+ <div class="commentEntry">
+ <h:form>
+
+ <h:outputLabel for="comment">Please type your comment for
#{friendComment.member.memberName}</h:outputLabel><br/>
+ <h:inputTextarea id="comment"
value="#{friendComment.comment}"/><br/>
+
+ <div class="buttons">
+ <h:commandButton action="#{friendAction.saveComment}"
value="Add comment" styleClass="action"/>
+ <h:commandButton value="Preview"
styleClass="action"/>
+ </div>
+
+ <br class="clear"/>
+ </h:form>
+ </div>
+
+ <div>
+ <b>Seam Text Quick Reference</b><br/>
+ <pre><code>
+*bold* /italic/ |monospace| -strikethrough- ^super^ _underline_
+
++Big Heading
+Headings must be followed by text
+
+++Smaller heading
+Paragraphs are ended with a blank line.
+
+#ordered list item
+
+=unordered list item
+
+"quoted text"
+ </code></pre>
+ </div>
+
+ </s:div>
+
+ </s:div>
+
+ <br class="clear"/>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendrequest.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendrequest.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/friendrequest.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{friendRequest == null}">
+ Could not create friend request.
+ </s:div>
+
+ <s:div rendered="#{friendRequest != null}">
+
+ <s:div id="blogMemberCard">
+ <s:link view="/profile.xhtml"
value="#{friendRequest.member.memberName}" propagation="none">
+ <f:param name="name"
value="#{friendRequest.member.memberName}"/>
+ <h:graphicImage
value="/content/images?id=#{friendRequest.member.picture.imageId}&width=90"/>
+ </s:link>
+
+ <br style="clear:both"/>
+ </s:div>
+
+ <div class="friendRequest">
+ <h1>Send a friend request</h1>
+
+ <p>
+ Use this form to request that
<b>#{friendRequest.member.memberName}</b> adds you to
+ #{friendRequest.member.gender.possessive} friends list.
+ </p>
+
+ <h:form>
+
+ <h:outputLabel for="introduction">Please type an introduction
message</h:outputLabel><br/>
+ <h:inputTextarea id="introduction"
value="#{friendRequest.introduction}"/><br/>
+
+ <div class="buttons">
+ <h:commandButton action="#{friendAction.saveRequest}"
value="Send request" styleClass="action"/>
+ </div>
+
+ <br class="clear"/>
+ </h:form>
+ </div>
+
+ </s:div>
+
+ <br class="clear"/>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/hashgen.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/hashgen.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/hashgen.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+ <h1>Password Hash Generator</h1>
+
+ <p>
+ This page uses the methods in JpaIdentityStore to generate password hash values
that you can
+ use in your own application's import.sql to create default accounts for your
application.
+ </p>
+
+ <p>
+ Please note that you must have a property annotated @PasswordSalt for these hash
values to work!
+ </p>
+
+ <h:form>
+
+ <div class="formRow">
+ <h:outputLabel for="password">Enter a
password</h:outputLabel>
+ <h:inputText id="password"
value="#{hashgenerator.password}" required="true"
styleClass="wide"/>
+ <div class="validationError"><h:message
for="password"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="salt">Password salt</h:outputLabel>
+ <h:inputText id="salt"
value="#{hashgenerator.passwordSalt}" required="false"
styleClass="wide"/>
+ <span>(Leave blank to generate a random salt)</span>
+ <div class="validationError"><h:message
for="salt"/></div>
+ </div>
+
+ <h:commandButton action="#{hashgenerator.generate}"
value="Generate hash"/>
+
+ </h:form>
+
+ <h2>Results</h2>
+
+ <div>Generated hash (hex encoded):
<pre>#{hashgenerator.passwordHash}</pre></div>
+
+ <div>Example SQL:<br/><textarea
style="width:640px;height:50px">#{hashgenerator.sql}</textarea></div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/home.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/home.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/home.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+ <div id="contentMain">
+ <h1>Welcome to seamspace!</h1>
+
+ <p>
+ This example project is an imitation of a popular social networking site, and
has
+ been put together to demonstrate the various features of the Seam Security
API.
+ </p>
+
+ <p><b>New!</b> You can now use the <s:link
view="/hashgen.xhtml" value="Password Hash Generator"/>
+ page to generate password hashes for your own application.
+ </p>
+
+ </div>
+
+ <div id="contentDivider">
+ </div>
+
+ <div id="contentSide">
+ <div class="advertising"></div>
+
+ <h:form id="loginForm" rendered="#{not
identity.loggedIn}">
+ <div class="memberLogin">
+ <div class="loginHeader">Member Login</div>
+
+ <h:messages id="messages" globalOnly="true"/>
+
+ <div class="loginRow">
+ <h:outputLabel for="name" value="Member name"
styleClass="loginLabel"/>
+ <h:inputText id="name"
value="#{credentials.username}"/>
+ </div>
+
+ <div class="validationMsg">
+ <h:message for="name"/>
+ </div>
+
+ <div class="loginRow">
+ <h:outputLabel for="password" value="Password"
styleClass="loginLabel"/>
+ <h:inputSecret id="password"
value="#{credentials.password}" redisplay="true"/>
+ </div>
+
+ <div class="validationMsg">
+ <h:message for="password"/>
+ </div>
+
+ <div class="loginRow">
+ <h:outputLabel for="rememberMe" value="Remember me"
styleClass="loginLabel"/>
+ <h:selectBooleanCheckbox id="rememberMe"
value="#{identity.rememberMe}"/>
+ </div>
+
+ <div class="buttons">
+ <h:commandButton id="login" value="LOGIN"
action="#{identity.login}" styleClass="loginButton"/>
+ <h:commandButton id="register" value="SIGN UP!"
action="#{register.start}" styleClass="registerButton"/>
+ </div>
+
+ <br class="clear"/>
+
+ </div>
+
+ <span>Tip: You can log in using <b>demo/demo</b> as the
username/password</span>
+ </h:form>
+
+ <div class="newMembers">
+ <div class="newMembersHeader">Cool new members</div>
+
+ <ui:repeat value="#{newMembers}" var="newMember">
+ <div class="newMember">
+
+ <s:link view="/profile.seam" propagation="none">
+ <f:param name="name"
value="#{newMember.memberName}"/>
+ #{newMember.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{newMember.picture.imageId}&width=90"/>
+ </s:link>
+
+ </div>
+ </ui:repeat>
+
+ <br class="clear"/>
+ </div>
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.page.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.page.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.page.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,9 @@
+<page
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd">
+ <navigation from-action="#{imagePermission.applyPermissions}">
+ <rule if-outcome="success">
+ <redirect view-id="/imagepermissions.xhtml"/>
+ </rule>
+ </navigation>
+</page>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissiondetail.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,89 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:rich="http://richfaces.org/rich"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <div id="contentMain">
+
+ <h2>Permission Details</h2>
+
+ <hr/>
+
+ <h:messages globalOnly="true"/>
+
+ <h:form>
+ <s:fragment rendered="#{imagePermission.recipient eq null}">
+ <h3>Recipients</h3>
+
+ <p>
+ Select the roles and/or friends that you wish to grant permissions to, for
the following image
+ (Ctrl-click to select multiple):
+ </p>
+
+ <br class="clear"/>
+
+ <div class="thumbnail">
+ <h:graphicImage
value="/content/images?id=#{permissionSearch.target.imageId}&width=90"/>
+ </div>
+
+ <br class="clear"/>
+
+ <div class="formRow">
+ <h:outputLabel for="roles" value="Roles"
styleClass="formLabel"/>
+ <div class="selectMany">
+ <h:selectManyListbox id="roles"
value="#{imagePermission.selectedRoles}" styleClass="roles"
size="4">
+ <s:selectItems value="#{identityManager.listRoles()}"
var="role" label="#{role}"/>
+ </h:selectManyListbox>
+ </div>
+ <div class="validationError"><h:message
for="actions"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="friends" value="Friends"
styleClass="formLabel"/>
+ <div class="selectMany">
+ <h:selectManyListbox id="friends"
value="#{imagePermission.selectedFriends}" styleClass="roles"
size="6">
+ <s:selectItems value="#{imagePermission.availableFriends}"
var="friend" label="#{friend.memberName}"/>
+ <s:convertEntity />
+ </h:selectManyListbox>
+ </div>
+ <div class="validationError"><h:message
for="friends"/></div>
+ </div>
+
+ </s:fragment>
+
+ <div class="formRow">
+ <h:outputLabel for="actions" value="Actions allowed"
styleClass="formLabel"/>
+ <div class="selectMany">
+ <h:selectManyCheckbox id="actions"
value="#{imagePermission.selectedActions}" layout="pageDirection"
styleClass="roles">
+ <s:selectItems
value="#{permissionManager.listAvailableActions(imagePermission.target)}"
var="action" label="#{action}"/>
+ </h:selectManyCheckbox>
+ </div>
+ <div class="validationError"><h:message
for="actions"/></div>
+ </div>
+
+ <div class="formButtons">
+ <h:commandButton value="Save"
action="#{imagePermission.applyPermissions}"
styleClass="formButton"/>
+ <s:button view="/imagepermissions.xhtml"
value="Cancel" propagation="end"
styleClass="formButton"/>
+ </div>
+
+ <br class="clear"/>
+
+ </h:form>
+
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.page.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.page.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.page.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,11 @@
+<page
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd"
+ action="#{permissionSearch.refresh}">
+ <navigation from-action="#{imagePermission.createPermission}">
+ <redirect view-id="/imagepermissiondetail.xhtml"/>
+ </navigation>
+ <navigation from-action="#{imagePermission.editPermission}">
+ <redirect view-id="/imagepermissiondetail.xhtml"/>
+ </navigation>
+</page>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/imagepermissions.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <script type="text/javascript">
+ function confirmRevoke()
+ {
+ return confirm("Are you sure you wish to revoke this permission? This
action cannot be undone.");
+ }
+ </script>
+
+ <div id="contentMain">
+
+ <h2>Image Permissions</h2>
+
+ <div style="float: left">
+ <h3>Managing permissions for image:</h3>
+ </div>
+
+ <br class="clear"/>
+
+ <div class="thumbnail">
+ <h:graphicImage
value="/content/images?id=#{permissionSearch.target.imageId}&width=90"/>
+ </div>
+
+ <br class="clear"/>
+
+ <s:button action="#{imagePermission.createPermission}"
+ styleClass="newpermission"
+ rendered="#{s:hasPermission(permissionSearch.target,
'seam.grant-permission')}"/>
+
+ <h:dataTable
+ id="threads"
+ value="#{recipients}"
+ var="recipient"
+ styleClass="security"
+ cellspacing="0"
+ headerClass="header"
+ rowClasses="odd,even"
+ columnClasses=",,action">
+ <h:column width="auto">
+ <f:facet name="header">
+ Recipient
+ </f:facet>
+ #{recipient.name}
+ </h:column>
+ <h:column width="auto">
+ <f:facet name="header">
+ Actions Allowed
+ </f:facet>
+ #{permissionSearch.getActions(recipient)}
+ </h:column>
+ <h:column width="auto">
+ <f:facet name="header">
+ Action
+ </f:facet>
+ <s:link value="Edit"
action="#{imagePermission.editPermission}"
+ rendered="#{s:hasPermission(permissionSearch.target,
'seam.revoke-permission')}"/>
+ <span> | </span>
+ <s:link value="Revoke All"
action="#{permissionSearch.revokeSelected}"
+ rendered="#{s:hasPermission(permissionSearch.target,
'seam.revoke-permission')}"
+ onclick="return confirmRevoke()"/>
+ </h:column>
+ </h:dataTable>
+
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/bg_button.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/bg_button.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/checkmark.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/checkmark.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/cross.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/cross.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/ellipsis.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/ellipsis.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/no_image.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/images/no_image.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/index.html
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/index.html
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/index.html 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,5 @@
+<html>
+<head>
+ <meta http-equiv="Refresh" content="0; URL=home.seam">
+</head>
+</html>
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/builder.js
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/builder.js
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/builder.js 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (
http://script.aculo.us,
http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site:
http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature":
http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" +
elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature":
http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] =
arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' +
attributes[attribute].toString().escapeHTML().gsub(/"/,'"') +
'"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function')
scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG
BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM
FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT
INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP
OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE
TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/bullet.gif
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/bullet.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/close.gif
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/close.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/closelabel.gif
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/closelabel.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/effects.js
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/effects.js
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/effects.js 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (
http://script.aculo.us,
http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (
http://encytemedia.com/)
+// Mark Pilgrim (
http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site:
http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) +
this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this
effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed +
masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1
}
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each(
function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length <
effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ?
'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' :
'')
+ );
+ }
+ if (options && options.transition === false) options.transition =
Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options
|| { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+
'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName +
'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' +
$H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') ||
'0');
+ this.originalTop = parseFloat(this.element.getStyle('top') ||
'0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with
provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+
['top','left','width','height','fontSize'].each(
function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType
});
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel();
return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor =
this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return
parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return
parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart());
}.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 :
element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true
}),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth:
elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity:
oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect)
{
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect)
{
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect)
{
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect)
{
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element
with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth:
elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth:
elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0,
transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition:
options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition:
options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition:
options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition:
options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition:
options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos,
options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity:
oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color))
color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) :
parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+
(transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options
= track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true
}, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this +
'"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() +
s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes
collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.css
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.css
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.css 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,27 @@
+#lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center;
line-height: 0;}
+#lightbox img{ width: auto; height: auto;}
+#lightbox a img{ border: none; }
+
+#outerImageContainer{ position: relative; background-color: #fff; width: 250px; height:
250px; margin: 0 auto; }
+#imageContainer{ padding: 10px; }
+
+#loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align:
center; line-height: 0; }
+#hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10;
}
+#imageContainer>#hoverNav{ left: 0;}
+#hoverNav a{ outline: none;}
+
+#prevLink, #nextLink{ width: 49%; height: 100%; background-image:
url(data:image/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; }
+#prevLink { left: 0; float: left;}
+#nextLink { right: 0; float: right;}
+#prevLink:hover, #prevLink:visited:hover { background: url(prevlabel.gif) left 15%
no-repeat; }
+#nextLink:hover, #nextLink:visited:hover { background: url(nextlabel.gif) right 15%
no-repeat; }
+
+#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff;
margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }
+
+#imageData{ padding:0 10px; color: #666; }
+#imageData #imageDetails{ width: 70%; float: left; text-align: left; }
+#imageData #caption{ font-weight: bold; }
+#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
+#imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline:
none;}
+
+#overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px;
background-color: #000; }
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.js
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.js
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/lightbox.js 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,497 @@
+// -----------------------------------------------------------------------------------
+//
+// Lightbox v2.04
+// by Lokesh Dhakar -
http://www.lokeshdhakar.com
+// Last Modification: 2/9/08
+//
+// For more information, visit:
+//
http://lokeshdhakar.com/projects/lightbox2/
+//
+// Licensed under the Creative Commons Attribution 2.5 License -
http://creativecommons.org/licenses/by/2.5/
+// - Free for use in both personal and commercial projects
+// - Attribution requires leaving author name, author link, and the license info
intact.
+//
+// Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas
Fuchs(mir.aculo.us) for ideas, libs, and snippets.
+// Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of
proto-aculous.
+//
+// -----------------------------------------------------------------------------------
+/*
+
+ Table of Contents
+ -----------------
+ Configuration
+
+ Lightbox Class Declaration
+ - initialize()
+ - updateImageList()
+ - start()
+ - changeImage()
+ - resizeImageContainer()
+ - showImage()
+ - updateDetails()
+ - updateNav()
+ - enableKeyboardNav()
+ - disableKeyboardNav()
+ - keyboardAction()
+ - preloadNeighborImages()
+ - end()
+
+ Function Calls
+ - document.observe()
+
+*/
+// -----------------------------------------------------------------------------------
+
+//
+// Configurationl
+//
+LightboxOptions = Object.extend({
+ fileLoadingImage: 'lightbox/loading.gif',
+ fileBottomNavCloseImage: 'lightbox/closelabel.gif',
+
+ overlayOpacity: 0.8, // controls transparency of shadow overlay
+
+ animate: true, // toggles resizing animations
+ resizeSpeed: 7, // controls the speed of the image resizing animations
(1=slowest and 10=fastest)
+
+ borderSize: 10, //if you adjust the padding in the CSS, you will need to
update this variable
+
+ // When grouping images this is used to write: Image # of #.
+ // Change it for non-english localization
+ labelImage: "Image",
+ labelOf: "of"
+}, window.LightboxOptions || {});
+
+// -----------------------------------------------------------------------------------
+
+var Lightbox = Class.create();
+
+Lightbox.prototype = {
+ imageArray: [],
+ activeImage: undefined,
+
+ // initialize()
+ // Constructor runs on completion of the DOM loading. Calls updateImageList and then
+ // the function inserts html at the bottom of the page which is used to display the
shadow
+ // overlay and the image container.
+ //
+ initialize: function() {
+
+ this.updateImageList();
+
+ this.keyboardAction = this.keyboardAction.bindAsEventListener(this);
+
+ if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
+ if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1;
+
+ this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed)
* 0.15) : 0;
+ this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out
duration
+
+ // When Lightbox starts it will resize itself from 250 by 250 to the current
image dimension.
+ // If animations are turned off, it will be hidden as to prevent a flicker of a
+ // white 250 by 250 box.
+ var size = (LightboxOptions.animate ? 250 : 1) + 'px';
+
+
+ // Code inserts html at the bottom of the page that looks similar to this:
+ //
+ // <div id="overlay"></div>
+ // <div id="lightbox">
+ // <div id="outerImageContainer">
+ // <div id="imageContainer">
+ // <img id="lightboxImage">
+ // <div style="" id="hoverNav">
+ // <a href="#"
id="prevLink"></a>
+ // <a href="#"
id="nextLink"></a>
+ // </div>
+ // <div id="loading">
+ // <a href="#" id="loadingLink">
+ // <img src="images/loading.gif">
+ // </a>
+ // </div>
+ // </div>
+ // </div>
+ // <div id="imageDataContainer">
+ // <div id="imageData">
+ // <div id="imageDetails">
+ // <span id="caption"></span>
+ // <span id="numberDisplay"></span>
+ // </div>
+ // <div id="bottomNav">
+ // <a href="#" id="bottomNavClose">
+ // <img src="images/close.gif">
+ // </a>
+ // </div>
+ // </div>
+ // </div>
+ // </div>
+
+
+ var objBody = $$('body')[0];
+
+ objBody.appendChild(Builder.node('div',{id:'overlay'}));
+
+ objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
+ Builder.node('div',{id:'outerImageContainer'},
+ Builder.node('div',{id:'imageContainer'}, [
+ Builder.node('img',{id:'lightboxImage'}),
+ Builder.node('div',{id:'hoverNav'}, [
+ Builder.node('a',{id:'prevLink', href:
'#' }),
+ Builder.node('a',{id:'nextLink', href:
'#' })
+ ]),
+ Builder.node('div',{id:'loading'},
+ Builder.node('a',{id:'loadingLink', href:
'#' },
+ Builder.node('img', {src:
LightboxOptions.fileLoadingImage})
+ )
+ )
+ ])
+ ),
+ Builder.node('div', {id:'imageDataContainer'},
+ Builder.node('div',{id:'imageData'}, [
+ Builder.node('div',{id:'imageDetails'}, [
+ Builder.node('span',{id:'caption'}),
+ Builder.node('span',{id:'numberDisplay'})
+ ]),
+ Builder.node('div',{id:'bottomNav'},
+ Builder.node('a',{id:'bottomNavClose', href:
'#' },
+ Builder.node('img', { src:
LightboxOptions.fileBottomNavCloseImage })
+ )
+ )
+ ])
+ )
+ ]));
+
+
+ $('overlay').hide().observe('click', (function() { this.end();
}).bind(this));
+ $('lightbox').hide().observe('click', (function(event) { if
(event.element().id == 'lightbox') this.end(); }).bind(this));
+ $('outerImageContainer').setStyle({ width: size, height: size });
+ $('prevLink').observe('click', (function(event) { event.stop();
this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
+ $('nextLink').observe('click', (function(event) { event.stop();
this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
+ $('loadingLink').observe('click', (function(event) { event.stop();
this.end(); }).bind(this));
+ $('bottomNavClose').observe('click', (function(event) { event.stop();
this.end(); }).bind(this));
+
+ var th = this;
+ (function(){
+ var ids =
+ 'overlay lightbox outerImageContainer imageContainer lightboxImage
hoverNav prevLink nextLink loading loadingLink ' +
+ 'imageDataContainer imageData imageDetails caption numberDisplay
bottomNav bottomNavClose';
+ $w(ids).each(function(id){ th[id] = $(id); });
+ }).defer();
+ },
+
+ //
+ // updateImageList()
+ // Loops through anchor tags looking for 'lightbox' references and applies
onclick
+ // events to appropriate links. You can rerun after dynamically adding images
w/ajax.
+ //
+ updateImageList: function() {
+ this.updateImageList = Prototype.emptyFunction;
+
+ document.observe('click', (function(event){
+ var target = event.findElement('a[rel^=lightbox]') ||
event.findElement('area[rel^=lightbox]');
+ if (target) {
+ event.stop();
+ this.start(target);
+ }
+ }).bind(this));
+ },
+
+ //
+ // start()
+ // Display overlay and lightbox. If image is part of a set, add siblings to
imageArray.
+ //
+ start: function(imageLink) {
+
+ $$('select', 'object', 'embed').each(function(node){
node.style.visibility = 'hidden' });
+
+ // stretch overlay to fill page and fade in
+ var arrayPageSize = this.getPageSize();
+ $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height:
arrayPageSize[1] + 'px' });
+
+ new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to:
LightboxOptions.overlayOpacity });
+
+ this.imageArray = [];
+ var imageNum = 0;
+
+ if ((imageLink.rel == 'lightbox')){
+ // if image is NOT part of a set, add single image to imageArray
+ this.imageArray.push([imageLink.href, imageLink.title]);
+ } else {
+ // if image is part of a set..
+ this.imageArray =
+ $$(imageLink.tagName + '[href][rel="' + imageLink.rel +
'"]').
+ collect(function(anchor){ return [anchor.href, anchor.title]; }).
+ uniq();
+
+ while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
+ }
+
+ // calculate top and left offset for the lightbox
+ var arrayPageScroll = document.viewport.getScrollOffsets();
+ var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
+ var lightboxLeft = arrayPageScroll[0];
+ this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft +
'px' }).show();
+
+ this.changeImage(imageNum);
+ },
+
+ //
+ // changeImage()
+ // Hide most elements and preload image in preparation for resizing image
container.
+ //
+ changeImage: function(imageNum) {
+
+ this.activeImage = imageNum; // update global var
+
+ // hide elements during transition
+ if (LightboxOptions.animate) this.loading.show();
+ this.lightboxImage.hide();
+ this.hoverNav.hide();
+ this.prevLink.hide();
+ this.nextLink.hide();
+ // HACK: Opera9 does not currently support scriptaculous opacity and appear fx
+ this.imageDataContainer.setStyle({opacity: .0001});
+ this.numberDisplay.hide();
+
+ var imgPreloader = new Image();
+
+ // once image is preloaded, resize image container
+
+
+ imgPreloader.onload = (function(){
+ this.lightboxImage.src = this.imageArray[this.activeImage][0];
+ this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
+ }).bind(this);
+ imgPreloader.src = this.imageArray[this.activeImage][0];
+ },
+
+ //
+ // resizeImageContainer()
+ //
+ resizeImageContainer: function(imgWidth, imgHeight) {
+
+ // get current width and height
+ var widthCurrent = this.outerImageContainer.getWidth();
+ var heightCurrent = this.outerImageContainer.getHeight();
+
+ // get new width and height
+ var widthNew = (imgWidth + LightboxOptions.borderSize * 2);
+ var heightNew = (imgHeight + LightboxOptions.borderSize * 2);
+
+ // scalars based on change from old to new
+ var xScale = (widthNew / widthCurrent) * 100;
+ var yScale = (heightNew / heightCurrent) * 100;
+
+ // calculate size difference between new and old image, and resize if necessary
+ var wDiff = widthCurrent - widthNew;
+ var hDiff = heightCurrent - heightNew;
+
+ if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX:
false, duration: this.resizeDuration, queue: 'front'});
+ if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY:
false, duration: this.resizeDuration, delay: this.resizeDuration});
+
+ // if new and old image are same size and no scaling transition is necessary,
+ // do a quick pause to prevent image flicker.
+ var timeout = 0;
+ if ((hDiff == 0) && (wDiff == 0)){
+ timeout = 100;
+ if (Prototype.Browser.IE) timeout = 250;
+ }
+
+ (function(){
+ this.prevLink.setStyle({ height: imgHeight + 'px' });
+ this.nextLink.setStyle({ height: imgHeight + 'px' });
+ this.imageDataContainer.setStyle({ width: widthNew + 'px' });
+
+ this.showImage();
+ }).bind(this).delay(timeout / 1000);
+ },
+
+ //
+ // showImage()
+ // Display image and begin preloading neighbors.
+ //
+ showImage: function(){
+ this.loading.hide();
+ new Effect.Appear(this.lightboxImage, {
+ duration: this.resizeDuration,
+ queue: 'end',
+ afterFinish: (function(){ this.updateDetails(); }).bind(this)
+ });
+ this.preloadNeighborImages();
+ },
+
+ //
+ // updateDetails()
+ // Display caption, image number, and bottom nav.
+ //
+ updateDetails: function() {
+
+ // if caption is not null
+// if (this.imageArray[this.activeImage][1] != ""){
+ this.caption.update(this.imageArray[this.activeImage][1]).show();
+// }
+
+ // if image is part of set display 'Image x of x'
+ if (this.imageArray.length > 1){
+ this.numberDisplay.update( LightboxOptions.labelImage + ' ' +
(this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' +
this.imageArray.length).show();
+ }
+
+ new Effect.Parallel(
+ [
+ new Effect.SlideDown(this.imageDataContainer, { sync: true, duration:
this.resizeDuration, from: 0.0, to: 1.0 }),
+ new Effect.Appear(this.imageDataContainer, { sync: true, duration:
this.resizeDuration })
+ ],
+ {
+ duration: this.resizeDuration,
+ afterFinish: (function() {
+ // update overlay size and update nav
+ var arrayPageSize = this.getPageSize();
+ this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
+ this.updateNav();
+ }).bind(this)
+ }
+ );
+ },
+
+ //
+ // updateNav()
+ // Display appropriate previous and next hover navigation.
+ //
+ updateNav: function() {
+
+ this.hoverNav.show();
+
+ // if not first image in set, display prev image button
+ if (this.activeImage > 0) this.prevLink.show();
+
+ // if not last image in set, display next image button
+ if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
+
+ this.enableKeyboardNav();
+ },
+
+ //
+ // enableKeyboardNav()
+ //
+ enableKeyboardNav: function() {
+ document.observe('keydown', this.keyboardAction);
+ },
+
+ //
+ // disableKeyboardNav()
+ //
+ disableKeyboardNav: function() {
+ document.stopObserving('keydown', this.keyboardAction);
+ },
+
+ //
+ // keyboardAction()
+ //
+ keyboardAction: function(event) {
+ var keycode = event.keyCode;
+
+ var escapeKey;
+ if (event.DOM_VK_ESCAPE) { // mozilla
+ escapeKey = event.DOM_VK_ESCAPE;
+ } else { // ie
+ escapeKey = 27;
+ }
+
+ var key = String.fromCharCode(keycode).toLowerCase();
+
+ if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
+ this.end();
+ } else if ((key == 'p') || (keycode == 37)){ // display previous image
+ if (this.activeImage != 0){
+ this.disableKeyboardNav();
+ this.changeImage(this.activeImage - 1);
+ }
+ } else if ((key == 'n') || (keycode == 39)){ // display next image
+ if (this.activeImage != (this.imageArray.length - 1)){
+ this.disableKeyboardNav();
+ this.changeImage(this.activeImage + 1);
+ }
+ }
+ },
+
+ //
+ // preloadNeighborImages()
+ // Preload previous and next images.
+ //
+ preloadNeighborImages: function(){
+ var preloadNextImage, preloadPrevImage;
+ if (this.imageArray.length > this.activeImage + 1){
+ preloadNextImage = new Image();
+ preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
+ }
+ if (this.activeImage > 0){
+ preloadPrevImage = new Image();
+ preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
+ }
+
+ },
+
+ //
+ // end()
+ //
+ end: function() {
+ this.disableKeyboardNav();
+ this.lightbox.hide();
+ new Effect.Fade(this.overlay, { duration: this.overlayDuration });
+ $$('select', 'object', 'embed').each(function(node){
node.style.visibility = 'visible' });
+ },
+
+ //
+ // getPageSize()
+ //
+ getPageSize: function() {
+
+ var xScroll, yScroll;
+
+ if (window.innerHeight && window.scrollMaxY) {
+ xScroll = window.innerWidth + window.scrollMaxX;
+ yScroll = window.innerHeight + window.scrollMaxY;
+ } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but
Explorer Mac
+ xScroll = document.body.scrollWidth;
+ yScroll = document.body.scrollHeight;
+ } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
+ xScroll = document.body.offsetWidth;
+ yScroll = document.body.offsetHeight;
+ }
+
+ var windowWidth, windowHeight;
+
+ if (self.innerHeight) { // all except Explorer
+ if(document.documentElement.clientWidth){
+ windowWidth = document.documentElement.clientWidth;
+ } else {
+ windowWidth = self.innerWidth;
+ }
+ windowHeight = self.innerHeight;
+ } else if (document.documentElement && document.documentElement.clientHeight) {
// Explorer 6 Strict Mode
+ windowWidth = document.documentElement.clientWidth;
+ windowHeight = document.documentElement.clientHeight;
+ } else if (document.body) { // other Explorers
+ windowWidth = document.body.clientWidth;
+ windowHeight = document.body.clientHeight;
+ }
+
+ // for small pages with total height less then height of the viewport
+ if(yScroll < windowHeight){
+ pageHeight = windowHeight;
+ } else {
+ pageHeight = yScroll;
+ }
+
+ // for small pages with total width less then width of the viewport
+ if(xScroll < windowWidth){
+ pageWidth = xScroll;
+ } else {
+ pageWidth = windowWidth;
+ }
+
+ return [pageWidth,pageHeight];
+ }
+}
+
+document.observe('dom:loaded', function () { new Lightbox(); });
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/loading.gif
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/loading.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/nextlabel.gif
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/nextlabel.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prevlabel.gif
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prevlabel.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prototype.js
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prototype.js
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/prototype.js 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site:
http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names =
this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return
this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'),
'');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return
memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair)
{
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/,
'/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' +
match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g,
'\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') +
"'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '(a)').replace(/"[^"\\\n\r]*"/g,
'');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return
this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return
this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]',
']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length :
match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]')
&&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') +
params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) :
null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml,
*/*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding :
'');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' :
'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ &&
contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response,
response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response,
response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive',
'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') ||
'').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' :
'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name +
'">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] =
Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement ||
insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName,
content.stripScripts());
+
+ if (position == 'top' || position == 'after')
childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className':
'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return
$(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className +
"(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), '
').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' :
'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' :
element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) +
'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) +
'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case
'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') ===
'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ?
'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') ||
'').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') &&
(element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName,
content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t =
Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>',
1],
+ TBODY: ['<table><tbody>',
'</tbody></table>', 2],
+ TR: ['<table><tbody><tr>',
'</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>',
'</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>',
1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA":
"TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList",
"OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading",
"H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading",
"H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A":
"Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol",
"COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection",
"TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD":
"TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' +
D] :
+ (B.Opera) ? document.body['client' + D] :
document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft ||
document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop ||
document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see
http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() +
"']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1}
')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[(a)#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) -
string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3}
')]",
+ '|=': "[contains(concat('-', @#{1}, '-'),
'-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or
following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or
translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) +
")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1)
", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1)
", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return
Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) +
p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}",
"#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c);
c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr:
/\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] ||
matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0;
i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype))
node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype))
node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!')
results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ?
[targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + '
').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root),
formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild &&
!node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include('
' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() +
'-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted
&&
+ submit !== false && (!submit || key == submit) && (submitted
= true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name !=
name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >=
0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select',
'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') ||
'';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype ||
document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return
"dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent &&
!element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer
src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use
"return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName =
function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, '
'), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') :
iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ')
&& (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name +
' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/scriptaculous.js
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/scriptaculous.js
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/lightbox/scriptaculous.js 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (
http://script.aculo.us,
http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site:
http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript"
src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >=
" +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] :
'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load();
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictures.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictures.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictures.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,77 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="head">
+ <script type="text/javascript"
src="lightbox/prototype.js"></script>
+ <script type="text/javascript"
src="lightbox/scriptaculous.js?load=effects,builder"></script>
+ <script type="text/javascript"
src="lightbox/lightbox.js"></script>
+ <link rel="stylesheet" href="lightbox/lightbox.css"
type="text/css" media="screen" />
+ </ui:define>
+
+ <ui:define name="content">
+
+ <script type="text/javascript">
+ function confirmDelete()
+ {
+ return confirm("Are you sure you wish to delete this image? This action
cannot be undone.");
+ }
+ </script>
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{selectedMember == null}">
+ Sorry, but this member does not exist.
+ </s:div>
+
+ <s:div rendered="#{selectedMember != null}">
+
+ <h1>#{selectedMember.memberName}'s pictures</h1>
+
+ <div class="memberPictureCard">
+ <s:link view="/profile.seam" propagation="none">
+ #{selectedMember.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{selectedMember.picture.imageId}&width=90"/>
+ </s:link>
+
+ <s:span rendered="#{s:hasPermission(selectedMember,
'uploadImage')}">
+ [<s:link view="/pictureupload.xhtml"
action="#{pictureAction.uploadPicture}" value="Upload picture"
propagation="none"/>]
+ </s:span>
+
+ <br style="clear:both"/>
+ </div>
+
+ <div class="memberPictures">
+ <ui:repeat value="#{memberImages}" var="img">
+
+ <div class="thumbnail">
+ <a href="content/images?id=#{img.imageId}"
rel="lightbox[pictureset]" title="#{img.caption}">
+ <h:graphicImage
value="/content/images?id=#{img.imageId}&width=90"
border="0"/>
+ </a>
+ <s:button view="/imagepermissions.seam"
+
action="#{permissionSearch.search(pictureSearch.lookupImage())}"
+ styleClass="padlock"
+ rendered="#{s:hasPermission(img,
'seam.grant-permission')}">
+ <f:param name="imageId"
value="#{img.imageId}"/>
+ </s:button>
+ <s:button styleClass="trash"
+ action="#{pictureSearch.delete(pictureSearch.lookupImage())}"
+ rendered="#{s:hasPermission(img, 'delete')}"
+ onclick="if (!confirmDelete()) return false">
+ <f:param name="imageId"
value="#{img.imageId}"/>
+ </s:button>
+ </div>
+
+ </ui:repeat>
+ </div>
+
+ </s:div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictureupload.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictureupload.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/pictureupload.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+ <div id="contentMain">
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <h3>Upload Picture</h3>
+
+ <div>
+
+ <h:form styleClass="register"
enctype="multipart/form-data">
+ <s:validateAll>
+
+ <div class="formRow">
+ <h:outputLabel
for="caption">Caption</h:outputLabel>
+ <h:inputText id="caption"
value="#{pictureAction.memberImage.caption}"/>
+ <div class="validationError"><h:message
for="caption"/></div>
+ </div>
+
+
+ <div class="formRow">
+ <h:outputLabel
for="picture">Picture</h:outputLabel>
+ <s:fileUpload id="picture"
data="#{pictureAction.memberImage.data}"
+
contentType="#{pictureAction.memberImage.contentType}" />
+ <div class="validationError"><h:message
for="picture"/></div>
+ </div>
+
+ </s:validateAll>
+
+ <div class="buttons">
+ <h:commandButton value="Upload"
action="#{pictureAction.savePicture}" styleClass="formButton"/>
+ <s:button value="Cancel" propagation="end"
view="/pictures.xhtml" styleClass="formButton">
+ <f:param name="name"
value="#{authenticatedMember.memberName}"/>
+ </s:button>
+ </div>
+
+ </h:form>
+
+ <br class="clear"/>
+ </div>
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/profile.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/profile.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/profile.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,117 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <s:div rendered="#{selectedMember == null}">
+ Sorry, but this member does not exist.
+ </s:div>
+
+ <s:div rendered="#{selectedMember != null}">
+
+ <s:div id="memberCard">
+ <h1>#{selectedMember.memberName}'s profile</h1>
+
+ <s:div id="memberCardPicture"
rendered="#{selectedMember.picture ne null}">
+ <h:graphicImage
value="/content/images?id=#{selectedMember.picture.imageId}&width=170"/>
+ </s:div>
+
+ <div id="memberCardText">
+ <span
class="tagline">"#{selectedMember.tagline}"</span><br/><br/>
+ #{selectedMember.gender.descr}<br/>
+ #{selectedMember.age}<br/>
+ #{selectedMember.location}<br/>
+ </div>
+
+ <br style="clear:both"/>
+
+ View My:
+ <s:link view="/pictures.xhtml" value="Pics">
+ <f:param name="name"
value="#{selectedMember.memberName}"/>
+ </s:link>
+
+ </s:div>
+
+ <s:div id="memberBlog">
+ <div class="sectionHeader">#{selectedMember.memberName}'s
latest blog entries</div>
+
+ <ui:repeat value="#{profile.latestBlogs}"
var="latestBlog">
+ <div class="blogSummary">#{latestBlog.title}
+ (<s:link view="/blogentry.xhtml" value="view
more">
+ <f:param name="name"
value="#{selectedMember.memberName}"/>
+ <f:param name="blogId"
value="#{latestBlog.blogId}"/>
+ </s:link>)
+ </div>
+ </ui:repeat>
+
+ [<s:link id="viewBlog" view="/blog.xhtml"
value="View all blog entries" propagation="none">
+ <f:param name="name"
value="#{selectedMember.memberName}"/>
+ </s:link>]
+
+ <s:span rendered="#{s:hasPermission(selectedMember,
'createBlog')}">
+ [<s:link id="createBlog" action="#{blog.createEntry}"
value="Create new blog entry" propagation="none"/>]
+ </s:span>
+ </s:div>
+
+ <s:div id="memberFriends">
+ <div class="sectionHeader">#{selectedMember.memberName}'s
friends</div>
+
+ <ui:repeat value="#{profile.friends}" var="f">
+ <div class="friend">
+
+ <s:link view="/profile.xhtml"
propagation="none">
+ <f:param name="name" value="#{f.memberName}"/>
+ #{f.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{f.picture.imageId}&width=90"/>
+ </s:link>
+
+ </div>
+ </ui:repeat>
+
+ <br class="clear"/>
+
+ <s:span rendered="#{selectedMember.memberId !=
authenticatedMember.memberId and s:hasPermission(selectedMember,
'createFriendRequest')}">
+ [<s:link view="/friendrequest.xhtml"
action="#{friendAction.createRequest}" value="Send a friend
request"/>]
+ </s:span>
+
+ </s:div>
+
+ <s:div id="friendComments">
+ <div class="sectionHeader">#{selectedMember.memberName}'s
friend's comments</div>
+
+ <ui:repeat value="#{profile.friendComments}" var="c">
+ <table class="friendComments">
+ <tr>
+ <td class="friendCommentor">
+ <s:link view="/profile.xhtml">
+ <f:param name="name"
value="#{c.friend.memberName}"/>
+ #{c.friend.memberName}<br/>
+ <h:graphicImage
value="/content/images?id=#{c.friend.picture.imageId}&width=90"/>
+ </s:link>
+ </td>
+
+ <td style="text-align: left">
+ <b>#{c.formattedCommentDate}</b><br/>
+ <p><s:formattedText
value="#{c.comment}"/></p>
+ </td>
+ </tr>
+ </table>
+ </ui:repeat>
+
+ <s:span rendered="#{s:hasPermission(selectedMember,
'createFriendComment')}">
+ [<s:link view="/friendcomment.xhtml" value="Add
Comment"/>]
+ </s:span>
+ </s:div>
+ </s:div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib"
+
xmlns:rich="http://richfaces.org/rich">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+ <div id="contentMain">
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <p>
+ Already a member? <s:link view="/home.seam" value="Click here
to log in" propagation="none"/>
+ </p>
+
+ <div id="register">
+ <div class="registerHeader">
+ JOIN SEAMSPACE HERE!
+ </div>
+
+ <h:form styleClass="register">
+ <s:validateAll>
+ <div class="formRow">
+ <h:outputLabel for="email">Email
address<em>*</em></h:outputLabel>
+ <h:inputText id="email"
value="#{register.member.email}" required="true"
styleClass="wide"/>
+ <div class="validationError"><h:message
for="email"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="firstName">First
name<em>*</em></h:outputLabel>
+ <h:inputText id="firstName"
value="#{register.member.firstName}" required="true"/>
+ <div class="validationError"><h:message
for="firstName"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="lastName">Last
name<em>*</em></h:outputLabel>
+ <h:inputText id="lastName"
value="#{register.member.lastName}" required="true"/>
+ <div class="validationError"><h:message
for="lastName"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="memberName">Nick
name<em>*</em></h:outputLabel>
+ <h:inputText id="memberName"
value="#{register.member.memberName}" required="true"/>
+ <div class="validationError"><h:message
for="memberName"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel
for="username">Username<em>*</em></h:outputLabel>
+ <h:inputText id="username"
value="#{register.username}" required="true"/>
+ <div class="validationError"><h:message
for="username"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel
for="password">Password<em>*</em></h:outputLabel>
+ <h:inputSecret id="password"
value="#{register.password}" required="true"/>
+ <div class="validationError"><h:message
for="password"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="confirmPassword">Confirm
password<em>*</em></h:outputLabel>
+ <h:inputSecret id="confirmPassword"
value="#{register.confirm}" required="true"/>
+ <div class="validationError"><h:message
for="confirmPassword"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel
for="gender">Gender<em>*</em></h:outputLabel>
+ <h:selectOneRadio id="gender"
value="#{register.gender}" required="true">
+ <f:selectItem itemValue="Male" itemLabel="Male"
/>
+ <f:selectItem itemValue="Female"
itemLabel="Female" />
+ </h:selectOneRadio>
+ <div class="validationError"><h:message
for="gender"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="dob">Date of
birth<em>*</em></h:outputLabel>
+ <rich:calendar id="dob"
value="#{register.member.dob}" required="true"
datePattern="MM/dd/yyyy" buttonIcon="images/ellipsis.png" />
+ <div class="validationError"><h:message
for="dob"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="verifyCaptcha"><h:graphicImage
value="/seam/resource/captcha"/><em>*</em></h:outputLabel>
+ <h:inputText id="verifyCaptcha"
value="#{captcha.response}" required="true"/>
+ <div class="validationError"><h:message
for="verifyCaptcha"/></div>
+ </div>
+
+ </s:validateAll>
+
+ <div class="buttons">
+ <h:commandButton value="Next"
action="#{register.next}" styleClass="registerButton"/>
+ </div>
+
+ </h:form>
+
+ <br class="clear"/>
+ </div>
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register2.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register2.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/register2.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,42 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+ <div id="contentMain">
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ <div id="register">
+ <div class="registerHeader">
+ JOIN SEAMSPACE HERE!
+ </div>
+
+ <h:form styleClass="register"
enctype="multipart/form-data">
+ <s:validateAll>
+
+ <div class="formRow">
+ <h:outputLabel for="picture">Member
photo</h:outputLabel>
+ <s:fileUpload id="picture"
data="#{register.picture}" accept="image/png"
+ contentType="#{register.pictureContentType}"
/>
+ <div class="validationError"><h:message
for="picture"/></div>
+ </div>
+
+ </s:validateAll>
+
+ <div class="buttons">
+ <h:commandButton value="Upload"
action="#{register.uploadPicture}" styleClass="registerButton"/>
+ </div>
+
+ </h:form>
+
+ <br class="clear"/>
+ </div>
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.page.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.page.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.page.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,9 @@
+<page
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd">
+ <navigation from-action="#{roleAction.save}">
+ <rule if-outcome="success">
+ <redirect view-id="/rolemanager.xhtml"/>
+ </rule>
+ </navigation>
+</page>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/roledetail.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:rich="http://richfaces.org/rich"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <div id="contentMain">
+
+ <h2>Role Details</h2>
+
+ <h:messages globalOnly="true"/>
+
+ <h:form id="role">
+
+ <div class="formRow">
+ <h:outputLabel for="role" value="Role"
styleClass="formLabel"/>
+ <h:inputText id="name" value="#{roleAction.role}"
readonly="#{identityManager.userExists(roleAction.role)}"/>
+ <div class="validationError"><h:message
for="role"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="groups" value="Member of"
styleClass="formLabel"/>
+ <div class="selectMany">
+ <h:selectManyCheckbox id="roles"
value="#{roleAction.groups}" layout="pageDirection"
styleClass="roles">
+ <s:selectItems value="#{roleAction.assignableRoles}"
var="role" label="#{role}"/>
+ </h:selectManyCheckbox>
+ </div>
+ <div class="validationError"><h:message
for="groups"/></div>
+ </div>
+
+ <div class="formButtons">
+ <h:commandButton id="save" value="Save"
action="#{roleAction.save}" styleClass="formButton"/>
+ <s:button id="cancel" view="/rolemanager.xhtml"
value="Cancel" propagation="end"
styleClass="formButton"/>
+ </div>
+
+ <br class="clear"/>
+
+ </h:form>
+
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.page.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.page.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.page.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,14 @@
+<page
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd"
+ action="#{roleSearch.loadRoles}">
+ <restrict>#{s:hasPermission('seam.role',
'read')}</restrict>
+
+ <navigation from-action="#{roleAction.createRole}">
+ <redirect view-id="/roledetail.xhtml"/>
+ </navigation>
+
+ <navigation
from-action="#{roleAction.editRole(roleSearch.selectedRole)}">
+ <redirect view-id="/roledetail.xhtml"/>
+ </navigation>
+</page>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/rolemanager.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,61 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <script type="text/javascript">
+ function confirmDelete()
+ {
+ return confirm("Are you sure you wish to delete this role? This action
cannot be undone.");
+ }
+ </script>
+
+ <div id="contentMain">
+
+ <h2>Role Manager</h2>
+
+ <s:button id="newRole" action="#{roleAction.createRole}"
styleClass="newrole" rendered="#{s:hasPermission('seam.account',
'create', null)}"/>
+
+ <h:dataTable
+ id="threads"
+ value="#{roles}"
+ var="role"
+ styleClass="security"
+ cellspacing="0"
+ headerClass="header"
+ rowClasses="odd,even"
+ columnClasses=",,action">
+ <h:column width="auto">
+ <f:facet name="header">Role</f:facet>
+ #{role}
+ </h:column>
+ <h:column id="roles" width="auto">
+ <f:facet name="header">Member Of</f:facet>
+ #{roleSearch.getRoleGroups(role)}
+ </h:column>
+ <h:column width="auto">
+ <f:facet name="header">Action</f:facet>
+ <s:fragment rendered="#{s:hasPermission('seam.role',
'update')}">
+ <s:link id="edit" value="Edit"
action="#{roleAction.editRole(roleSearch.selectedRole)}"/><span> |
</span>
+ </s:fragment>
+ <s:link id="delete" value="Delete"
action="#{identityManager.deleteRole(roleSearch.selectedRole)}"
+ rendered="#{s:hasPermission('seam.role',
'delete')}"
+ onclick="return confirmDelete()"/>
+ </h:column>
+ </h:dataTable>
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <div id="contentMain">
+
+ <h2>Security</h2>
+
+ <s:button id="manageUsers" view="/usermanager.xhtml"
styleClass="manageusers" value="Manage Users"/><br/>
+ <s:button id="manageRoles" view="/rolemanager.xhtml"
styleClass="manageroles" value="Manage Roles"/>
+
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security_error.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security_error.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/security_error.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+ <ui:define name="content">
+
+ <h1>A Security Error has occurred</h1>
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/advertising.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/advertising.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newpermission.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newpermission.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newrole.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newrole.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newuser.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/btn_newuser.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/cal-next.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/cal-next.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/cal-prev.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/cal-prev.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/date.css
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/date.css
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/date.css 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,185 @@
+div.seam-date
+{
+ margin-top: 5px;
+ border: 1px solid #AAAAAA;
+ background: #fff url(../img/input.bg.gif) 0 0 repeat-x;
+ background-color: #FFFFFF;
+ color: #505050;
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+}
+
+table.seam-date td {
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-weight: 11px;
+}
+
+.seam-date-monthNames
+{
+ width: 70px;
+ border: 1px solid #dddddd;
+ border-right: 3px solid #444444;
+ border-bottom: 3px solid #444444;
+ background-color: #ffffff;
+ font-size: 12px;
+ cursor: pointer;
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-weight: normal;
+}
+
+a.seam-date-monthNameLink, a.seam-date-monthNameLink:visited
+{
+ text-align: center;
+ display: block;
+ color: #555555;
+}
+
+a.seam-date-monthNameLink:hover
+{
+ background-color: #CCCCCC;
+ color: red;
+}
+
+.seam-date-years
+{
+ height: 10em;
+ overflow: auto;
+ width: 60px;
+ border: 1px solid #dddddd;
+ border-right: 3px solid #444444;
+ border-bottom: 3px solid #444444;
+ background-color: #ffffff;
+ font-size: 12px;
+ cursor: pointer;
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-weight: normal;
+}
+
+a.seam-date-yearLink, a.seam-date-yearLink:visited
+{
+ text-align: center;
+ display: block;
+ color: #555555;
+}
+
+a.seam-date-yearLink:hover
+{
+ background-color: #CCCCCC;
+ color: red;
+}
+
+tr.seam-date-header
+{
+ padding: 2px 0px 2px 0px;
+}
+
+td.seam-date-header
+{
+ padding: 0px 8px 0px 8px;
+ text-align: center;
+ color: gray;
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-weight: bold;
+ font-size: 12px;
+}
+
+td.seam-date-header-prevMonth
+{
+ background-image: url("cal-prev.png");
+ background-repeat: no-repeat;
+ background-position: center;
+ padding: 0px 2px 0px 2px;
+ width: 17px;
+ height: 16px;
+ margin-left: 2px;
+}
+
+td.seam-date-header-nextMonth
+{
+ background-image: url("cal-next.png");
+ background-repeat: no-repeat;
+ background-position: center;
+ padding: 0px 2px 0px 2px;
+ width: 17px;
+ height: 16px;
+ margin-right: 2px;
+}
+
+tr.seam-date-headerDays
+{
+ color: white;
+ font-weight: normal;
+}
+
+tr.seam-date-headerDays > td
+{
+ background-color: #CCCCCC;
+ border: 1px solid #AAAAAA;
+ color: white;
+ text-align: center;
+ width: 26px;
+}
+
+tr.seam-date-footer
+{
+ background-color: white;
+ color: #505050;
+ font-weight: bold;
+}
+
+tr.seam-date-footer > td
+{
+ text-align: center;
+}
+
+td.seam-date-inMonth
+{
+ background-color: white;
+ color: black;
+ font-weight: normal;
+ cursor: pointer;
+ border: 1px solid #ece9d8;
+}
+
+td.seam-date-outMonth
+{
+ background-color: white;
+ color: #999999;
+ font-weight: normal;
+ cursor: pointer;
+ border: 1px solid #ece9d8;
+}
+
+td.seam-date-selected
+{
+ background-color: #CCCCCC;
+ border: 1px solid #AAAAAA;
+ color: black;
+ font-weight: normal;
+}
+
+td.seam-date-dayOff-inMonth
+{
+ background-color: #efefef;
+ color: black;
+ font-weight: normal;
+ cursor: pointer;
+ border: 1px solid #ece9d8;
+}
+
+td.seam-date-dayOff-outMonth
+{
+ background-color: #efefef;
+ color: #999999;
+ font-weight: normal;
+ cursor: pointer;
+ border: 1px solid #ece9d8;
+}
+
+td.seam-date-hover
+{
+ background-color: #CCCCCC;
+ border: 1px solid #AAAAAA;
+ cursor: pointer;
+ color: red;
+}
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/divider.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/divider.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/manage_roles.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/manage_roles.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/manage_users.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/manage_users.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/padlock.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/padlock.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.css
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.css
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.css 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,600 @@
+body {
+ font-family: verdana, arial, sans-serif, helvetica;
+ background-color: #e5e5e5;
+ font-size:11px;
+ margin: 0;
+}
+
+h1, h2, h3 {
+ margin-top: 2px;
+ margin-bottom: 6px;
+}
+
+#header {
+ margin-left: auto;
+ margin-right: auto;
+ background: url(seamspace.png) left top no-repeat;
+ height: 100px;
+ width: 800px;
+ background-color: #003399;
+}
+
+#menubar {
+ margin-left: auto;
+ margin-right: auto;
+ overflow: none;
+ height: 17px;
+ width: 800px;
+ background-color: #5a8cc0;
+ text-align: center;
+ padding-top: 3px;
+}
+
+#content {
+ padding-top: 10px;
+ margin-left: auto;
+ margin-right: auto;
+ width: 800px;
+ background-color: #ffffff;
+ min-height: 800px;
+}
+
+#content a, #content a:visited {
+ font-weight: bold;
+ color: #003399;
+}
+
+#content a:hover {
+ font-weight: bold;
+ color: #7799dd;
+}
+
+#contentMain {
+ float: left;
+ width: 430px;
+ margin-left: 10px;
+ margin-top: 10px;
+}
+
+#contentDivider {
+ float: left;
+ background: url(divider.png) repeat-y top left;
+ height: 100%;
+ width: 10px;
+}
+
+#contentSide {
+ float: left;
+ width: 310px;
+ margin-left: 10px;
+ margin-top: 10px;
+ margin-right: 10px;
+}
+
+#memberCard {
+ width: 350px;
+ float: left;
+ margin-left: 10px;
+ border: 2px solid #eeeeee;
+ background-color: #f5f5f5;
+ padding: 2px;
+}
+
+#memberCardPicture {
+ width: 170px;
+ float: left;
+}
+
+#memberCardText {
+ width: 170px;
+ float: right;
+}
+
+#memberBlog {
+ width: 400px;
+ float: right;
+ margin-right: 10px;
+ border: 2px solid #eeeeee;
+ padding: 2px;
+}
+
+#blogMemberCard {
+ width: 140px;
+ float: left;
+ margin-left: 10px;
+ border: 2px solid #eeeeee;
+ background-color: #f5f5f5;
+ padding: 2px;
+ text-align: center;
+}
+
+#blog {
+ float: right;
+ width: 600px;
+ margin-right: 10px;
+ padding: 2px;
+}
+
+#memberFriends {
+ width: 400px;
+ float: right;
+ margin-right: 10px;
+ margin-top: 12px;
+ border: 2px solid #eeeeee;
+ padding: 2px;
+}
+
+div.friend {
+ float: left;
+ width: 99px;
+ text-align: center;
+}
+
+#friendComments {
+ width: 400px;
+ float: right;
+ margin-right: 10px;
+ margin-top: 12px;
+ border: 2px solid #eeeeee;
+ padding: 2px;
+}
+
+table.friendComments {
+ width: 100%;
+}
+
+table.friendComments td {
+ border: 1px solid #dddddd;
+ background-color: #eeeeee;
+ text-align: center;
+ vertical-align: top;
+}
+
+td.friendCommentor {
+ width: 100px;
+}
+
+div.friendRequest {
+ background-color: #bbddff;
+ width: 600px;
+ float: right;
+ margin-right: 10px;
+ border: 2px solid #eeeeee;
+ padding: 4px;
+}
+
+div.friendRequest textarea {
+ font-family: verdana, arial, sans-serif, helvetica;
+ font-size:11px;
+ margin: 4px 12px 8px 0px;
+ width: 560px;
+ height: 120px;
+}
+
+div.blogSummary {
+ padding: 0px 2px 4px 2px;
+ margin-bottom: 8px;
+}
+
+div.blogEntry {
+ background-color: #bbddff;
+ padding: 8px 8px 8px 8px;
+ margin-bottom: 12px;
+}
+
+div.blogEntry label {
+ font-weight: bold;
+}
+
+div.blogEntry input.title {
+ width: 560px;
+}
+
+div.blogEntry textarea {
+ font-family: verdana, arial, sans-serif, helvetica;
+ font-size:11px;
+ margin: 4px 12px 8px 0px;
+ width: 560px;
+ height: 120px;
+}
+
+div.blogDate {
+ font-weight: bold;
+ margin-bottom: 8px;
+}
+
+div.blogTitle {
+ font-weight: bold;
+ margin-left: 24px;
+ margin-bottom: 8px;
+}
+
+div.blogText {
+ margin-left: 24px;
+ margin-bottom: 8px;
+ text-align: justify;
+}
+
+div.blogFooter {
+ margin-bottom: 8px;
+}
+
+table.blogComment {
+ margin-bottom: 2px;
+ width: 100%;
+}
+
+td.blogCommentor {
+ width: 160px;
+ background-color: #ff9933;
+ text-align: center;
+ vertical-align: top;
+}
+
+td.blogCommentText {
+ background-color: #ffddbb;
+ padding: 12px 4px 4px 8px;
+}
+
+div.commentEntry {
+ background-color: #ff9933;
+ padding: 4px 4px 4px 4px;
+}
+
+div.commentEntry label {
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 4px;
+}
+
+div.commentEntry textarea {
+ font-family: verdana, arial, sans-serif, helvetica;
+ font-size:11px;
+ margin: 8px 12px 8px 6px;
+ width: 560px;
+ height: 120px;
+}
+
+div.buttons {
+ float: right;
+}
+
+input.action {
+ display: inline;
+ margin-right: 8px;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ border: 1px solid #003399;
+ background-color: #ffffff;
+ color: #003399;
+ font-size: 10px;
+ padding: 3px 8px 3px 8px;
+}
+
+div.headerRight {
+ float: right;
+ width: 440px;
+ padding-right: 4px;
+ padding-top: 4px;
+}
+
+div.headerMenu {
+ float: right;
+}
+
+div.advertising {
+ background: url(advertising.png) no-repeat top left;
+ width: 307px;
+ height: 86px;
+}
+
+div.sectionHeader {
+ font-weight: bold;
+ font-size: normal;
+ background-color: #eeeeee;
+ padding: 2px 2px 2px 2px;
+ margin-bottom: 12px;
+}
+
+span.tagline {
+ font-style: italic;
+}
+
+a, a:visited, a:hover {
+ color: #ffffff;
+ text-decoration: none;
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+#header a:hover {
+ text-decoration: underline;
+}
+
+#search {
+ margin-top: 2px;
+}
+
+#search a:hover {
+ margin-bottom: 4px;
+ text-decoration: none;
+}
+
+input.searchField {
+ width: 290px;
+}
+
+input.searchButton {
+ width: 140px;
+}
+
+#menubar a:hover {
+ color: #003399;
+ text-decoration: underline;
+}
+
+div.memberLogin {
+ margin-top: 16px;
+ width: 300px;
+ border: 1px solid #003399;
+ padding: 0px;
+}
+
+div.loginHeader {
+ color: #ffffff;
+ font-weight: bold;
+ background-color: #003399;
+ height: 18px;
+ padding: 2px 2px 2px 2px;
+}
+
+div.newMembers {
+ width: 300px;
+ margin-top: 8px;
+ border: 1px solid #ffcc99;
+}
+
+div.newMembersHeader {
+ font-weight: bold;
+ background-color: #ffcc99;
+ height: 18px;
+ padding: 2px 2px 2px 2px;
+}
+
+div.newMember {
+ float: left;
+ width: 99px;
+ text-align: center;
+}
+
+div.newMember img {
+ border: none;
+}
+
+div.loginRow {
+ padding-top: 2px;
+ padding-bottom: 2px;
+}
+
+label.loginLabel {
+ float: left;
+ width: 100px;
+ padding: 2px 2px 2px 2px;
+}
+
+div.buttons {
+ float: right;
+ margin-right: 60px;
+}
+
+input.loginButton {
+ display: inline;
+ margin-right: 8px;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ border: 1px solid #003399;
+ background-color: #ffffff;
+ color: #003399;
+ font-size: 10px;
+ padding: 3px 8px 3px 8px;
+}
+
+input.registerButton {
+ display: inline;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ border: 1px solid #ffa76d;
+ background-color: #ff6600;
+ color: #ffffff;
+ font-size: 10px;
+ padding: 3px 8px 3px 8px;
+}
+
+div.loginRow input[type='text'], div.loginRow input[type='password'] {
+ width: 180px;
+}
+
+.clear {
+ clear: both;
+ font-size: 0px;
+}
+
+.divider {
+ color: #aaaaaa;
+}
+
+div.errors {
+ color: #ff0000;
+ font-weight: bold;
+ font-size: normal;
+}
+
+div.errors ul {
+ list-style: none;
+}
+
+#register {
+ float: left;
+ width: 400px;
+ border: 1px solid #5a8cc0;
+}
+
+div.registerHeader {
+ font-size: normal;
+ font-weight: bold;
+ color: #ffffff;
+ background-color: #5a8cc0;
+ padding: 8px 4px 8px 12px;
+}
+
+form.register label {
+ float: left;
+ display: block;
+ vertical-align: top;
+ width: 120px;
+ margin-top: 2px;
+}
+
+form.register input.wide {
+ width: 240px;
+}
+
+form.register em {
+ font-size: normal;
+ font-weight: bold;
+ color: #ff0000;
+}
+
+form.register div.validationError {
+ margin-left: 120px;
+ font-weight: bold;
+ color: #ff0000;
+}
+
+img.ellipsis {
+ width: 18px;
+ height: 18px;
+ border: none;
+ margin-bottom: 2px;
+ margin-left: 2px;
+ vertical-align: bottom;
+ cursor: pointer;
+}
+
+div.seam-date {
+ background-color: #ffffff;
+ border: 1px solid #5a8cc0;
+}
+
+td.seam-date-hover {
+ background-color: #5a8cc0;
+ color: #ffffff;
+ cursor: pointer;
+}
+
+quote {
+ border: 1px solid #fac289;
+ margin: 4px 8px 4px 8px;
+ padding: 12px 12px 12px 12px;
+ background-color: #fbf4ec;
+ display: block;
+}
+
+/* General form styles */
+
+div.formRow {
+ padding: 3px 4px 3px 2px;
+ clear: both;
+}
+
+div.formRow label {
+ float: left;
+ width: 120px;
+ padding: 2px 2px 2px 2px;
+}
+
+div.formRow input[type='text'] {
+ width: 120px;
+}
+
+div.formRow input[type='password'] {
+ width: 120px;
+}
+
+div.validationError {
+ margin-left: 120px;
+ font-weight: bold;
+ color: #ff0000;
+}
+
+.roles {
+ width: 120px;
+ border: 1px solid #7F9DB9;
+ background-color: #E7EDF7;
+}
+
+div.selectMany label {
+ float: none;
+}
+
+.formButton {
+ background: url(../images/bg_button.png) top left repeat-x;
+ border: 1px solid #003399;
+ font-size: small;
+ font-weight: bold;
+ color: #000000;
+ margin-right: 8px;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+div.formButtons {
+ float: right;
+ padding: 4px 8px 16px 2px;
+}
+
+div.memberPictures {
+ float: right;
+ width: 600px;
+ margin-right: 10px;
+ padding: 2px;
+ background-color: #000000;
+ border: 1px solid #aaaaaa;
+ padding: 8px 8px 8px 8px;
+}
+
+div.memberPictureCard {
+ width: 140px;
+ float: left;
+ margin-left: 10px;
+ border: 2px solid #eeeeee;
+ background-color: #f5f5f5;
+ padding: 2px;
+ text-align: center;
+}
+
+div.thumbnail {
+ width: 110px;
+ background-color: #333333;
+ padding: 10px 10px 10px 10px;
+ margin: 8px 8px 8px 8px;
+ float: left;
+ text-align: center;
+}
+
+input.padlock {
+ background: url(padlock.png) top left no-repeat;
+ width: 14px;
+ height: 20px;
+ float: left;
+ border: 0px;
+ margin-left: 10px;
+}
+
+input.trash {
+ background: url(trash.png) top left no-repeat;
+ width: 20px;
+ height: 20px;
+ float: left;
+ border: 0px;
+}
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/seamspace.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/security.css
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/security.css
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/security.css 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,126 @@
+input.newuser {
+ background: url(btn_newuser.png) top left no-repeat;
+ height: 39px;
+ width: 113px;
+ margin: 4px 4px 4px 4px;
+ border: 0px;
+ cursor: pointer;
+}
+
+input.newrole {
+ background: url(btn_newrole.png) top left no-repeat;
+ height: 39px;
+ width: 113px;
+ margin: 4px 4px 4px 4px;
+ border: 0px;
+ cursor: pointer;
+}
+
+input.newpermission {
+ background: url(btn_newpermission.png) top left no-repeat;
+ height: 39px;
+ width: 113px;
+ margin: 4px 4px 4px 4px;
+ border: 0px;
+ cursor: pointer;
+}
+
+input.manageusers {
+ display: block;
+ background: url(manage_users.png) top left no-repeat;
+ height: 88px;
+ width: 300px;
+ padding-left: 10px;
+ font-size: 19px;
+ font-weight: bold;
+ color: #333333;
+ border: 0px;
+ cursor: pointer;
+ margin-top: 20px;
+ margin-left: 20px;
+}
+
+input.manageroles {
+ display: block;
+ background: url(manage_roles.png) top left no-repeat;
+ height: 88px;
+ width: 300px;
+ padding-left: 10px;
+ font-size: 19px;
+ font-weight: bold;
+ color: #333333;
+ border: 0px;
+ cursor: pointer;
+ margin-top: 20px;
+ margin-left: 20px;
+}
+
+.roles {
+ width: 120px;
+ border: 1px solid #7F9DB9;
+ background-color: #E7EDF7;
+}
+
+div.selectMany label {
+ float: none;
+}
+
+.formButton {
+ background: url(../images/bg_button.png) top left repeat-x;
+ border: 1px solid #003399;
+ font-size: small;
+ font-weight: bold;
+ color: #000000;
+ margin-right: 8px;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+div.formButtons {
+ float: right;
+ padding: 4px 8px 16px 2px;
+}
+
+div.checkmark {
+ background: url(../images/checkmark.png) top left no-repeat;
+ width: 14px;
+ height: 15px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+div.cross {
+ background: url(../images/cross.png) top left no-repeat;
+ width: 14px;
+ height: 15px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.security {
+ border: 1px solid black;
+ width: 500px;
+}
+
+th.header {
+ background: url(table_header.png) top left repeat-x;
+ color: #ffffff;
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+tr.odd {
+ background-color: #ffffff;
+}
+
+tr.even {
+ background-color: #E9F5FF;
+}
+
+td.enabled {
+ text-align: center;
+}
+
+td.action {
+ text-align: right;
+}
\ No newline at end of file
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/table_header.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/table_header.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/trash.png
===================================================================
(Binary files differ)
Property changes on:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/style/trash.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/template.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/template.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/template.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:s="http://jboss.com/products/seam/taglib"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core">
+
+<h:head>
+ <meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1" />
+ <title>SeamSpace</title>
+ <link href="style/seamspace.css" rel="stylesheet"
type="text/css"/>
+ <link href="style/date.css" rel="stylesheet"
type="text/css"/>
+ <ui:insert name="head"/>
+</h:head>
+
+<body>
+
+ <div id="header">
+ <div class="headerRight">
+ <div class="headerMenu">
+
+ <s:fragment rendered="#{identity.loggedIn}">
+ <s:link id="profile" view="/profile.xhtml"
value="My Profile" propagation="none">
+ <f:param name="name"
value="#{authenticatedMember.memberName}"/>
+ </s:link>
+ <h:outputText styleClass="divider" value=" | "/>
+ </s:fragment>
+
+ <s:fragment rendered="#{s:hasRole('admin')}">
+ <s:link id="security" view="/security.xhtml"
value="Security" propagation="none"/>
+ <h:outputText styleClass="divider" value=" | "/>
+ </s:fragment>
+
+ <s:link id="logout" action="#{identity.logout}"
value="Log out" rendered="#{identity.loggedIn}"/>
+ <h:outputLink id="login" value="home.seam"
rendered="#{not identity.loggedIn}">Log in</h:outputLink>
+ </div>
+ <br style="clear:both"/>
+ <h:form>
+ <div>
+ <a href="#">SeamSpace</a><h:outputText
styleClass="divider" value=" | "/>
+ <a href="#">People</a><h:outputText
styleClass="divider" value=" | "/>
+ <a href="#">Music</a><h:outputText
styleClass="divider" value=" | "/>
+ <a href="#">Blogs</a>
+ </div>
+ <div id="search">
+ <h:inputText type="text" styleClass="searchField"/>
+ <h:commandButton value="Search SeamSpace"
onclick="javascript:alert('This feature coming soon!');return false"
styleClass="searchButton"/>
+ </div>
+ </h:form>
+ </div>
+ </div>
+
+ <div id="menubar">
+ <s:link view="/home.xhtml" value="Home"
propagation="none"/><h:outputText styleClass="divider"
value=" | "/>
+ <s:link value="Browse" onclick="javascript:alert('This feature
coming soon!');return false"/><h:outputText styleClass="divider"
value=" | "/>
+ <s:link value="Blog" onclick="javascript:alert('This feature
coming soon!');return false"/><h:outputText styleClass="divider"
value=" | "/>
+ <s:link value="Music" onclick="javascript:alert('This feature
coming soon!');return false"/>
+ </div>
+
+ <div id="content">
+ <ui:insert name="content"/>
+ </div>
+
+</body>
+</html>
+
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.page.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.page.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.page.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,9 @@
+<page
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd">
+ <navigation from-action="#{userAction.save}">
+ <rule if-outcome="success">
+ <redirect view-id="/usermanager.xhtml"/>
+ </rule>
+ </navigation>
+</page>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/userdetail.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:rich="http://richfaces.org/rich"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <div id="contentMain">
+
+ <h2>User Details</h2>
+
+ <h:messages globalOnly="true"/>
+
+ <h:form id="user">
+
+ <div class="formRow">
+ <h:outputLabel for="firstname" value="First name"
styleClass="formLabel"/>
+ <h:inputText id="firstname"
value="#{userAction.firstname}"
readonly="#{identityManager.userExists(userAction.username)}"/>
+ <div class="validationError"><h:message
for="firstname"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="lastname" value="Last name"
styleClass="formLabel"/>
+ <h:inputText id="lastname"
value="#{userAction.lastname}"
readonly="#{identityManager.userExists(userAction.username)}"/>
+ <div class="validationError"><h:message
for="lastname"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="username" value="Username"
styleClass="formLabel"/>
+ <h:inputText id="username"
value="#{userAction.username}"
readonly="#{identityManager.userExists(userAction.username)}"/>
+ <div class="validationError"><h:message
for="username"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="password" value="Password"
styleClass="formLabel"/>
+ <h:inputSecret id="password"
value="#{userAction.password}"/>
+ <div class="validationError"><h:message
for="password"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="confirm" value="Confirm password"
styleClass="formLabel"/>
+ <h:inputSecret id="confirm"
value="#{userAction.confirm}"/>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="roles" value="Member of"
styleClass="formLabel"/>
+ <div class="selectMany">
+ <h:selectManyCheckbox id="roles"
value="#{userAction.roles}" layout="pageDirection"
styleClass="roles">
+ <s:selectItems
value="#{identityManager.listGrantableRoles()}" var="role"
label="#{role}"/>
+ </h:selectManyCheckbox>
+ </div>
+ <div class="validationError"><h:message
for="roles"/></div>
+ </div>
+
+ <div class="formRow">
+ <h:outputLabel for="enabled" value="Account enabled"
styleClass="formLabel"/>
+ <h:selectBooleanCheckbox id="enabled"
value="#{userAction.enabled}"/>
+ </div>
+
+ <div class="formButtons">
+ <h:commandButton id="save" value="Save"
action="#{userAction.save}" styleClass="formButton"/>
+ <s:button id="cancel" view="/usermanager.xhtml"
value="Cancel" propagation="end"
styleClass="formButton"/>
+ </div>
+
+ <br class="clear"/>
+
+ </h:form>
+
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.page.xml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.page.xml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.page.xml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,14 @@
+<page
xmlns="http://jboss.com/products/seam/pages"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.3.xsd"
+ action="#{userSearch.loadUsers}">
+ <restrict>#{s:hasPermission('seam.user',
'read')}</restrict>
+
+ <navigation from-action="#{userAction.createUser}">
+ <redirect view-id="/userdetail.xhtml"/>
+ </navigation>
+
+ <navigation
from-action="#{userAction.editUser(userSearch.selectedUser)}">
+ <redirect view-id="/userdetail.xhtml"/>
+ </navigation>
+</page>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/usermanager.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,74 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core"
+
xmlns:s="http://jboss.com/products/seam/taglib">
+
+ <ui:composition template="template.xhtml">
+
+ <ui:define name="head">
+ <link href="style/security.css" rel="stylesheet"
type="text/css"/>
+ </ui:define>
+
+ <ui:define name="content">
+
+ <script type="text/javascript">
+ function confirmDelete()
+ {
+ return confirm("Are you sure you wish to delete this user? This action
cannot be undone.");
+ }
+ </script>
+
+ <div id="contentMain">
+
+ <h2>User Manager</h2>
+
+ <s:button id="newUser" action="#{userAction.createUser}"
styleClass="newuser" rendered="#{s:hasPermission('seam.account',
'create')}"/>
+
+ <h:dataTable
+ id="threads"
+ value="#{users}"
+ var="user"
+ styleClass="security"
+ cellspacing="0"
+ headerClass="header"
+ rowClasses="odd,even"
+ columnClasses=",,enabled,action">
+ <h:column width="auto">
+ <f:facet name="header">
+ User name
+ </f:facet>
+ #{user}
+ </h:column>
+ <h:column width="auto">
+ <f:facet name="header">
+ Member Of
+ </f:facet>
+ #{userSearch.getUserRoles(user)}
+ </h:column>
+ <h:column id="enabled" width="auto">
+ <f:facet name="header">
+ Enabled
+ </f:facet>
+ <div class="#{identityManager.isUserEnabled(user) ?
'checkmark' : 'cross'}"/>
+ </h:column>
+ <h:column id="action" width="auto">
+ <f:facet name="header">
+ Action
+ </f:facet>
+
+ <s:fragment rendered="#{s:hasPermission('seam.user',
'update')}">
+ <s:link id="edit" value="Edit"
action="#{userAction.editUser(userSearch.selectedUser)}"/><span> |
</span>
+ </s:fragment>
+ <s:link id="delete" value="Delete"
action="#{identityManager.deleteUser(userSearch.selectedUser)}"
+ rendered="#{s:hasPermission('seam.user',
'delete')}"
+ onclick="return confirmDelete()"/>
+ </h:column>
+ </h:dataTable>
+ </div>
+
+ </ui:define>
+
+ </ui:composition>
+</html>
Added:
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/welcome.xhtml
===================================================================
---
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/welcome.xhtml
(rev 0)
+++
branches/community/Seam_2_3/examples-ee6/seamspace/seamspace-web/src/main/webapp/welcome.xhtml 2012-04-02
07:53:34 UTC (rev 14457)
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
xmlns="http://www.w3.org/1999/xhtml"
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html">
+
+<h:head>
+ <title>SeamSpace</title>
+</h:head>
+
+<body>
+ <h1>Login successful!</h1>
+
+ <div class="errors"><h:messages
globalOnly="true"/></div>
+
+</body>
+</html>
+