diff --git a/README.md b/README.md index 2e277b7..6d9f9bc 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,43 @@ # Rainloop for YunoHost -* [rainloop](http://rainloop.net/ ) +* [rainloop](http://rainloop.net/ ): 1.10.5.192 ## English Rainloop is a lightweight webmail. -To configure it, go to http://DOMAIN.TLD/rainloop/?admin +To configure it, go to http://DOMAIN.TLD/rainloop/app/?admin - The default login is : admin -- The default password is : 12345 +- The default password is : Password chosen during install +- If you lost the admin password, you can retrieve it using ``sudo yunohost app settings rainloop password`` -To configure your instance, go to the admin panel, then "Domains" and add a domain in accord with your mail server setup. - -To access the database (required for contacts), the paramaters are the following : -- Database name : rainloop -- Password : the_database_password_indicated_at_installation - -Once this is done in the admin interface, each user can add a remote carddav server from their own parameters interface. -If you use baikal, the CardDav address is : -https://DOMAIN.TLD/baikal/card.php/addressbooks/USER/default/ - -- to upgrade the app once a new rainloop version is available, simply run in a local shell via ssh or otherwise : +Each user can add a remote carddav server from their own parameters interface. -``sudo yunohost app upgrade -u https://github.com/polytan02/rainloop_ynh rainloop`` +- If you use baikal, the CardDav address is: https://DOMAIN.TLD/baikal/card.php/addressbooks/USER/default/ +- If you use NextCloud, the CardDav address is: https://DOMAIN.TLD/nextcloud/remote.php/carddav/addressbooks/USER/contacts + +Rainloop saves your PGP private keys in the browser storage. This means that you will loose your private keys if you clear your browser storage (e.g., private browsing, different computer...). This packages integrates [PGPback by chtixof](https://github.com/chtixof/pgpback_ynh) so you can store your PGP private keys on the server securely. Go to **http://DOMAIN.TLD/rainloop/pgpback** to backup your PGP keys on the server or restore them. + +To upgrade the app once a new rainloop version is available, simply run in a local shell via ssh or otherwise : +``sudo yunohost app upgrade -u https://github.com/YunoHost-Apps/rainloop_ynh rainloop`` ## Français Rainloop est un webmail simple et léger. -Pour le configurer après l'installation, veuillez vous rendre sur http://DOMAIN.TLD/rainloop/?admin +Pour le configurer après l'installation, veuillez vous rendre sur http://DOMAIN.TLD/rainloop/app/?admin -- Le nom d'utilisateur admin par défaut est : admin -- Le mot de passe admin par défaut est : 12345 +- Le nom d'utilisateur admin par défaut est : admin +- Le mot de passe admin par défaut est : Mot de passe choisi lors de l'installation +- Si vous avez oublié votre mot de passe, vous pouvez le retrouver avec ``sudo yunohost app settings rainloop password`` -Pour configurer votre instance, connectez-vous en admin, puis allez dans "Domains" et ajoutez votre domaine en accord avec la configuration de votre serveur email. +Chaque utilisateur peut ajouter un carnet d'adresse distant CardDav via leur propre paramètres. -Pour accéder à la base de donnée (necessaire pour gérer les contacts), les paramètres sont les suivants : -- Nom de la base de donnée : rainloop -- Mot de passe : Le_mot_de_passe_de_la_base_de_donnée_renseigné_lors_de_l'installation - -Une fois ceci fait depuis l'interface d'administration, chaque utilisateur peut ajouter un carnet d'adresse distant CardDav via leur propre paramètres. -Si vous utilisez Baikal, l'adresse à renseigner est du type : -https://DOMAIN.TLD/baikal/card.php/addressbooks/UTILISATEUR/default/ +- Si vous utilisez Baikal, l'adresse à renseigner est du type : https://DOMAIN.TLD/baikal/card.php/addressbooks/UTILISATEUR/default/ +- Si vous utilisez NextCloud, l'adresse à renseigner est du type : https://DOMAIN.TLD/nextcloud/remote.php/carddav/addressbooks/USER/contacts +Rainloop stocke les clés PGP privées dans le stockage de navigateur. Cela implique que vos clés seront perdues quand vous videz le stockage de navigateur (navigation incognito, changement d'ordinateur, ...). Ce paquet intègre [PGPback de chtixof](https://github.com/chtixof/pgpback_ynh) pour que vous puissiez stocker vos clés privées PGP de manière sécurisée sur le serveur. Rendez-vous **http://DOMAIN.TLD/rainloop/pgpback** pour stocker vos clés privées PGP sur le serveur ou les restaurer dans un nouveau navigateur. -- pour mettre à jour rainloop lorsqu'une nouvelle version est disponible, lancez en console locale (ssh ou autre) : - -``sudo yunohost app upgrade -u https://github.com/polytan02/rainloop_ynh rainloop`` +Pour mettre à jour rainloop lorsqu'une nouvelle version est disponible, lancez en console locale (ssh ou autre) : +``sudo yunohost app upgrade -u https://github.com/YunoHost-Apps/rainloop_ynh rainloop`` diff --git a/check_process b/check_process new file mode 100644 index 0000000..afbfc25 --- /dev/null +++ b/check_process @@ -0,0 +1,52 @@ +;; Test Rainloop LDAP suggestions + auto_remove=1 + ; Manifest + domain="domain.tld" (DOMAIN) + path="/rainloop" (PATH) + is_public="No" (PUBLIC|public=Yes|private=No) + password="password" (PASSWORD) + ldap="Yes" + lang="English" + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=1 + setup_nourl=0 + setup_private=1 + setup_public=1 + upgrade=1 + backup_restore=1 + multi_instance=0 + wrong_user=0 + wrong_path=1 + incorrect_path=1 + corrupt_source=0 + fail_download_source=0 + port_already_use=0 + final_path_already_use=0 +;; Test Rainloop no LDAP suggestions + auto_remove=1 + ; Manifest + domain="domain.tld" (DOMAIN) + path="/rainloop" (PATH) + is_public="No" (PUBLIC|public=Yes|private=No) + password="password" (PASSWORD) + ldap="No" + lang="English" + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=1 + setup_nourl=0 + setup_private=1 + setup_public=1 + upgrade=1 + backup_restore=1 + multi_instance=0 + wrong_user=0 + wrong_path=1 + incorrect_path=1 + corrupt_source=0 + fail_download_source=0 + port_already_use=0 + final_path_already_use=0 diff --git a/conf/config.php b/conf/config.php new file mode 100644 index 0000000..a3b1f53 --- /dev/null +++ b/conf/config.php @@ -0,0 +1,27 @@ +SetPassword($args['password']); +echo $oConfig->Save() ? 'Admin password updated' : 'Admin password not updated'; + +?> \ No newline at end of file diff --git a/conf/data/configs/application.ini b/conf/data/configs/application.ini new file mode 100644 index 0000000..0dfec1b --- /dev/null +++ b/conf/data/configs/application.ini @@ -0,0 +1,329 @@ +; RainLoop Webmail configuration file +; Please don't add custom parameters here, those will be overwritten + +[webmail] +; Text displayed as page title +title = "RainLoop Webmail" + +; Text displayed on startup +loading_description = "RainLoop" +favicon_url = "" + +; Theme used by default +theme = "Default" + +; Allow theme selection on settings screen +allow_themes = On +allow_user_background = Off + +; Language used by default +language = "LANGTOCHANGE" + +; Admin Panel interface language +language_admin = "LANGTOCHANGE" + +; Allow language selection on settings screen +allow_languages_on_settings = On +allow_additional_accounts = On +allow_additional_identities = On + +; Number of messages displayed on page by default +messages_per_page = 20 + +; File size limit (MB) for file upload on compose screen +; 0 for unlimited. +attachment_size_limit = 25 + +[interface] +show_attachment_thumbnail = On + +[branding] +login_logo = "" +login_background = "" +login_desc = "" +login_css = "" +login_powered = On +user_css = "" +user_logo = "" +user_logo_title = "" +user_logo_message = "" +user_iframe_message = "" +welcome_page_url = "" +welcome_page_display = "none" + +[contacts] +; Enable contacts +enable = On +allow_sharing = On +allow_sync = On +sync_interval = 20 +type = "mysql" +pdo_dsn = "mysql:host=127.0.0.1;port=3306;dbname=rainloop" +pdo_user = "MYSQLUSER" +pdo_password = "MYSQLPASSWORD" +suggestions_limit = 30 + +[security] +; Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery) +csrf_protection = On +custom_server_signature = "RainLoop" +x_frame_options_header = "" +openpgp = On +use_rsa_encryption = Off + +; Login and password for web admin panel +admin_login = "admin" +admin_password = "12345" + +; Access settings +allow_admin_panel = On +allow_two_factor_auth = Off +force_two_factor_auth = Off +allow_universal_login = Off +admin_panel_host = "" +core_install_access_domain = "" + +[ssl] +; Require verification of SSL certificate used. +verify_certificate = Off + +; Allow self-signed certificates. Requires verify_certificate. +allow_self_signed = On + +; Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt) +cafile = "" + +; capath must be a correctly hashed certificate directory. (/etc/ssl/certs/) +capath = "" + +[capa] +folders = On +composer = On +contacts = On +settings = On +quota = On +help = On +reload = On +search = On +search_adv = On +filters = On +x-templates = Off +dangerous_actions = On +message_actions = On +messagelist_actions = On +attachments_actions = On + +[login] +default_domain = "domain.tld" + +; Allow language selection on webmail login screen +allow_languages_on_login = On +determine_user_language = On +determine_user_domain = Off +welcome_page = Off +forgot_password_link_url = "" +registration_link_url = "" + +; This option allows webmail to remember the logged in user +; once they closed the browser window. +; +; Values: +; "DefaultOff" - can be used, disabled by default; +; "DefaultOn" - can be used, enabled by default; +; "Unused" - cannot be used +sign_me_auto = "DefaultOff" + +[plugins] +; Enable plugin support +enable = On + +; List of enabled plugins +enabled_list = "PLUGINSTOENABLE" + +[defaults] +; Editor mode used by default (Plain, Html, HtmlForced or PlainForced) +view_editor_type = "Html" + +; layout: 0 - no preview, 1 - side preview, 2 - bottom preview +view_layout = 1 +view_use_checkboxes = On +autologout = Off +show_images = Off +contacts_autosave = On +mail_use_threads = Off +mail_reply_same_folder = Off + +[logs] +; Enable logging +enable = Off + +; Logs entire request only if error occured (php requred) +write_on_error_only = Off + +; Logs entire request only if php error occured +write_on_php_error_only = Off + +; Logs entire request only if request timeout (in seconds) occured. +write_on_timeout_only = 0 + +; Required for development purposes only. +; Disabling this option is not recommended. +hide_passwords = On +time_offset = 0 +session_filter = "" + +; Log filename. +; For security reasons, some characters are removed from filename. +; Allows for pattern-based folder creation (see examples below). +; +; Patterns: +; {date:Y-m-d} - Replaced by pattern-based date +; Detailed info: http://www.php.net/manual/en/function.date.php +; {user:email} - Replaced by user's email address +; If user is not logged in, value is set to "unknown" +; {user:login} - Replaced by user's login (the user part of an email) +; If user is not logged in, value is set to "unknown" +; {user:domain} - Replaced by user's domain name (the domain part of an email) +; If user is not logged in, value is set to "unknown" +; {user:uid} - Replaced by user's UID regardless of account currently used +; +; {user:ip} +; {request:ip} - Replaced by user's IP address +; +; Others: +; {imap:login} {imap:host} {imap:port} +; {smtp:login} {smtp:host} {smtp:port} +; +; Examples: +; filename = "log-{date:Y-m-d}.txt" +; filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log" +; filename = "{user:email}-{date:Y-m-d}.txt" +filename = "log-{date:Y-m-d}.txt" + +; Enable auth logging in a separate file (for fail2ban) +auth_logging = Off +auth_logging_filename = "fail2ban/auth-{date:Y-m-d}.txt" +auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}" + +[debug] +; Special option required for development purposes +enable = Off + +[social] +; Google +google_enable = Off +google_enable_auth = Off +google_enable_auth_fast = Off +google_enable_drive = Off +google_enable_preview = Off +google_client_id = "" +google_client_secret = "" +google_api_key = "" + +; Facebook +fb_enable = Off +fb_app_id = "" +fb_app_secret = "" + +; Twitter +twitter_enable = Off +twitter_consumer_key = "" +twitter_consumer_secret = "" + +; Dropbox +dropbox_enable = Off +dropbox_api_key = "" + +[cache] +; The section controls caching of the entire application. +; +; Enables caching in the system +enable = On + +; Additional caching key. If changed, cache is purged +index = "v1" + +; Can be: files, APC, memcache +fast_cache_driver = "files" + +; Additional caching key. If changed, fast cache is purged +fast_cache_index = "v1" + +; Browser-level cache. If enabled, caching is maintainted without using files +http = On + +; Caching message UIDs when searching and sorting (threading) +server_uids = On + +[labs] +; Experimental settings. Handle with care. +; +ignore_folders_subscription = Off +check_new_password_strength = On +update_channel = "stable" +allow_gravatar = On +allow_prefetch = On +allow_smart_html_links = On +cache_system_data = On +date_from_headers = Off +autocreate_system_folders = On +allow_message_append = Off +disable_iconv_if_mbstring_supported = Off +login_fault_delay = 1 +log_ajax_response_write_limit = 300 +allow_html_editor_source_button = Off +allow_html_editor_biti_buttons = Off +allow_ctrl_enter_on_compose = Off +try_to_detect_hidden_images = Off +hide_dangerous_actions = Off +use_app_debug_js = Off +use_app_debug_css = Off +use_imap_sort = On +use_imap_force_selection = Off +use_imap_list_subscribe = On +use_imap_thread = On +use_imap_move = On +use_imap_auth_plain = Off +use_imap_expunge_all_on_delete = Off +imap_forwarded_flag = "$Forwarded" +imap_read_receipt_flag = "$ReadReceipt" +imap_body_text_limit = 555000 +imap_message_list_fast_simple_search = On +imap_message_list_count_limit_trigger = 0 +imap_message_list_date_filter = 0 +imap_message_list_permanent_filter = "" +imap_message_all_headers = Off +imap_large_thread_limit = 50 +imap_folder_list_limit = 200 +imap_show_login_alert = On +smtp_show_server_errors = Off +sieve_allow_raw_script = Off +sieve_utf8_folder_name = On +mail_func_clear_headers = On +mail_func_additional_parameters = Off +favicon_status = On +folders_spec_limit = 50 +owncloud_save_folder = "Attachments" +curl_proxy = "" +curl_proxy_auth = "" +in_iframe = Off +force_https = Off +custom_login_link = "" +custom_logout_link = "" +allow_external_login = Off +allow_external_sso = Off +external_sso_key = "" +http_client_ip_check_proxy = Off +fast_cache_memcache_host = "127.0.0.1" +fast_cache_memcache_port = 11211 +fast_cache_memcache_expire = 43200 +use_local_proxy_for_external_images = Off +cookie_default_path = "" +startup_url = "" +emogrifier = On +dev_email = "" +dev_password = "" + +[version] +current = "1.9.3.363" +saved = "Wed, 07 Oct 2015 09:22:24 +0000" diff --git a/conf/data/domains/default.ini b/conf/data/domains/default.ini new file mode 100644 index 0000000..cf272b2 --- /dev/null +++ b/conf/data/domains/default.ini @@ -0,0 +1,16 @@ +imap_host = "auto" +imap_port = 993 +imap_secure = "SSL" +imap_short_login = Off +sieve_use = Off +sieve_allow_raw = Off +sieve_host = "" +sieve_port = 4190 +sieve_secure = "None" +smtp_host = "auto" +smtp_port = 465 +smtp_secure = "SSL" +smtp_short_login = Off +smtp_auth = On +smtp_php_mail = Off +white_list = "" diff --git a/conf/data/domains/domain.tld.ini b/conf/data/domains/domain.tld.ini new file mode 100644 index 0000000..b28de1f --- /dev/null +++ b/conf/data/domains/domain.tld.ini @@ -0,0 +1,16 @@ +imap_host = "localhost" +imap_port = 993 +imap_secure = "SSL" +imap_short_login = On +sieve_use = On +sieve_allow_raw = On +sieve_host = "localhost" +sieve_port = 4190 +sieve_secure = "TLS" +smtp_host = "localhost" +smtp_port = 587 +smtp_secure = "TLS" +smtp_short_login = On +smtp_auth = On +smtp_php_mail = Off +white_list = "" diff --git a/conf/nginx.conf b/conf/nginx.conf index c7d5d44..c45c7dc 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -5,8 +5,16 @@ location PATHTOCHANGE { rewrite ^ https://$server_name$request_uri? permanent; } + location ^~ PATHTOCHANGE/app/data { + deny all; + } + + location ^~ PATHTOCHANGE/pgpback/keys { + deny all; + } + client_max_body_size 10G; - index index.php; + index index.php index.html; try_files $uri $uri/ index.php; location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; diff --git a/hooks/post_domain_add b/hooks/post_domain_add new file mode 100644 index 0000000..534cf63 --- /dev/null +++ b/hooks/post_domain_add @@ -0,0 +1,7 @@ +#!/bin/bash + +app='rainloop' # This could never work with multi-instance. Need to find a better way +domain=$1 +rainloop_path=/var/www/$app/app + +sudo cp ../conf/data/domains/domain.tld.ini $rainloop_path/data/_data_/_default_/domains/$domain.ini diff --git a/hooks/post_domain_remove b/hooks/post_domain_remove new file mode 100644 index 0000000..e4d7a9b --- /dev/null +++ b/hooks/post_domain_remove @@ -0,0 +1,7 @@ +#!/bin/bash + +app='rainloop' # This could never work with multi-instance. Need to find a better way +domain=$1 +rainloop_path=/var/www/$app/app + +sudo rm $rainloop_path/data/_data_/_default_/domains/$domain.ini diff --git a/manifest.json b/manifest.json index dab095c..e76dca7 100644 --- a/manifest.json +++ b/manifest.json @@ -1,16 +1,25 @@ { + "packaging_format": 1, "name": "Rainloop", "id": "rainloop", "description": { - "en": "Lightweight webmail", - "fr": "Webmail leger" + "en": "Lightweight multi-account webmail", + "fr": "Webmail léger multi-comptes" }, "url": "http://rainloop.net/", + "license": "free", "maintainer": { - "name": "polytan02", - "email": "polytan02@mcgva.org" + "name": "scith, Djip007" }, - "multi_instance": "false", + "multi_instance": false, + "services": [ + "nginx", + "php5-fpm", + "mysql" + ], + "requirements": { + "yunohost": ">= 2.4.0" + }, "arguments": { "install" : [ { @@ -35,20 +44,37 @@ { "name": "is_public", "ask": { - "en": "Is it a public application ?", + "en": "Is it a public application?", "fr": "Est-ce une page publique ?" }, "choices": ["Yes", "No"], "default": "No" }, - { - "name": "dp_pwd", + { + "name": "password", "type": "password", "ask": { - "en": "Choose a password for Rainloop MySQL database. Please note that the table and the user will be rainloop (case sensitive - used for carddav)", - "fr": "Choisissez un mot de passe pour la base MySQL de Rainloop. Veuillez noter que la table et l'utilisateur créés seront rainloop (sensible à la casse - utilisé pour carddav)" + "en": "Choose a strong password for the 'admin' user", + "fr": "Choisissez un mot de passe fort pour l'administrateur 'admin'" + } + }, + { + "name": "ldap", + "ask": { + "en": "Do you want to add YunoHost users to the recipients suggestions?", + "fr": "Souhaitez-vous ajouter les utilisateurs YunoHost dans les suggestions de destinataires ?" }, - "example": "my_strong_password" + "choices": ["Yes", "No"], + "default": "Yes" + }, + { + "name": "lang", + "ask": { + "en": "Select default language", + "fr": "Definir la langue par defaut" + }, + "choices": ["English", "Francais"], + "default": "English" } ] } diff --git a/scripts/backup b/scripts/backup new file mode 100644 index 0000000..a973630 --- /dev/null +++ b/scripts/backup @@ -0,0 +1,31 @@ +#!/bin/bash + +# Exit on command errors and treat unset variables as an error + set -eu + app=$YNH_APP_INSTANCE_NAME + +# Set app specific variables + dbname=$app + dbuser=$app + +# Source app helpers + source /usr/share/yunohost/helpers + +# Retrieve app settings + domain=$(ynh_app_setting_get "$app" domain) + path=$(ynh_app_setting_get "$app" path) + dbpass=$(ynh_app_setting_get "$app" mysqlpwd) + +# Copy the app files + DESTDIR="/var/www/$app" + ynh_backup "$DESTDIR" "sources" + +# Copy the conf files + ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" + +# Copy dedicated php-fpm process to backup folder + ynh_backup "/etc/php5/fpm/pool.d/${app}.conf" "php-fpm.conf" + +# Dump the database + mysqldump -u "$dbuser" -p"$dbpass" --no-create-db "$dbname" > ./db.sql + ynh_backup "db.sql" "dump.sql" diff --git a/scripts/install b/scripts/install index 6359874..42c9d9f 100644 --- a/scripts/install +++ b/scripts/install @@ -1,80 +1,148 @@ #!/bin/bash -app=rainloop +# Exit on command errors and treat unset variables as an error + set -eu + app=$YNH_APP_INSTANCE_NAME + rainloop_version='1.10.5.192' + +# Source app helpers + . /usr/share/yunohost/helpers # Retrieve arguments -domain=$1 -path=$2 -is_public=$3 - -# Removal of trailing / -if [ $path = "/" ] -then - #sitename="root" - echo "Installation on the root of the domain" -else - # sitename == path without any "/" - #sitename=$(echo $path | cut -d '/' -f 2) - # Removal of trailing / - # path can be null but not really an issue for the remaining commands - path=${path%/} -fi - + domain=$YNH_APP_ARG_DOMAIN + path=$YNH_APP_ARG_PATH + is_public=$YNH_APP_ARG_IS_PUBLIC + password=$YNH_APP_ARG_PASSWORD + ldap=$YNH_APP_ARG_LDAP + lang=$YNH_APP_ARG_LANG +# Correct path + if [ "${path:0:1}" != "/" ]; then + path="/$path" + fi + if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then + path="${path:0:${#path}-1}" + fi # Check domain/path availability -sudo yunohost app checkurl $domain$path -a rainloop -if [[ ! $? -eq 0 ]]; then - exit 1 -fi - -# Generate random password -#db_pwd=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d 'A-Za-z0-9' | sed -n 's/\(.\{24\}\).*/\1/p') -db_pwd=$4 + sudo yunohost app checkurl "${domain}${path}" -a "$app" \ + || ynh_die "Path not available: ${domain}${path}" # Use 'rainloop' as database name and user -db_user=$app + dbuser=$app + dbname=$app + dbpass=$(ynh_string_random) # Initialize database and store mysql password for upgrade -sudo yunohost app initdb $db_user -p $db_pwd -sudo yunohost app setting rainloop mysqlpwd -v $db_pwd + ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" + ynh_app_setting_set "$app" mysqlpwd "$dbpass" -#mysql -u $db_user -p$db_pwd $db_user < ../sources/plugins/automatic_addressbook/SQL/mysql.initial.sql +# Create the final path and copy sources + final_path=/var/www/$app + rainloop_path=${final_path}/app -# Copy files to the right place -final_path=/var/www/$app -sudo rm -rf $final_path -sudo mkdir -p $final_path -# Use of latest community edition -sudo wget http://repository.rainloop.net/v2/webmail/rainloop-community-latest.zip -O $final_path/rainloop.zip -sudo unzip $final_path/rainloop.zip -d $final_path/ -sudo rm $final_path/rainloop.zip + sudo rm -rf $final_path + sudo mkdir -p $final_path + sudo mkdir -p $rainloop_path + + # Download sources and keys + sudo wget -q https://github.com/RainLoop/rainloop-webmail/releases/download/v${rainloop_version}/rainloop-community-${rainloop_version}.zip + sudo wget -q https://github.com/RainLoop/rainloop-webmail/releases/download/v${rainloop_version}/rainloop-community-${rainloop_version}.zip.asc + sudo wget -q https://repository.rainloop.net/RainLoop.asc + # Verify the integrity of sources + sudo gpg --import --quiet RainLoop.asc + sudo gpg --verify --quiet rainloop-community-${rainloop_version}.zip.asc rainloop-community-${rainloop_version}.zip || ynh_die "Download failed" + sudo gpg --batch --delete-key --yes Rainloop + # Unzip + sudo unzip -qq rainloop-community-${rainloop_version}.zip -d $rainloop_path/ + + # Install plugins + sudo mkdir -p $rainloop_path/data/_data_/_default_/plugins + sudo cp -rf ../sources/plugins/auto-domain-grab $rainloop_path/data/_data_/_default_/plugins/. + sudo cp -rf ../sources/plugins/ynh-login-mapping $rainloop_path/data/_data_/_default_/plugins/. + sudo cp -rf ../sources/plugins/ynh-ldap-suggestions $rainloop_path/data/_data_/_default_/plugins/. + +# Autoconfig + sudo mkdir -p $rainloop_path/data/_data_/_default_/configs/ + application_file=$rainloop_path/data/_data_/_default_/configs/application.ini + + # Set lang => define from install manifest + case "$lang" in + Francais) + lang="fr" + ;; + English) + lang="en" + ;; + *) + lang="en" + esac + ynh_app_setting_set "$app" lang "$lang" + + # Set plugins + plugins="auto-domain-grab" # This plugin is trying to automatically grab unknown domains if users want to add external email accounts + if [ "$ldap" = "Yes" ]; + then + plugins="$plugins,ynh-ldap-suggestions" # This plugin is to suggest YunoHost users in recipients list + fi + ynh_app_setting_set "$app" plugins "$plugins" + + sudo cp ../conf/data/configs/application.ini $application_file + sudo sed -i "s@domain.tld@$domain@g" $application_file + sudo sed -i "s@MYSQLUSER@$dbuser@g" $application_file + sudo sed -i "s@MYSQLPASSWORD@$dbpass@g" $application_file + sudo sed -i "s@LANGTOCHANGE@$lang@g" $application_file + sudo sed -i "s@PLUGINSTOENABLE@$plugins@g" $application_file + +# Set admin password + sudo php ../conf/config.php --index="$rainloop_path/index.php" --password="$password" + ynh_app_setting_set "$app" password "$password" + +# Add default domain configs by looping through all the domains already added + sudo mkdir -p $rainloop_path/data/_data_/_default_/domains/ + # get list of ldap domains + alldomains=`ldapsearch -LLL -x -b ou=domains,dc=yunohost,dc=org -s one "objectclass=top" virtualdomain | grep -v "dn:" | sed "s/virtualdomain://" ` + for ldomain in $alldomains ; do + sudo cp ../conf/data/domains/domain.tld.ini $rainloop_path/data/_data_/_default_/domains/$ldomain.ini + done + # Add wildcard domain for auto-grab + sudo cp ../conf/data/domains/default.ini $rainloop_path/data/_data_/_default_/domains/default.ini + +# install SSO - at the moment the index is the SSO and rainloop is installed in /app + sudo cp ../sources/sso/sso.php $final_path/index.php + sudo sed -i "s@domain.tld@$domain@g" $final_path/index.php + sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/index.php + +# Install PGPback by chtixof to allow users to backup/restore their PGP private keys on the server + sudo cp -rf ../sources/pgpback $final_path/. # Set permissions to rainloop directory -# sudo mkdir -p $final_path/logs -sudo chown -R www-data:www-data $final_path + sudo find $final_path/. -type d -exec chmod 755 {} \; + sudo find $final_path/. -type f -exec chmod 644 {} \; + sudo chown -R www-data:www-data $final_path -# Modify Nginx configuration file and copy it to Nginx conf directory -sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf -sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf -sed -i "s@NAMETOCHANGE@$app@g" ../conf/nginx.conf -sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf +# Install Nginx configuration file + nginx_conf_file=/etc/nginx/conf.d/$domain.d/$app.conf + sudo cp ../conf/nginx.conf $nginx_conf_file + sudo sed -i "s@PATHTOCHANGE@$path@g" $nginx_conf_file + sudo sed -i "s@ALIASTOCHANGE@$final_path/@g" $nginx_conf_file + sudo sed -i "s@NAMETOCHANGE@$app@g" $nginx_conf_file + sudo chown root: $nginx_conf_file + sudo chmod 644 $nginx_conf_file -sed -i "s@NAMETOCHANGE@$app@g" ../conf/php-fpm.conf -finalphpconf=/etc/php5/fpm/pool.d/$app.conf -sudo cp ../conf/php-fpm.conf $finalphpconf -sudo chown root: $finalphpconf -sudo chmod 644 $finalphpconf + finalphpconf=/etc/php5/fpm/pool.d/$app.conf + sudo cp ../conf/php-fpm.conf $finalphpconf + sudo sed -i "s@NAMETOCHANGE@$app@g" $finalphpconf + sudo chown root: $finalphpconf + sudo chmod 644 $finalphpconf # Make app public if necessary -sudo yunohost app setting $app is_public -v "$is_public" -if [ "$is_public" = "Yes" ]; -then - sudo yunohost app setting $app skipped_uris -v "/" -fi + ynh_app_setting_set "$app" is_public "$is_public" + if [ "$is_public" = "Yes" ]; + then + ynh_app_setting_set "$app" skipped_uris "/" + fi - -# Reload Nginx and regenerate SSOwat conf -sudo service php5-fpm reload -sudo service nginx reload -sudo yunohost app ssowatconf +# Reload services + sudo service php5-fpm reload || true + sudo service nginx reload || true diff --git a/scripts/remove b/scripts/remove index d3c64c6..318d192 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,18 +1,29 @@ #!/bin/bash -app=rainloop +# Exit on command errors and treat unset variables as an error + set -eu + app=$YNH_APP_INSTANCE_NAME -db_user=$app -db_name=$app -root_pwd=$(sudo cat /etc/yunohost/mysql) -domain=$(sudo yunohost app setting $app domain) +# Source app helpers + source /usr/share/yunohost/helpers -mysql -u root -p$root_pwd -e "DROP DATABASE $db_name ; DROP USER $db_user@localhost ;" -sudo rm -rf /var/www/$app -sudo rm -f /etc/nginx/conf.d/$domain.d/$app.conf -sudo rm -f /etc/php5/fpm/pool.d/$app.conf +# Retrieve arguments + dbuser=$app + dbname=$app + domain=$(ynh_app_setting_get "$app" domain) -sudo service php5-fpm restart -sudo service nginx reload -sudo yunohost app ssowatconf +# Drop MySQL database and user + ynh_mysql_drop_db "$dbname" 2>&1 || true + ynh_mysql_drop_user "$dbuser" 2>&1 || true +# Delete app directory and configurations + sudo rm -rf "/var/www/${app}" + sudo rm -f "/etc/php5/fpm/pool.d/${app}.conf" + [[ -n $domain ]] && sudo rm -f "/etc/nginx/conf.d/${domain}.d/${app}.conf" + +# Remove GPG key + sudo gpg --batch --delete-key --yes Rainloop + +# Reload services + sudo service php5-fpm reload || true + sudo service nginx reload || true diff --git a/scripts/restore b/scripts/restore new file mode 100644 index 0000000..3d3aef5 --- /dev/null +++ b/scripts/restore @@ -0,0 +1,56 @@ +#!/bin/bash + +# Exit on command errors and treat unset variables as an error + set -eu + +# Get multi-instances specific variables + app=$YNH_APP_INSTANCE_NAME + +# Source app helpers + source /usr/share/yunohost/helpers + +# Retrieve old app settings + domain=$(ynh_app_setting_get "$app" domain) + path=$(ynh_app_setting_get "$app" path) + dbname=$app + dbuser=$app + dbpass=$(ynh_app_setting_get "$app" mysqlpwd) + +# Check domain/path availability + sudo yunohost app checkurl "${domain}${path}" -a "$app" \ + || ynh_die + +# Check destination directory + DESTDIR="/var/www/$app" + [[ -d $DESTDIR ]] && ynh_die \ + "The destination directory '$DESTDIR' already exists.\ + You should safely delete it before restoring this app." + +# Check configuration files + nginx_conf="/etc/nginx/conf.d/${domain}.d/${app}.conf" + [[ -f $nginx_conf ]] && ynh_die \ + "The NGINX configuration already exists at '${nginx_conf}'. + You should safely delete it before restoring this app." + phpfpm_conf="/etc/php5/fpm/pool.d/${app}.conf" + [[ -f $phpfpm_conf ]] && ynh_die \ + "The PHP FPM configuration already exists at '${phpfpm_conf}'. + You should safely delete it before restoring this app." + +# Restore the app files + sudo cp -a ./sources "$DESTDIR" + +# Create and restore the database + ynh_mysql_create_db $dbname $dbuser $dbpass + ynh_mysql_connect_as $dbuser $dbpass $dbname < ./dump.sql + +# Fix installation directories and permissions + sudo mkdir -p "${DESTDIR}/logs" "${DESTDIR}/temp" + sudo chown -R www-data: "$DESTDIR" + +# Restore configuration files + sudo cp -a ./nginx.conf "$nginx_conf" + sudo cp -a ./php-fpm.conf "$phpfpm_conf" + +# Reload services + sudo service php5-fpm reload || true + sudo service nginx reload || true diff --git a/scripts/upgrade b/scripts/upgrade index 231aaea..879d1ee 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,51 +1,99 @@ #!/bin/bash + app=$YNH_APP_INSTANCE_NAME + rainloop_version='1.10.5.192' -app=rainloop +# Backup the current version of the app, restore it if the upgrade fails +# Check if old backup exists + if sudo yunohost backup list | grep -q $app-before-upgrade > /dev/null 2>&1; + then + sudo yunohost backup delete $app-before-upgrade + else + echo "no old backup to delete" + fi + sudo yunohost backup create --ignore-hooks --apps $app --name $app-before-upgrade --quiet + EXIT_PROPERLY () { + trap '' EXIT + set +eu + sudo yunohost backup restore --ignore-hooks $app-before-upgrade --apps $app --force --quiet # Restore the backup if upgrade failed + ynh_die "Upgrade failed. The app was restored to the way it was before the failed upgrade." + } + set -eu + trap EXIT_PROPERLY ERR + +# Source app helpers + source /usr/share/yunohost/helpers # Retrieve arguments -domain=$(sudo yunohost app setting $app domain) -path=$(sudo yunohost app setting $app path) -is_public=$(sudo yunohost app setting $app is_public) -dp_pwd=$(sudo yunohost app setting rainloop mysqlpwd) -db_user=$app + domain=$(ynh_app_setting_get "$app" domain) + path=$(ynh_app_setting_get "$app" path) + is_public=$(ynh_app_setting_get "$app" is_public) + password=$(ynh_app_setting_get "$app" password) + ldap=$(ynh_app_setting_get "$app" ldap) + lang=$(ynh_app_setting_get "$app" lang) + dp_pwd=$(ynh_app_setting_get "$app" mysqlpwd) + db_user=$app + plugins=$(ynh_app_setting_get "$app" plugins) -# Initialize database and store mysql password for upgrade -root_pwd=$(sudo cat /etc/yunohost/mysql) -mysql -u root -p$root_pwd -e "DROP DATABASE $db_name ; DROP USER $db_user@localhost ;" -sudo yunohost app initdb $db_user -p $db_pwd +# Correct path + if [ "${path:0:1}" != "/" ]; then + path="/$path" + fi + if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then + path="${path:0:${#path}-1}" + fi -# Copy files to the right place -final_path=/var/www/$app -#sudo rm -rf $final_path/* -# Use of latest community edition -sudo wget http://repository.rainloop.net/v2/webmail/rainloop-community-latest.zip -O $final_path/rainloop.zip -sudo unzip -ou $final_path/rainloop.zip -d $final_path/ -sudo rm $final_path/rainloop.zip +# no update for db now... + +# Copy the new sources + final_path=/var/www/$app + rainloop_path=${final_path}/app + sudo rm -rf $rainloop_path/rainloop # Remove the previous Rainloop files except data + + # Download sources and keys + sudo wget -q https://github.com/RainLoop/rainloop-webmail/releases/download/v${rainloop_version}/rainloop-community-${rainloop_version}.zip + sudo wget -q https://github.com/RainLoop/rainloop-webmail/releases/download/v${rainloop_version}/rainloop-community-${rainloop_version}.zip.asc + sudo wget -q https://repository.rainloop.net/RainLoop.asc + # Verify the integrity of sources + sudo gpg --import --quiet RainLoop.asc + sudo gpg --verify --quiet rainloop-community-${rainloop_version}.zip.asc rainloop-community-${rainloop_version}.zip + sudo gpg --batch --delete-key --yes Rainloop + # Unzip and overwrite + sudo unzip -qq -o rainloop-community-${rainloop_version}.zip -d $rainloop_path/ + + # Update ynh plugins: + sudo mkdir -p $rainloop_path/data/_data_/_default_/plugins + sudo cp -rf ../sources/plugins/auto-domain-grab $rainloop_path/data/_data_/_default_/plugins/. + sudo cp -rf ../sources/plugins/ynh-login-mapping $rainloop_path/data/_data_/_default_/plugins/. + sudo cp -rf ../sources/plugins/ynh-ldap-suggestions $rainloop_path/data/_data_/_default_/plugins/. + +# update SSO + sudo cp ../sources/sso/sso.php $final_path/index.php + sudo sed -i "s@domain.tld@$domain@g" $final_path/index.php + sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/index.php + +# Install PGPback by chtixof to allow users to backup/restore their PGP private keys on the server + sudo cp -rf ../sources/pgpback $final_path/. # Set permissions to rainloop directory -sudo chown -R www-data:www-data /var/www/$app + sudo find $final_path/. -type d -exec chmod 755 {} \; + sudo find $final_path/. -type f -exec chmod 644 {} \; + sudo chown -R www-data:www-data $final_path -# Modify Nginx configuration file and copy it to Nginx conf directory -sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf -sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf -sed -i "s@NAMETOCHANGE@$app@g" ../conf/nginx.conf -sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf +# Update Nginx configuration file + nginx_conf_file=/etc/nginx/conf.d/$domain.d/$app.conf + sudo cp ../conf/nginx.conf $nginx_conf_file + sudo sed -i "s@PATHTOCHANGE@$path@g" $nginx_conf_file + sudo sed -i "s@ALIASTOCHANGE@$final_path/@g" $nginx_conf_file + sudo sed -i "s@NAMETOCHANGE@$app@g" $nginx_conf_file + sudo chown root: $nginx_conf_file + sudo chmod 644 $nginx_conf_file -sed -i "s@NAMETOCHANGE@$app@g" ../conf/php-fpm.conf -finalphpconf=/etc/php5/fpm/pool.d/$app.conf -sudo cp ../conf/php-fpm.conf $finalphpconf -sudo chown root: $finalphpconf -sudo chmod 644 $finalphpconf + finalphpconf=/etc/php5/fpm/pool.d/$app.conf + sudo cp ../conf/php-fpm.conf $finalphpconf + sudo sed -i "s@NAMETOCHANGE@$app@g" $finalphpconf + sudo chown root: $finalphpconf + sudo chmod 644 $finalphpconf -# Make app public if necessary -sudo yunohost app setting $app is_public -v "$is_public" -if [ "$is_public" = "Yes" ]; -then - sudo yunohost app setting $app skipped_uris -v "/" -fi - - -# Reload Nginx and regenerate SSOwat conf -sudo service php5-fpm reload -sudo service nginx reload -sudo yunohost app ssowatconf +# Reload services + sudo service php5-fpm reload || true + sudo service nginx reload || true diff --git a/sources/pgpback/fav.php b/sources/pgpback/fav.php new file mode 100644 index 0000000..ed6eebc --- /dev/null +++ b/sources/pgpback/fav.php @@ -0,0 +1,23 @@ + diff --git a/sources/pgpback/index.html b/sources/pgpback/index.html new file mode 100644 index 0000000..2671b0a --- /dev/null +++ b/sources/pgpback/index.html @@ -0,0 +1,90 @@ + + + + PGPBack + + + + +

PGPBack : OpenPGP keys backup for Rainloop

+PGPBack has been tested with Chrome. It enables the following:

+Set the local OpenPGP keys from the server

+Backup the local OpenPGP keys onto the server

+Clear the local OpenPGP keys (for security reasons)

+ + + + \ No newline at end of file diff --git a/sources/pgpback/lib/jquery-1.11.2.min.js b/sources/pgpback/lib/jquery-1.11.2.min.js new file mode 100644 index 0000000..e6a051d --- /dev/null +++ b/sources/pgpback/lib/jquery-1.11.2.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.2 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.2",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("