├── oauthclient ├── src │ └── play.plugins ├── public │ ├── stylesheets │ │ └── main.css │ ├── images │ │ └── favicon.png │ └── javascripts │ │ └── jquery-1.4.min.js ├── app │ ├── views │ │ ├── Application │ │ │ └── index.html │ │ ├── errors │ │ │ ├── 404.html │ │ │ └── 500.html │ │ └── main.html │ └── play │ │ └── modules │ │ └── oauthclient │ │ ├── ICredentials.java │ │ ├── WSOAuthConsumer.java │ │ └── OAuthClient.java ├── lib │ └── signpost-core-1.2.jar ├── conf │ ├── messages │ └── routes ├── commands.py ├── build.xml └── documentation │ └── manual │ └── home.textile └── example └── twitter ├── public ├── images │ └── favicon.png ├── stylesheets │ └── main.css └── javascripts │ └── jquery-1.4.min.js ├── conf ├── messages ├── routes └── application.conf ├── test ├── data.yml ├── Application.test.html ├── BasicTest.java └── ApplicationTest.java └── app ├── views ├── errors │ ├── 404.html │ └── 500.html └── Application │ └── index.html ├── models ├── User.java └── Credentials.java └── controllers └── Application.java /oauthclient/src/play.plugins: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oauthclient/public/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oauthclient/app/views/Application/index.html: -------------------------------------------------------------------------------- 1 | #{extends 'main.html' /} 2 | #{set title:'Home' /} 3 | 4 | #{welcome /} -------------------------------------------------------------------------------- /oauthclient/lib/signpost-core-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erwan/playoauthclient/HEAD/oauthclient/lib/signpost-core-1.2.jar -------------------------------------------------------------------------------- /oauthclient/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erwan/playoauthclient/HEAD/oauthclient/public/images/favicon.png -------------------------------------------------------------------------------- /example/twitter/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erwan/playoauthclient/HEAD/example/twitter/public/images/favicon.png -------------------------------------------------------------------------------- /oauthclient/conf/messages: -------------------------------------------------------------------------------- 1 | # You can specialize this file for each language. 2 | # For example, for French create a messages.fr file 3 | # 4 | -------------------------------------------------------------------------------- /example/twitter/conf/messages: -------------------------------------------------------------------------------- 1 | # You can specialize this file for each language. 2 | # For example, for French create a messages.fr file 3 | # 4 | -------------------------------------------------------------------------------- /example/twitter/test/data.yml: -------------------------------------------------------------------------------- 1 | # you describe your data using the YAML notation here 2 | # and then load them using Fixtures.load("data.yml") 3 | 4 | # User(bob): 5 | # email: bob@gmail.com 6 | # password: secret 7 | # fullname: Bob -------------------------------------------------------------------------------- /example/twitter/test/Application.test.html: -------------------------------------------------------------------------------- 1 | *{ You can use plain selenium command using the selenium tag }* 2 | 3 | #{selenium} 4 | // Open the home page, and check that no error occured 5 | open('/') 6 | waitForPageToLoad(1000) 7 | assertNotTitle('Application error') 8 | #{/selenium} -------------------------------------------------------------------------------- /example/twitter/test/BasicTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.*; 2 | import java.util.*; 3 | import play.test.*; 4 | import models.*; 5 | 6 | public class BasicTest extends UnitTest { 7 | 8 | @Test 9 | public void aVeryImportantThingToTest() { 10 | assertEquals(2, 1 + 1); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /oauthclient/app/play/modules/oauthclient/ICredentials.java: -------------------------------------------------------------------------------- 1 | package play.modules.oauthclient; 2 | 3 | public interface ICredentials { 4 | 5 | public void setToken(String token); 6 | 7 | public String getToken(); 8 | 9 | public void setSecret(String secret); 10 | 11 | public String getSecret(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /example/twitter/public/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: #1196FC; 3 | font-family: sans-serif; 4 | } 5 | 6 | body { 7 | background-color: #77D9F9; 8 | -moz-border-radius: 20px; 9 | -webkit-border-radius: 20px; 10 | padding: 20px 30px 20px 30px; 11 | } 12 | 13 | h1, h2, h3 { 14 | color: #154E84; 15 | } 16 | -------------------------------------------------------------------------------- /oauthclient/commands.py: -------------------------------------------------------------------------------- 1 | # Here you can create play commands that are specific to the module 2 | 3 | # Example below: 4 | # ~~~~ 5 | if play_command == 'hello': 6 | try: 7 | print "~ Hello" 8 | sys.exit(0) 9 | 10 | except getopt.GetoptError, err: 11 | print "~ %s" % str(err) 12 | print "~ " 13 | sys.exit(-1) 14 | 15 | sys.exit(0) -------------------------------------------------------------------------------- /oauthclient/conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # ~~~~ 4 | 5 | # Home page 6 | GET / Application.index 7 | 8 | # Map static resources from the /app/public folder to the /public path 9 | GET /public/ staticDir:public 10 | 11 | # Catch all 12 | * /{controller}/{action} {controller}.{action} 13 | -------------------------------------------------------------------------------- /example/twitter/test/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.*; 2 | import play.test.*; 3 | import play.mvc.*; 4 | import play.mvc.Http.*; 5 | import models.*; 6 | 7 | public class ApplicationTest extends FunctionalTest { 8 | 9 | @Test 10 | public void testThatIndexPageWorks() { 11 | Response response = GET("/"); 12 | assertIsOk(response); 13 | assertContentType("text/html", response); 14 | assertCharset("utf-8", response); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /example/twitter/conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # ~~~~ 4 | 5 | # Home page 6 | GET / Application.index 7 | GET /auth Application.authenticate 8 | 9 | POST /ws/status Application.setStatus 10 | 11 | # Map static resources from the /app/public folder to the /public path 12 | GET /public/ staticDir:public 13 | 14 | # Catch all 15 | * /{controller}/{action} {controller}.{action} 16 | -------------------------------------------------------------------------------- /oauthclient/app/views/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Not found 5 | 6 | 7 | 8 | #{if play.mode.name() == 'DEV'} 9 | #{404 result /} 10 | #{/if} 11 | #{else} 12 |

Not found

13 |

14 | ${result.message} 15 |

16 | #{/else} 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/twitter/app/views/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Not found 5 | 6 | 7 | 8 | #{if play.mode.name() == 'DEV'} 9 | #{404 result /} 10 | #{/if} 11 | #{else} 12 |

Not found

13 |

14 | ${result.message} 15 |

16 | #{/else} 17 | 18 | 19 | -------------------------------------------------------------------------------- /oauthclient/app/views/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | #{get 'title' /} 6 | 7 | 8 | #{get 'moreStyles' /} 9 | 10 | 11 | #{get 'moreScripts' /} 12 | 13 | 14 | #{doLayout /} 15 | 16 | 17 | -------------------------------------------------------------------------------- /oauthclient/app/views/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Application error 5 | 6 | 7 | 8 | #{if play.mode.name() == 'DEV'} 9 | #{500 exception /} 10 | #{/if} 11 | #{else} 12 |

Oops, an error occured

13 |

14 | This exception has been logged with id ${exception.id}. 15 |

16 | #{/else} 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/twitter/app/views/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Application error 5 | 6 | 7 | 8 | #{if play.mode.name() == 'DEV'} 9 | #{500 exception /} 10 | #{/if} 11 | #{else} 12 |

Oops, an error occured

13 |

14 | This exception has been logged with id ${exception.id}. 15 |

16 | #{/else} 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/twitter/app/models/User.java: -------------------------------------------------------------------------------- 1 | package models; 2 | 3 | import java.util.*; 4 | 5 | import play.*; 6 | import play.db.jpa.*; 7 | 8 | import javax.persistence.*; 9 | 10 | 11 | 12 | @Entity 13 | public class User extends Model { 14 | 15 | public String username; 16 | 17 | public Credentials twitterCreds; 18 | 19 | public User(String username) { 20 | this.username = username; 21 | this.twitterCreds = new Credentials(); 22 | this.twitterCreds.save(); 23 | } 24 | 25 | public static User findOrCreate(String username) { 26 | User user = User.find("username", username).first(); 27 | if (user == null) { 28 | user = new User(username); 29 | } 30 | return user; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /example/twitter/app/models/Credentials.java: -------------------------------------------------------------------------------- 1 | package models; 2 | 3 | import play.*; 4 | import play.db.jpa.*; 5 | import play.modules.oauthclient.ICredentials; 6 | 7 | import javax.persistence.*; 8 | import java.util.*; 9 | 10 | @Entity 11 | public class Credentials extends Model implements ICredentials { 12 | 13 | private String token; 14 | 15 | private String secret; 16 | 17 | public void setToken(String token) { 18 | this.token = token; 19 | save(); 20 | } 21 | 22 | public String getToken() { 23 | return token; 24 | } 25 | 26 | public void setSecret(String secret) { 27 | this.secret = secret; 28 | save(); 29 | } 30 | 31 | public String getSecret() { 32 | return secret; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /example/twitter/app/views/Application/index.html: -------------------------------------------------------------------------------- 1 | #{extends 'main.html' /} 2 | #{set title:'Home' /} 3 | 4 | %{ 5 | doc = mentions.asXml() 6 | }% 7 | 8 |

Useless Twitter Mashup

9 | 10 | Status: 11 | 12 |

Mentions

13 | 14 | 21 | 22 | -------------------------------------------------------------------------------- /oauthclient/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 |
33 |
34 |
35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 | -------------------------------------------------------------------------------- /example/twitter/app/controllers/Application.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import java.net.URLEncoder; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import models.*; 8 | 9 | import play.libs.WS; 10 | import play.libs.WS.HttpResponse; 11 | import play.modules.oauthclient.OAuthClient; 12 | import play.mvc.*; 13 | 14 | public class Application extends Controller { 15 | 16 | public static void index() throws Exception { 17 | String url = "http://twitter.com/statuses/mentions.xml"; 18 | String mentions = play.libs.WS.url(getConnector().sign(getUser().twitterCreds, url)).get().getString(); 19 | render(mentions); 20 | } 21 | 22 | public static void setStatus(String status) throws Exception { 23 | String url = "http://twitter.com/statuses/update.json?status=" + URLEncoder.encode(status, "utf-8"); 24 | String response = getConnector().sign(getUser().twitterCreds, WS.url(url), "POST").post().getString(); 25 | request.current().contentType = "application/json"; 26 | renderText(response); 27 | } 28 | 29 | // Twitter authentication 30 | 31 | public static void authenticate(String callback) throws Exception { 32 | // 1: get the request token 33 | Map args = new HashMap(); 34 | args.put("callback", callback); 35 | String callbackURL = Router.getFullUrl(request.controller + ".oauthCallback", args); 36 | getConnector().authenticate(getUser().twitterCreds, callbackURL); 37 | } 38 | 39 | public static void oauthCallback(String callback, String oauth_token, String oauth_verifier) throws Exception { 40 | // 2: get the access token 41 | getConnector().retrieveAccessToken(getUser().twitterCreds, oauth_verifier); 42 | redirect(callback); 43 | } 44 | 45 | private static OAuthClient connector = null; 46 | private static OAuthClient getConnector() { 47 | if (connector == null) { 48 | connector = new OAuthClient( 49 | "http://twitter.com/oauth/request_token", 50 | "http://twitter.com/oauth/access_token", 51 | "http://twitter.com/oauth/authorize", 52 | "eevIR82fiFK3e6VrGpO9rw", 53 | "OYCQA6fpsLiMVaxqqm1EqDjDWFmdlbkSYYcIbwICrg"); 54 | } 55 | return connector; 56 | } 57 | 58 | // TODO: Make it real? 59 | 60 | private static User getUser() { 61 | return User.findOrCreate("guest"); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /oauthclient/app/play/modules/oauthclient/WSOAuthConsumer.java: -------------------------------------------------------------------------------- 1 | package play.modules.oauthclient; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Map; 6 | 7 | import oauth.signpost.AbstractOAuthConsumer; 8 | import oauth.signpost.exception.OAuthCommunicationException; 9 | import oauth.signpost.exception.OAuthExpectationFailedException; 10 | import oauth.signpost.exception.OAuthMessageSignerException; 11 | import oauth.signpost.http.HttpRequest; 12 | import play.libs.WS.WSRequest; 13 | 14 | public class WSOAuthConsumer extends AbstractOAuthConsumer { 15 | 16 | public WSOAuthConsumer(String consumerKey, String consumerSecret) { 17 | super(consumerKey, consumerSecret); 18 | } 19 | 20 | @Override 21 | protected HttpRequest wrap(Object request) { 22 | if (!(request instanceof WSRequest)) { 23 | throw new IllegalArgumentException("WSOAuthConsumer expects requests of type play.libs.WS.WSRequest"); 24 | } 25 | return new WSRequestAdapter((WSRequest)request); 26 | } 27 | 28 | public WSRequest sign(WSRequest request, String method) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException { 29 | WSRequestAdapter req = (WSRequestAdapter)wrap(request); 30 | req.setMethod(method); 31 | sign(req); 32 | return request; 33 | } 34 | 35 | public class WSRequestAdapter implements HttpRequest { 36 | 37 | private WSRequest request; 38 | 39 | public WSRequestAdapter(WSRequest request) { 40 | this.request = request; 41 | } 42 | 43 | public Map getAllHeaders() { 44 | return request.headers; 45 | } 46 | 47 | public String getContentType() { 48 | return request.mimeType; 49 | } 50 | 51 | public String getHeader(String name) { 52 | return request.headers.get(name); 53 | } 54 | 55 | public InputStream getMessagePayload() throws IOException { 56 | return null; 57 | } 58 | 59 | private String method = "GET"; 60 | 61 | public String getMethod() { 62 | return this.method; 63 | } 64 | 65 | private void setMethod(String method) { 66 | this.method = method; 67 | } 68 | 69 | public String getRequestUrl() { 70 | return request.url; 71 | } 72 | 73 | public void setHeader(String name, String value) { 74 | request.setHeader(name, value); 75 | } 76 | 77 | public void setRequestUrl(String url) { 78 | request.url = url; 79 | } 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /oauthclient/documentation/manual/home.textile: -------------------------------------------------------------------------------- 1 | h1. OAuth Client 2 | 3 | This module allows applications to connect to an "oauth":http://oauth.net provider, such as "Twitter":http://apiwiki.twitter.com/ or "Google":http://code.google.com/apis/accounts/docs/AuthForWebApps.html . 4 | 5 | h2. OAuth Basics 6 | 7 | In order to access to users' data from a oauth provider, you need to register and obtain a consumer key. See the documentation on your provider's website for detailed on how to obtain it. 8 | 9 | You need to following: 10 | * Request URL 11 | * Access URL 12 | * Authorize URL 13 | * Consumer key 14 | * Consumer secret 15 | 16 | The workflow is the following, for each user: 17 | # Get a request token from the provider. The user must be redirected to a page on the provider's site where he explicitly grants access rights to your application. 18 | # Exchange the request token for an access token. 19 | # Use the token to sign requests to access the user's data with REST request on the provider. 20 | 21 | Depending on the provider's policy the token may expire at any time. The user can also revoke the permission to your application. 22 | 23 | h2. Using The Module 24 | 25 | The main class to use is play.modules.oauthclient.OAuthClient. It is used to retrieve request and access token, and sign requests. 26 | 27 | You need to store each user's token in your data layer. To do so you must provide a ICredentials for each user; you can use the Credentials implementation which inherits model and as such will be serialized to your data layer. 28 | 29 | h2. The OAuthClient Class 30 | 31 | Here is how you would create a client to connect to Twitter's API: 32 | 33 | bc. OAuthClient client = new OAuthClient( 34 | "http://twitter.com/oauth/request_token", 35 | "http://twitter.com/oauth/access_token", 36 | "http://twitter.com/oauth/authorize", 37 | "aaaaaaaaaaaaaaaaaaaaaa", // Your application's consumer key 38 | "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); // You application's consumer secret 39 | 40 | h2. Authentication 41 | 42 | First, you need a request token: 43 | 44 | bc. ICredentials creds = new Credentials(); 45 | client.authenticate(creds, callbackURL); 46 | 47 | Calling this method will redirect the user to a page on the provider where he is asked to grant your application permission to access his data. After that, the provider will redirect him to the URL you provided in callbackURL with oauth_token and oauth_verifier as arguments. You will need the oauth_verifier to get your access token. The token and secret will be set in creds. If you use your own implementation of ICredentials, make sure that they get saved in the setters. 48 | 49 | Then, you need to exchange this request token for an access token: 50 | 51 | bc. client.retrieveAccessToken(creds, oauth_verifier); 52 | 53 | creds should contain the tokens set by OAuthClient.authenticate. oauth_verifier comes from the callback in the previous step. 54 | 55 | When this is done, creds contain everything you need to sign request and retrieve data related to the user who performed the workflow. 56 | 57 | h2. Signing Requests 58 | 59 | With the correct ICredentials, you can sign any request; this is not limited to the current session. Requests are done using play.libs.WS: 60 | 61 | While a classical, non signed request would be the following: 62 | 63 | bc. WS.url(url).get(); 64 | 65 | A signed request will be: 66 | 67 | bc. WS.url(client.sign(creds, url)).get(); 68 | 69 | If the request is not a GET, you need to sign the request instead of the URL and pass the method: 70 | 71 | bc. client.sign(creds, WS.url(url), "POST").post(); 72 | 73 | h2. Example 74 | 75 | A simple "twitter example":http://github.com/erwan/playoauthclient/tree/master/example/twitter/ is available. 76 | -------------------------------------------------------------------------------- /oauthclient/app/play/modules/oauthclient/OAuthClient.java: -------------------------------------------------------------------------------- 1 | package play.modules.oauthclient; 2 | 3 | import oauth.signpost.OAuthProvider; 4 | import oauth.signpost.basic.DefaultOAuthProvider; 5 | import play.Logger; 6 | import play.libs.WS.WSRequest; 7 | import play.mvc.results.Redirect; 8 | 9 | public class OAuthClient { 10 | 11 | private String requestURL; 12 | private String accessURL; 13 | private String authorizeURL; 14 | private String consumerKey; 15 | private String consumerSecret; 16 | 17 | private WSOAuthConsumer consumer; 18 | private OAuthProvider provider; 19 | 20 | public OAuthClient(String requestURL, String accessURL, String authorizeURL, String consumerKey, String consumerSecret) { 21 | this.requestURL = requestURL; 22 | this.accessURL = accessURL; 23 | this.authorizeURL = authorizeURL; 24 | this.consumerKey = consumerKey; 25 | this.consumerSecret = consumerSecret; 26 | } 27 | 28 | public WSOAuthConsumer getConsumer(ICredentials cred) { 29 | if (consumer == null) { 30 | consumer = new WSOAuthConsumer( 31 | consumerKey, 32 | consumerSecret); 33 | consumer.setTokenWithSecret(cred.getToken(), cred.getSecret()); 34 | } 35 | return consumer; 36 | } 37 | 38 | public OAuthProvider getProvider() { 39 | if (provider == null) { 40 | provider = new DefaultOAuthProvider( 41 | requestURL, 42 | accessURL, 43 | authorizeURL); 44 | provider.setOAuth10a(true); 45 | } 46 | return provider; 47 | } 48 | 49 | // Authentication 50 | 51 | public void authenticate(ICredentials cred, String callbackURL) throws Exception { 52 | throw new Redirect(retrieveRequestToken(cred, callbackURL)); 53 | } 54 | 55 | /** 56 | * Retrieve the request token, and store it in user. 57 | * to in order to get the token. 58 | * @param cred the ICredentials where the oauth token and oauth secret will be set. 59 | * @param callbackURL: the URL the user should be redirected after he grants the rights to our app 60 | * @return the URL on the provider's site that we should redirect the user 61 | */ 62 | public String retrieveRequestToken(ICredentials cred, String callbackURL) throws Exception { 63 | Logger.info("Consumer key: " + getConsumer(cred).getConsumerKey()); 64 | Logger.info("Consumer secret: " + getConsumer(cred).getConsumerSecret()); 65 | Logger.info("Token before request: " + getConsumer(cred).getToken()); 66 | String authUrl = getProvider().retrieveRequestToken(getConsumer(cred), callbackURL); 67 | Logger.info("Token after request: " + getConsumer(cred).getToken()); 68 | cred.setToken(consumer.getToken()); 69 | cred.setSecret(consumer.getTokenSecret()); 70 | return authUrl; 71 | } 72 | 73 | /** 74 | * Retrieve the access token, and store it in user. 75 | * to in order to get the token. 76 | * @param user the ICredentials with the request token and secret already set (using retrieveRequestToken). 77 | * The access token and secret will be set these. 78 | * @return the URL on the provider's site that we should redirect the user 79 | * @see retrieveRequestToken 80 | */ 81 | public void retrieveAccessToken(ICredentials user, String verifier) throws Exception { 82 | Logger.info("Token before retrieve: " + getConsumer(user).getToken()); 83 | Logger.info("Verifier: " + verifier); 84 | getProvider().retrieveAccessToken(getConsumer(user), verifier); 85 | user.setToken(consumer.getToken()); 86 | user.setSecret(consumer.getTokenSecret()); 87 | } 88 | 89 | // Signing requests 90 | 91 | /** 92 | * Sign the url with the OAuth tokens for the user. This method can only be used for GET requests. 93 | * @param url 94 | * @return 95 | * @throws OAuthMessageSignerException 96 | * @throws OAuthExpectationFailedException 97 | * @throws OAuthCommunicationException 98 | */ 99 | public String sign(ICredentials user, String url) throws Exception { 100 | return getConsumer(user).sign(url); 101 | } 102 | 103 | public WSRequest sign(ICredentials user, WSRequest request, String method) throws Exception { 104 | return getConsumer(user).sign(request, method); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /example/twitter/conf/application.conf: -------------------------------------------------------------------------------- 1 | # This is the main configuration file for the application. 2 | # ~~~~~ 3 | application.name=Twitter 4 | 5 | # Application mode 6 | # ~~~~~ 7 | # Set to dev to enable instant reloading and other development help. 8 | # Otherwise set to prod. 9 | application.mode=dev 10 | 11 | # Secret key 12 | # ~~~~~ 13 | # The secret key is used to secure cryptographics functions 14 | # If you deploy your application to several instances be sure to use the same key ! 15 | application.secret=e227tafmfs0xrexah43hm34kkrcetav48nwk9x037wp87jkrp06m7n8wc8m7gbag 16 | 17 | # Additional modules 18 | # ~~~~~ 19 | # A module is another play! application. Add a line for each module you want 20 | # to add to your application. Modules path are either absolutes or relative to 21 | # the application root. 22 | # 23 | #module.crud=${play.path}/modules/crud 24 | #module.secure=${play.path}/modules/secure 25 | #module.ecss=${play.path}/modules/ecss 26 | #module.gae=${play.path}/modules/gae 27 | #module.gwt=${play.path}/modules/gwt 28 | #module.search=${play.path}/modules/search 29 | #module.siena=${play.path}/modules/siena 30 | #module.spring=${play.path}/modules/spring 31 | module.oauthclient=/home/erwan/Devel/Play/oauthclient/oauthclient 32 | 33 | # i18n 34 | # ~~~~~ 35 | # Define locales used by your application. 36 | # You can then place localized messages in conf/messages.{locale} files 37 | # application.langs=fr,en,ja 38 | 39 | # Server configuration 40 | # ~~~~~ 41 | # If you need to change the HTTP port, uncomment this (default is set to 9000) 42 | # http.port=9000 43 | # 44 | # By default the server listen for HTTP on the wilcard address. 45 | # You can restrict this. 46 | # http.address=127.0.0.1 47 | 48 | # Session configuration 49 | # ~~~~~~~~~~~~~~~~~~~~~~ 50 | # By default, session will be written to the transient PLAY_SESSION cookie. 51 | # application.session.cookie=PLAY 52 | # application.session.maxAge=1h 53 | 54 | # JVM configuration 55 | # ~~~~~ 56 | # Define which port is used by JPDA when application is in debug mode (default is set to 8000) 57 | # jpda.port=8000 58 | # 59 | # Java source level => 1.5, 1.6 or 1.7 (experimental) 60 | # java.source=1.5 61 | 62 | # Log level 63 | # ~~~~~ 64 | # Specify log level for your application. 65 | # If you want a very customized log, create a log4j.properties file in the conf directory 66 | # application.log=INFO 67 | # 68 | # More logging configuration 69 | # application.log.path=/log4j.properties 70 | # application.log.system.out=off 71 | 72 | # Database configuration 73 | # ~~~~~ 74 | # Enable a database engine if needed. 75 | # 76 | # To quickly set up a development database, use either: 77 | # - mem : for a transient in memory database (HSQL in memory) 78 | # - fs : for a simple file written database (HSQL file stored) 79 | db=mem 80 | # 81 | # To connect to a local MySQL5 database, use: 82 | # db=mysql:user:pwd@database_name 83 | # 84 | # If you need a full JDBC configuration use the following : 85 | # db.url=jdbc:postgresql:database_name 86 | # db.driver=org.postgresql.Driver 87 | # db.user=root 88 | # db.pass=secret 89 | # 90 | # Connections pool configuration : 91 | # db.pool.timeout=1000 92 | # db.pool.maxSize=30 93 | # db.pool.minSize=10 94 | # 95 | # If you want to reuse an existing Datasource from your application server, use: 96 | # db=java:/comp/env/jdbc/myDatasource 97 | 98 | # JPA Configuration (Hibernate) 99 | # ~~~~~ 100 | # 101 | # Specify the custom JPA dialect to use here (default to guess): 102 | # jpa.dialect=org.hibernate.dialect.PostgreSQLDialect 103 | # 104 | # Specify the ddl generation pattern to use (default to update, set to none to disable it): 105 | # jpa.ddl=update 106 | # 107 | # Debug SQL statements (logged using DEBUG level): 108 | # jpa.debugSQL=true 109 | # 110 | # You can even specify additional hibernate properties here: 111 | # hibernate.use_sql_comments=true 112 | # ... 113 | 114 | # Memcached configuration 115 | # ~~~~~ 116 | # Enable memcached if needed. Otherwise a local cache is used. 117 | # memcached=enabled 118 | # 119 | # Specify memcached host (default to 127.0.0.1:11211) 120 | # memcached.host=127.0.0.1:11211 121 | # 122 | # Or you can specify multiple host to build a distributed cache 123 | # memcached.1.host=127.0.0.1:11211 124 | # memcached.2.host=127.0.0.1:11212 125 | 126 | # HTTP Response headers control for static files 127 | # ~~~~~ 128 | # Set the default max-age, telling the user's browser how long it should cache the page. 129 | # Default is 3600 (one hour). Set it to 0 to send no-cache. 130 | # This is only read in prod mode, in dev mode the cache is disabled. 131 | http.cacheControl=3600 132 | 133 | # If enabled, Play will generate entity tags automatically and send a 304 when needed. 134 | # Default is true, set it to false to deactivate use of entity tags. 135 | http.useETag=true 136 | 137 | # WS configuration 138 | # ~~~~~ 139 | # If you need to set proxy params for WS requests 140 | # http.proxyHost = localhost 141 | # http.proxyPort = 3128 142 | # http.proxyUser = jojo 143 | # http.proxyPassword = jojo 144 | 145 | # Mail configuration 146 | # ~~~~~ 147 | # Default is to use a mock Mailer 148 | mail.smtp=mock 149 | 150 | # Or, specify mail host configuration 151 | # mail.smtp.host=127.0.0.1 152 | # mail.smtp.user=admin 153 | # mail.smtp.pass= 154 | # mail.smtp.channel=ssl 155 | 156 | # Execution pool 157 | # ~~~~~ 158 | # Default to 1 thread in DEV mode or (nb processors + 1) threads in PROD mode. 159 | # Try to keep a low as possible. 1 thread will serialize all requests (very useful for debugging purpose) 160 | # play.pool=3 161 | 162 | # Open file from errors pages 163 | # ~~~~~ 164 | # If your text editor supports to open files using URL, Play! will link 165 | # error pages to files dynamically 166 | # 167 | # Example, for textmate: 168 | # play.editor=txmt://open?url=file://%s&line=%s 169 | 170 | # Testing. Set up a custom configuration for test mode 171 | # ~~~~~ 172 | #%test.module.cobertura=${play.path}/modules/cobertura 173 | %test.application.mode=dev 174 | %test.db=mem 175 | %test.jpa.ddl=create-drop 176 | %test.mail.smtp=mock 177 | 178 | # These features will be automatically enabled in the 1.1 release 179 | # For now you can enable them if you want 180 | # ~~~~~ 181 | future.bindJPAObjects=true 182 | future.escapeInTemplates=true 183 | -------------------------------------------------------------------------------- /example/twitter/public/javascripts/jquery-1.4.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery JavaScript Library v1.4 3 | * http://jquery.com/ 4 | * 5 | * Copyright 2010, John Resig 6 | * Dual licensed under the MIT or GPL Version 2 licenses. 7 | * http://docs.jquery.com/License 8 | * 9 | * Includes Sizzle.js 10 | * http://sizzlejs.com/ 11 | * Copyright 2010, The Dojo Foundation 12 | * Released under the MIT, BSD, and GPL Licenses. 13 | * 14 | * Date: Wed Jan 13 15:23:05 2010 -0500 15 | */ 16 | (function(A,w){function oa(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(oa,1);return}c.ready()}}function La(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function $(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var o in b)$(a,o,b[o],f,e,d);return a}if(d!==w){f=!i&&f&&c.isFunction(d);for(o=0;o-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete t[p]}i=c(a.target).closest(f,a.currentTarget); 18 | n=0;for(l=i.length;n)[^>]*$|^#([\w-]+)$/,Pa=/^.[^:#\[\.,]*$/,Qa=/\S/, 21 | Ra=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Sa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],M,ca=Object.prototype.toString,da=Object.prototype.hasOwnProperty,ea=Array.prototype.push,R=Array.prototype.slice,V=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Oa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Sa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])]; 22 | c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ua([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return U.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a)}else return!b||b.jquery?(b||U).find(a):c(b).find(a);else if(c.isFunction(a))return U.ready(a);if(a.selector!==w){this.selector=a.selector; 23 | this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,this)},selector:"",jquery:"1.4",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length= 24 | 0;ea.apply(this,a);return this},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject|| 25 | c(null)},push:ea,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length, 34 | htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b, 35 | a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function o(){c.support.noCloneEvent=false;d.detachEvent("onclick",o)});d.cloneNode(true).fireEvent("onclick")}c(function(){var o=s.createElement("div");o.style.width=o.style.paddingLeft="1px";s.body.appendChild(o);c.boxModel=c.support.boxModel=o.offsetWidth===2;s.body.removeChild(o).style.display="none"});a=function(o){var p=s.createElement("div");o="on"+o;var n=o in 36 | p;if(!n){p.setAttribute(o,"return;");n=typeof p[o]==="function"}return n};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var H="jQuery"+K(),Ta=0,ya={},Ua={};c.extend({cache:{},expando:H,noData:{embed:true,object:true,applet:true},data:function(a, 37 | b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var f=a[H],e=c.cache;if(!b&&!f)return null;f||(f=++Ta);if(typeof b==="object"){a[H]=f;e=e[f]=c.extend(true,{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Ua:(e[f]={});if(d!==w){a[H]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var d=a[H],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[H]}catch(i){a.removeAttribute&& 38 | a.removeAttribute(H)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this, 39 | a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this, 40 | a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var za=/[\n\t]/g,fa=/\s+/,Va=/\r/g,Wa=/href|src|style/,Xa=/(button|input)/i,Ya=/(button|input|object|select|textarea)/i,Za=/^(a|area)$/i,Aa=/radio|checkbox/;c.fn.extend({attr:function(a, 41 | b){return $(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.addClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(fa),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i=0;else if(c.nodeName(this,"select")){var z=c.makeArray(t);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),z)>=0});if(!z.length)this.selectedIndex= 46 | -1}else this.value=t}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Wa.test(b);if(b in a&&f&&!i){if(e){if(b==="type"&&Xa.test(a.nodeName)&&a.parentNode)throw"type property can't be changed";a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue; 47 | if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Ya.test(a.nodeName)||Za.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var $a=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType=== 48 | 3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;if(!d.guid)d.guid=c.guid++;if(f!==w){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):w};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var o,p=0;o=b[p++];){var n=o.split(".");o=n.shift();d.type=n.slice(0).sort().join(".");var t=e[o],z=this.special[o]||{};if(!t){t=e[o]={}; 49 | if(!z.setup||z.setup.call(a,f,n,d)===false)if(a.addEventListener)a.addEventListener(o,i,false);else a.attachEvent&&a.attachEvent("on"+o,i)}if(z.add)if((n=z.add.call(a,d,f,n,t))&&c.isFunction(n)){n.guid=n.guid||d.guid;d=n}t[d.guid]=d;this.global[o]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===w||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/); 50 | for(var o=0;i=b[o++];){var p=i.split(".");i=p.shift();var n=!p.length,t=c.map(p.slice(0).sort(),$a);t=new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.)?")+"(\\.|$)");var z=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var B in f[i])if(n||t.test(f[i][B].type))delete f[i][B];z.remove&&z.remove.call(a,p,j);for(e in f[i])break;if(!e){if(!z.teardown||z.teardown.call(a,p)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+ 51 | i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(B=c.data(a,"handle"))B.elem=null;c.removeData(a,"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[H]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== 52 | 8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;var i=c.data(d,"handle");i&&i.apply(d,b);var j,o;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){j=d[e];o=d["on"+e]}}catch(p){}i=c.nodeName(d,"a")&&e==="click";if(!f&&j&&!a.isDefaultPrevented()&&!i){this.triggered=true;try{d[e]()}catch(n){}}else if(o&&d["on"+e].apply(d,b)===false)a.result=false;this.triggered=false;if(!a.isPropagationStopped())(d=d.parentNode||d.ownerDocument)&&c.event.trigger(a,b,d,true)}, 53 | handle:function(a){var b,d;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result}, 54 | props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[H])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement|| 55 | s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&& 56 | a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;c.event.add(this,b.live,qa,b)},remove:function(a){if(a.length){var b=0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],qa)}},special:{}},beforeunload:{setup:function(a, 57 | b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=K();this[H]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ba;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped= 58 | ba;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ba;this.stopPropagation()},isDefaultPrevented:aa,isPropagationStopped:aa,isImmediatePropagationStopped:aa};var Ba=function(a){for(var b=a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ca=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover", 59 | mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ca:Ba,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ca:Ba)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return pa("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+ 60 | d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return pa("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var ga=/textarea|input|select/i;function Da(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex> 61 | -1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ha(a,b){var d=a.target,f,e;if(!(!ga.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Da(d);if(e!==f){if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",e);if(d.type!=="select"&&(f!=null||e)){a.type="change";return c.event.trigger(a,b,this)}}}}c.event.special.change={filters:{focusout:ha,click:function(a){var b=a.target,d=b.type;if(d=== 62 | "radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ha.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ha.call(this,a)},beforeactivate:function(a){a=a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Da(a))}},setup:function(a,b,d){for(var f in W)c.event.add(this,f+".specialChange."+d.guid,W[f]);return ga.test(this.nodeName)}, 63 | remove:function(a,b){for(var d in W)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),W[d]);return ga.test(this.nodeName)}};var W=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d, 64 | f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){thisObject=e;e=f;f=w}var j=b==="one"?c.proxy(e,function(o){c(this).unbind(o,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e,thisObject):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a, 65 | b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d0){y=u;break}}u=u[g]}m[r]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 69 | e=0,i=Object.prototype.toString,j=false,o=true;[0,0].sort(function(){o=false;return 0});var p=function(g,h,k,m){k=k||[];var r=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return k;for(var q=[],v,u,y,S,I=true,N=x(h),J=g;(f.exec(""),v=f.exec(J))!==null;){J=v[3];q.push(v[1]);if(v[2]){S=v[3];break}}if(q.length>1&&t.exec(g))if(q.length===2&&n.relative[q[0]])u=ia(q[0]+q[1],h);else for(u=n.relative[q[0]]?[h]:p(q.shift(),h);q.length;){g=q.shift();if(n.relative[g])g+=q.shift(); 70 | u=ia(g,u)}else{if(!m&&q.length>1&&h.nodeType===9&&!N&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){v=p.find(q.shift(),h,N);h=v.expr?p.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:q.pop(),set:B(m)}:p.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&h.parentNode?h.parentNode:h,N);u=v.expr?p.filter(v.expr,v.set):v.set;if(q.length>0)y=B(u);else I=false;for(;q.length;){var E=q.pop();v=E;if(n.relative[E])v=q.pop();else E="";if(v==null)v=h;n.relative[E](y,v,N)}}else y=[]}y||(y=u);if(!y)throw"Syntax error, unrecognized expression: "+ 71 | (E||g);if(i.call(y)==="[object Array]")if(I)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&F(h,y[g])))k.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&k.push(u[g]);else k.push.apply(k,y);else B(y,k);if(S){p(S,r,k,m);p.uniqueSort(k)}return k};p.uniqueSort=function(g){if(D){j=o;g.sort(D);if(j)for(var h=1;h":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,r=g.length;m=0))k||m.push(v);else if(k)h[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, 78 | CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,m,r,q){h=g[1].replace(/\\/g,"");if(!q&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,m,r){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=p(g[3],null,null,h);else{g=p.filter(g[3],h,k,true^r);k||m.push.apply(m, 79 | g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!p(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, 80 | text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, 81 | setFilters:{first:function(g,h){return h===0},last:function(g,h,k,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return hk[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,m){var r=h[1],q=n.filters[r];if(q)return q(g,k,h,m);else if(r==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(r==="not"){h= 82 | h[3];k=0;for(m=h.length;k=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=n.attrHandle[k]?n.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== 84 | "="?k===h:m==="*="?k.indexOf(h)>=0:m==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:m==="!="?k!==h:m==="^="?k.indexOf(h)===0:m==="$="?k.substr(k.length-h.length)===h:m==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,m){var r=n.setFilters[h[2]];if(r)return r(g,k,h,m)}}},t=n.match.POS;for(var z in n.match){n.match[z]=new RegExp(n.match[z].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[z]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[z].source.replace(/\\(\d+)/g,function(g, 85 | h){return"\\"+(h-0+1)}))}var B=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){B=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,m=g.length;k";var k=s.documentElement;k.insertBefore(g,k.firstChild);if(s.getElementById(h)){n.find.ID=function(m,r,q){if(typeof r.getElementById!=="undefined"&&!q)return(r=r.getElementById(m[1]))?r.id===m[1]||typeof r.getAttributeNode!=="undefined"&& 88 | r.getAttributeNode("id").nodeValue===m[1]?[r]:w:[]};n.filter.ID=function(m,r){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===r}}k.removeChild(g);k=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;k[m];m++)k[m].nodeType===1&&h.push(k[m]);k=h}return k};g.innerHTML=""; 89 | if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=p,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){p=function(m,r,q,v){r=r||s;if(!v&&r.nodeType===9&&!x(r))try{return B(r.querySelectorAll(m),q)}catch(u){}return g(m,r,q,v)};for(var k in g)p[k]=g[k];h=null}}(); 90 | (function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,k,m){if(typeof k.getElementsByClassName!=="undefined"&&!m)return k.getElementsByClassName(h[1])};g=null}}})();var F=s.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g, 91 | h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ia=function(g,h){var k=[],m="",r;for(h=h.nodeType?[h]:h;r=n.match.PSEUDO.exec(g);){m+=r[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;r=0;for(var q=h.length;r=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var i=d;i0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i= 94 | {},j;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var p=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,t){for(;t&&t.ownerDocument&&t!==b;){if(p?p.index(t)>-1:c(t).is(a))return t;t=t.parentNode}return null})},index:function(a){if(!a||typeof a=== 95 | "string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(sa(a[0])||sa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", 96 | d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? 97 | a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);ab.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||cb.test(f))&&bb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||!c(a).is(d));){a.nodeType=== 98 | 1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ga=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,db=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/"},G={option:[1,""], 99 | legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};G.optgroup=G.option;G.tbody=G.tfoot=G.colgroup=G.caption=G.thead;G.th=G.td;if(!c.support.htmlSerialize)G._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this); 100 | return d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.getText(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, 101 | wrapInner:function(a){return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&& 102 | this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this, 103 | "after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ga,"").replace(Y,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ta(this,b);ta(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType=== 104 | 1?this[0].innerHTML.replace(Ga,""):null;else if(typeof a==="string"&&!/