changeset 1512:bf263968da47

merge beta in stable branch
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 07 Oct 2011 01:08:50 +0200
parents e058df3ff2b4 (current diff) a5981def1961 (diff)
children 12946daf44f9
files .hgtags CONTRIBUTORS MANIFEST.in README.rst development.ini docs/changelog.rst docs/contributing.rst docs/enable_git.rst docs/index.rst docs/installation.rst docs/setup.rst docs/statistics.rst docs/upgrade.rst docs/usage/enable_git.rst docs/usage/statistics.rst ez_setup.py production.ini rhodecode/__init__.py rhodecode/config/deployment.ini_tmpl rhodecode/config/environment.py rhodecode/config/middleware.py rhodecode/config/routing.py rhodecode/controllers/admin/admin.py rhodecode/controllers/admin/ldap_settings.py rhodecode/controllers/admin/permissions.py rhodecode/controllers/admin/repos.py rhodecode/controllers/admin/settings.py rhodecode/controllers/admin/users.py rhodecode/controllers/branches.py rhodecode/controllers/changelog.py rhodecode/controllers/changeset.py rhodecode/controllers/error.py rhodecode/controllers/feed.py rhodecode/controllers/files.py rhodecode/controllers/home.py rhodecode/controllers/journal.py rhodecode/controllers/login.py rhodecode/controllers/search.py rhodecode/controllers/settings.py rhodecode/controllers/shortlog.py rhodecode/controllers/summary.py rhodecode/controllers/tags.py rhodecode/i18n/rhodecode.pot rhodecode/lib/__init__.py rhodecode/lib/auth.py rhodecode/lib/auth_ldap.py rhodecode/lib/backup_manager.py rhodecode/lib/celerylib/__init__.py rhodecode/lib/celerylib/tasks.py rhodecode/lib/colored_formatter.py rhodecode/lib/db_manage.py rhodecode/lib/dbmigrate/__init__.py rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py rhodecode/lib/dbmigrate/versions/__init__.py rhodecode/lib/exceptions.py rhodecode/lib/helpers.py rhodecode/lib/hooks.py rhodecode/lib/indexers/__init__.py rhodecode/lib/indexers/daemon.py rhodecode/lib/middleware/https_fixup.py rhodecode/lib/middleware/simplegit.py rhodecode/lib/middleware/simplehg.py rhodecode/lib/smtp_mailer.py rhodecode/lib/timerproxy.py rhodecode/lib/utils.py rhodecode/model/__init__.py rhodecode/model/db.py rhodecode/model/forms.py rhodecode/model/permission.py rhodecode/model/repo.py rhodecode/model/scm.py rhodecode/model/settings.py rhodecode/model/user.py rhodecode/public/css/style.css rhodecode/public/images/quick_l.png rhodecode/public/images/quick_l_selected.png rhodecode/public/images/quick_r.png rhodecode/public/images/quick_r_selected.png rhodecode/public/js/yui2a.js rhodecode/templates/admin/permissions/permissions.html rhodecode/templates/admin/repos/repos.html rhodecode/templates/admin/settings/settings.html rhodecode/templates/admin/users/user_edit_my_account.html rhodecode/templates/base/base.html rhodecode/templates/changelog/changelog.html rhodecode/templates/changeset/changeset.html rhodecode/templates/errors/error_404.html rhodecode/templates/errors/error_document.html rhodecode/templates/files/files_annotate.html rhodecode/templates/files/files_browser.html rhodecode/templates/files/files_source.html rhodecode/templates/index.html rhodecode/templates/journal.html rhodecode/templates/journal/journal.html rhodecode/templates/login.html rhodecode/templates/password_reset.html rhodecode/templates/register.html rhodecode/templates/summary/summary.html rhodecode/tests/__init__.py rhodecode/tests/functional/test_changelog.py rhodecode/tests/test_hg_operations.sh rhodecode/websetup.py setup.cfg setup.py test.ini
diffstat 225 files changed, 22326 insertions(+), 5724 deletions(-) [+]
line wrap: on
line diff
--- a/CONTRIBUTORS	Thu May 12 19:50:48 2011 +0200
+++ b/CONTRIBUTORS	Fri Oct 07 01:08:50 2011 +0200
@@ -4,4 +4,12 @@
     Jason Harris <jason@jasonfharris.com>
     Thayne Harbaugh  <thayne@fusionio.com>
     cejones
-    Thomas Waldmann <tw-public@gmx.de>
\ No newline at end of file
+    Thomas Waldmann <tw-public@gmx.de>
+    Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>
+    Dmitri Kuznetsov
+    Jared Bunting <jared.bunting@peachjean.com>
+    Steve Romanow <slestak989@gmail.com>
+    Augosto Hermann <augusto.herrmann@planejamento.gov.br>    
+    Ankit Solanki <ankit.solanki@gmail.com>    
+    Liad Shani <liadff@gmail.com>
+    
\ No newline at end of file
--- a/MANIFEST.in	Thu May 12 19:50:48 2011 +0200
+++ b/MANIFEST.in	Fri Oct 07 01:08:50 2011 +0200
@@ -14,9 +14,6 @@
 recursive-include rhodecode/public/css *
 recursive-include rhodecode/public/images *
 #js
-include rhodecode/public/js/yui2a.js
-include rhodecode/public/js/excanvas.min.js
-include rhodecode/public/js/yui.flot.js
-include rhodecode/public/js/graph.js
+recursive-include rhodecode/public/js *
 #templates
 recursive-include rhodecode/templates *
--- a/README.rst	Thu May 12 19:50:48 2011 +0200
+++ b/README.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -1,4 +1,3 @@
-
 =================================================
 Welcome to RhodeCode (RhodiumCode) documentation!
 =================================================
@@ -26,13 +25,13 @@
 using the following credentials:
 
 - username: demo
-- password: demo
+- password: demo12
 
 Source code
 -----------
 
 The latest sources can be obtained from official RhodeCode instance
-https://hg.rhodecode.org 
+https://secure.rhodecode.org 
 
 
 MIRRORS:
@@ -60,20 +59,28 @@
   Supports http/https and LDAP
 - Full permissions (private/read/write/admin) and authentication per project. 
   One account for web interface and mercurial_ push/pull/clone operations.
+- Have built in users groups for easier permission management
+- Repository groups let you group repos and manage them easier.
+- Users can fork other users repo. RhodeCode have also compare view to see
+  combined changeset for all changeset made within single push.
+- Build in commit-api let's you add, edit and commit files right from RhodeCode
+  interface using simple editor or upload form for binaries.
 - Mako templates let's you customize the look and feel of the application.
-- Beautiful diffs, annotations and source code browsing all colored by pygments.
+- Beautiful diffs, annotations and source code browsing all colored by pygments. 
+  Raw diffs are made in git-diff format, including git_ binary-patches
 - Mercurial_ branch graph and yui-flot powered graphs with zooming and statistics
 - Admin interface with user/permission management. Admin activity journal, logs
   pulls, pushes, forks, registrations and other actions made by all users.
-- Server side forks. It is possible to fork a project and modify it freely without
-  breaking the main repository.
+- Server side forks. It is possible to fork a project and modify it freely 
+  without breaking the main repository. You can even write Your own hooks 
+  and install them
 - Full text search powered by Whoosh on the source files, and file names.
   Build in indexing daemons, with optional incremental index build
   (no external search servers required all in one application)
 - Setup project descriptions and info inside built in db for easy, non 
   file-system operations
-- Intelligent cache with invalidation after push or project change, provides high 
-  performance and always up to date data.
+- Intelligent cache with invalidation after push or project change, provides 
+  high performance and always up to date data.
 - Rss / atom feeds, gravatar support, download sources as zip/tar/gz
 - Async tasks for speed and performance using celery_ (works without them too)  
 - Backup scripts can do backup of whole app and send it over scp to desired 
@@ -87,17 +94,17 @@
 Incoming / Plans
 ----------------
 
-- Project grouping
-- User groups/teams
+- Finer granular permissions per branch, repo group or subrepo
+- pull requests and web based merges
+- notification and message system 
 - SSH based authentication with server side key management
 - Code review (probably based on hg-review)
 - Full git_ support, with push/pull server (currently in beta tests)
-- Redmine integration
-- Public accessible activity feeds
+- Redmine and other bugtrackers integration
 - Commit based built in wiki system
-- Clone points and cloning from remote repositories into RhodeCode
 - More statistics and graph (global annotation + some more statistics)
-- Other advancements as development continues (or you can of course make additions and or requests)
+- Other advancements as development continues (or you can of course make 
+  additions and or requests)
 
 License
 -------
--- a/development.ini	Thu May 12 19:50:48 2011 +0200
+++ b/development.ini	Fri Oct 07 01:08:50 2011 +0200
@@ -7,6 +7,7 @@
 
 [DEFAULT]
 debug = true
+pdebug = false
 ################################################################################
 ## Uncomment and replace with the address which should receive                ## 
 ## any error reports after application crash                                  ##
@@ -48,6 +49,8 @@
 app_instance_uuid = develop
 cut_off_limit = 256000
 force_https = false
+commit_parse_limit = 25
+use_gravatar = true
 
 ####################################
 ###        CELERY CONFIG        ####
@@ -139,8 +142,9 @@
 #########################################################
 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 #########################################################
-sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
-sqlalchemy.db1.echo = True
+#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
+sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
+sqlalchemy.db1.echo = false
 sqlalchemy.db1.pool_recycle = 3600
 sqlalchemy.convert_unicode = true
 
@@ -201,13 +205,13 @@
 [handler_console]
 class = StreamHandler
 args = (sys.stderr,)
-level = NOTSET
+level = DEBUG
 formatter = color_formatter
 
 [handler_console_sql]
 class = StreamHandler
 args = (sys.stderr,)
-level = NOTSET
+level = DEBUG
 formatter = color_formatter_sql
 
 ################
@@ -226,4 +230,4 @@
 [formatter_color_formatter_sql]
 class=rhodecode.lib.colored_formatter.ColorFormatterSql
 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
-datefmt = %Y-%m-%d %H:%M:%S
\ No newline at end of file
+datefmt = %Y-%m-%d %H:%M:%S
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/api/api.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,111 @@
+.. _api:
+
+
+API
+===
+
+
+Starting from RhodeCode version 1.2 a simple API was implemented.
+There's a single schema for calling all api methods. API is implemented
+with JSON protocol both ways. An url to send API request in RhodeCode is 
+<your_server>/_admin/api
+
+
+All clients need to send JSON data in such format::
+
+    {
+        "api_key":"<api_key>",
+        "method":"<method_name>",
+        "args":{"<arg_key>":"<arg_val>"}
+    }
+
+Example call for autopulling remotes repos using curl::
+    curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
+
+Simply provide 
+ - *api_key* for access and permission validation.
+ - *method* is name of method to call
+ - *args* is an key:value list of arguments to pass to method
+    
+.. note::
+    
+    api_key can be found in your user account page    
+    
+    
+RhodeCode API will return always a JSON formatted answer::
+    
+    {
+        "result": "<result>", 
+        "error": null
+    }
+
+All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
+calling api *error* key from response will contain failure description 
+and result will be null.
+
+API METHODS
++++++++++++
+
+    
+pull
+----
+
+Pulls given repo from remote location. Can be used to automatically keep 
+remote repos up to date. This command can be executed only using api_key 
+belonging to user with admin rights
+
+INPUT::
+
+    api_key:"<api_key>"
+    method: "pull"
+    args: {"repo":<repo_name>}
+
+OUTPUT::
+
+    result:"Pulled from <repo_name>"
+    error:null
+
+    
+create_user
+-----------
+
+Creates new user in RhodeCode. This command can be executed only using api_key 
+belonging to user with admin rights
+
+INPUT::
+
+    api_key:"<api_key>"
+    method: "create_user"
+    args: {"username": "<username>", 
+           "password": "<password>", 
+           "active":   "<bool>", 
+           "admin":    "<bool>", 
+           "name":     "<firstname>", 
+           "lastname": "<lastname>", 
+           "email":    "<useremail>"}
+
+OUTPUT::
+
+    result:{"id": <newuserid>,
+            "msg":"created new user <username>"}
+    error:null
+    
+    
+create_users_group
+------------------
+
+creates new users group. This command can be executed only using api_key 
+belonging to user with admin rights
+
+INPUT::
+
+    api_key:"<api_key>"
+    method: "create_user"
+    args: {"name":  "<groupname>", 
+           "active":"<bool>"}
+
+OUTPUT::
+
+    result:{"id": <newusersgroupid>,
+            "msg":"created new users group <groupname>"}
+    error:null    
--- a/docs/api/index.rst	Thu May 12 19:50:48 2011 +0200
+++ b/docs/api/index.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -7,4 +7,4 @@
    :maxdepth: 3
 
    models
-    
\ No newline at end of file
+   api 
\ No newline at end of file
--- a/docs/changelog.rst	Thu May 12 19:50:48 2011 +0200
+++ b/docs/changelog.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -3,7 +3,79 @@
 Changelog
 =========
 
+1.2.0 (**2011-10-07**)
+======================
 
+
+news
+----
+
+- implemented #47 repository groups
+- implemented #89 Can setup google analytics code from settings menu
+- implemented #91 added nicer looking archive urls with more download options
+  like tags, branches
+- implemented #44 into file browsing, and added follow branch option
+- implemented #84 downloads can be enabled/disabled for each repository
+- anonymous repository can be cloned without having to pass default:default
+  into clone url
+- fixed #90 whoosh indexer can index chooses repositories passed in command 
+  line
+- extended journal with day aggregates and paging
+- implemented #107 source code lines highlight ranges
+- implemented #93 customizable changelog on combined revision ranges - 
+  equivalent of githubs compare view 
+- implemented #108 extended and more powerful LDAP configuration
+- implemented #56 users groups
+- major code rewrites optimized codes for speed and memory usage
+- raw and diff downloads are now in git format
+- setup command checks for write access to given path
+- fixed many issues with international characters and unicode. It uses utf8
+  decode with replace to provide less errors even with non utf8 encoded strings
+- #125 added API KEY access to feeds
+- #109 Repository can be created from external Mercurial link (aka. remote 
+  repository, and manually updated (via pull) from admin panel
+- beta git support - push/pull server + basic view for git repos
+- added followers page and forks page
+- server side file creation (with binary file upload interface) 
+  and edition with commits powered by codemirror 
+- #111 file browser file finder, quick lookup files on whole file tree 
+- added quick login sliding menu into main page
+- changelog uses lazy loading of affected files details, in some scenarios 
+  this can improve speed of changelog page dramatically especially for 
+  larger repositories.
+- implements #214 added support for downloading subrepos in download menu.
+- Added basic API for direct operations on rhodecode via JSON
+- Implemented advanced hook management
+
+fixes
+-----
+
+- fixed file browser bug, when switching into given form revision the url was 
+  not changing
+- fixed propagation to error controller on simplehg and simplegit middlewares
+- fixed error when trying to make a download on empty repository
+- fixed problem with '[' chars in commit messages in journal
+- fixed #99 Unicode errors, on file node paths with non utf-8 characters
+- journal fork fixes
+- removed issue with space inside renamed repository after deletion
+- fixed strange issue on formencode imports
+- fixed #126 Deleting repository on Windows, rename used incompatible chars. 
+- #150 fixes for errors on repositories mapped in db but corrupted in 
+  filesystem
+- fixed problem with ascendant characters in realm #181
+- fixed problem with sqlite file based database connection pool
+- whoosh indexer and code stats share the same dynamic extensions map
+- fixes #188 - relationship delete of repo_to_perm entry on user removal
+- fixes issue #189 Trending source files shows "show more" when no more exist
+- fixes issue #197 Relative paths for pidlocks
+- fixes issue #198 password will require only 3 chars now for login form
+- fixes issue #199 wrong redirection for non admin users after creating a repository
+- fixes issues #202, bad db constraint made impossible to attach same group 
+  more than one time. Affects only mysql/postgres
+- fixes #218 os.kill patch for windows was missing sig param
+- improved rendering of dag (they are not trimmed anymore when number of 
+  heads exceeds 5)
+    
 1.1.8 (**2011-04-12**)
 ======================
 
@@ -34,6 +106,7 @@
   Thomas Waldmann
 - fixed issue #166 summary pager was skipping 10 revisions on second page
 
+
 1.1.7 (**2011-03-23**)
 ======================
 
@@ -93,7 +166,6 @@
 - journal fixes
 - fixed option to access repository just by entering http://server/<repo_name> 
 
-
 1.1.3 (**2011-02-16**)
 ======================
 
--- a/docs/enable_git.rst	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-.. _enable_git:
-
-Enabling GIT support (beta)
-===========================
-
-
-Git support in RhodeCode 1.1 was disabled due to current instability issues. However,
-if you would like to test git support please feel free to re-enable it. To re-enable GIT support just
-uncomment the git line in the file rhodecode/__init__.py
-
-.. code-block:: python
- 
-   BACKENDS = {
-       'hg': 'Mercurial repository',
-       #'git': 'Git repository',
-   }
-
-.. note::
-   Please note that the git support provided by RhodeCode is not yet fully
-   stable and RhodeCode might crash while using git repositories. (That is why
-   it is currently disabled.) Thus be careful about enabling git support, and
-   certainly don't use it in a production setting!
\ No newline at end of file
--- a/docs/index.rst	Thu May 12 19:50:48 2011 +0200
+++ b/docs/index.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -19,8 +19,11 @@
 .. toctree::
    :maxdepth: 1
 
-   enable_git
-   statistics
+   usage/general
+   usage/enable_git
+   usage/statistics
+   usage/backup
+   usage/api_key_access
    
 **Develop**
 
--- a/docs/installation.rst	Thu May 12 19:50:48 2011 +0200
+++ b/docs/installation.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -3,19 +3,12 @@
 Installation
 ============
 
-``RhodeCode`` is written entirely in Python. In order to gain maximum performance
-there are some third-party you must install. When RhodeCode is used 
-together with celery you have to install some kind of message broker,
-recommended one is rabbitmq_ to make the async tasks work.
+``RhodeCode`` is written entirely in Python. Before posting any issues make 
+sure, your not missing any system libraries and using right version of 
+libraries required by RhodeCode. There's also restriction in terms of mercurial
+clients. Minimal version of hg client known working fine with RhodeCode is
+**1.6**. If you're using older client, please upgrade.
 
-Of course RhodeCode works in sync mode also and then you do not have to install
-any third party applications. However, using Celery_ will give you a large 
-speed improvement when using many big repositories. If you plan to use 
-RhodeCode for say 7 to 10 small repositories, RhodeCode will perform perfectly 
-well without celery running.
-   
-If you make the decision to run RhodeCode with celery make sure you run 
-celeryd using paster and message broker together with the application.   
 
 Installing RhodeCode from Cheese Shop
 -------------------------------------
@@ -40,7 +33,12 @@
 ---------------------------------
 
 
-- Assuming you have installed virtualenv_ create a new virtual environment using virtualenv:: 
+For installing RhodeCode i highly recommend using separate virtualenv_. This
+way many required by RhodeCode libraries will remain sandboxed from your main
+python and making things less problematic when doing system python updates. 
+
+- Assuming you have installed virtualenv_ create a new virtual environment 
+  using virtualenv command:: 
 
     virtualenv --no-site-packages /var/www/rhodecode-venv
 
@@ -64,21 +62,40 @@
    ``virtualenv`` script.  It's perfectly acceptable (and desirable)
    to create a virtualenv as a normal user.
      
-- Make a folder for rhodecode somewhere on the filesystem for example::
+- Make a folder for rhodecode data files, and configuration somewhere on the 
+  filesystem. For example::
 
     mkdir /var/www/rhodecode
   
     
-- Run this command to install rhodecode::
+- Go into the created directory run this command to install rhodecode::
 
-    easy_install rhodecode 
+    easy_install rhodecode
+  
+  or::
+ 
+    pip install rhodecode 
 
-- This will install rhodecode together with pylons and all other required python
-  libraries
+- This will install rhodecode together with pylons and all other required 
+  python libraries into activated virtualenv
 
 Requirements for Celery (optional)
 ----------------------------------
 
+In order to gain maximum performance
+there are some third-party you must install. When RhodeCode is used 
+together with celery you have to install some kind of message broker,
+recommended one is rabbitmq_ to make the async tasks work.
+
+Of course RhodeCode works in sync mode also and then you do not have to install
+any third party applications. However, using Celery_ will give you a large 
+speed improvement when using many big repositories. If you plan to use 
+RhodeCode for say 7 to 10 repositories, RhodeCode will perform perfectly well 
+without celery running.
+   
+If you make the decision to run RhodeCode with celery make sure you run 
+celeryd using paster and message broker together with the application. 
+
 .. note::
    Installing message broker and using celery is optional, RhodeCode will
    work perfectly fine without them.
--- a/docs/setup.rst	Thu May 12 19:50:48 2011 +0200
+++ b/docs/setup.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -5,16 +5,17 @@
 
 
 Setting up RhodeCode
---------------------------
+--------------------
 
-First, you will need to create a RhodeCode configuration file. Run the following
-command to do this::
+First, you will need to create a RhodeCode configuration file. Run the 
+following command to do this::
  
     paster make-config RhodeCode production.ini
 
 - This will create the file `production.ini` in the current directory. This
-  configuration file contains the various settings for RhodeCode, e.g proxy port,
-  email settings, usage of static files, cache, celery settings and logging.
+  configuration file contains the various settings for RhodeCode, e.g proxy 
+  port, email settings, usage of static files, cache, celery settings and 
+  logging.
 
 
 Next, you need to create the databases used by RhodeCode. I recommend that you
@@ -27,19 +28,19 @@
 
 This will prompt you for a "root" path. This "root" path is the location where
 RhodeCode will store all of its repositories on the current machine. After
-entering this "root" path ``setup-app`` will also prompt you for a username and password
-for the initial admin account which ``setup-app`` sets up for you.
+entering this "root" path ``setup-app`` will also prompt you for a username 
+and password for the initial admin account which ``setup-app`` sets up for you.
 
 - The ``setup-app`` command will create all of the needed tables and an admin
-  account. When choosing a root path you can either use a new empty location, or a
-  location which already contains existing repositories. If you choose a location
-  which contains existing repositories RhodeCode will simply add all of the
-  repositories at the chosen location to it's database. (Note: make sure you
-  specify the correct path to the root).
+  account. When choosing a root path you can either use a new empty location, 
+  or a location which already contains existing repositories. If you choose a 
+  location which contains existing repositories RhodeCode will simply add all 
+  of the repositories at the chosen location to it's database. (Note: make 
+  sure you specify the correct path to the root).
 - Note: the given path for mercurial_ repositories **must** be write accessible
-  for the application. It's very important since the RhodeCode web interface will
-  work without write access, but when trying to do a push it will eventually fail
-  with permission denied errors unless it has write access.
+  for the application. It's very important since the RhodeCode web interface 
+  will work without write access, but when trying to do a push it will 
+  eventually fail with permission denied errors unless it has write access.
 
 You are now ready to use RhodeCode, to run it simply execute::
  
@@ -48,7 +49,8 @@
 - This command runs the RhodeCode server. The web app should be available at the 
   127.0.0.1:5000. This ip and port is configurable via the production.ini 
   file created in previous step
-- Use the admin account you created above when running ``setup-app`` to login to the web app.
+- Use the admin account you created above when running ``setup-app`` to login 
+  to the web app.
 - The default permissions on each repository is read, and the owner is admin. 
   Remember to update these if needed.
 - In the admin panel you can toggle ldap, anonymous, permissions settings. As
@@ -56,9 +58,9 @@
 
 Try copying your own mercurial repository into the "root" directory you are
 using, then from within the RhodeCode web application choose Admin >
-repositories. Then choose Add New Repository. Add the repository you copied into
-the root. Test that you can browse your repository from within RhodeCode and then
-try cloning your repository from RhodeCode with::
+repositories. Then choose Add New Repository. Add the repository you copied 
+into the root. Test that you can browse your repository from within RhodeCode 
+and then try cloning your repository from RhodeCode with::
 
     hg clone http://127.0.0.1:5000/<repository name>
 
@@ -67,8 +69,8 @@
 Using RhodeCode with SSH
 ------------------------
 
-RhodeCode currently only hosts repositories using http and https. (The addition of
-ssh hosting is a planned future feature.) However you can easily use ssh in
+RhodeCode currently only hosts repositories using http and https. (The addition
+of ssh hosting is a planned future feature.) However you can easily use ssh in
 parallel with RhodeCode. (Repository access via ssh is a standard "out of
 the box" feature of mercurial_ and you can use this to access any of the
 repositories that RhodeCode is hosting. See PublishingRepositories_)
@@ -77,10 +79,10 @@
 as the project. When using repository groups, each group is a subdirectory.
 This allows you to easily use ssh for accessing repositories.
 
-In order to use ssh you need to make sure that your web-server and the users login
-accounts have the correct permissions set on the appropriate directories. (Note
-that these permissions are independent of any permissions you have set up using
-the RhodeCode web interface.)
+In order to use ssh you need to make sure that your web-server and the users 
+login accounts have the correct permissions set on the appropriate directories.
+(Note that these permissions are independent of any permissions you have set up
+using the RhodeCode web interface.)
 
 If your main directory (the same as set in RhodeCode settings) is for example
 set to **/home/hg** and the repository you are using is named `rhodecode`, then
@@ -95,35 +97,41 @@
 permissions as set up via the RhodeCode web interface, you can create an
 authentication hook to connect to the rhodecode db and runs check functions for
 permissions against that.
-
-
     
 Setting up Whoosh full text search
 ----------------------------------
 
 Starting from version 1.1 the whoosh index can be build by using the paster
 command ``make-index``. To use ``make-index`` you must specify the configuration
-file that stores the location of the index, and the location of the repositories
-(`--repo-location`).
+file that stores the location of the index. You may specify the location of the 
+repositories (`--repo-location`).  If not specified, this value is retrieved 
+from the RhodeCode database.  This was required prior to 1.2.  Starting from 
+version 1.2 it is also possible to specify a comma separated list of 
+repositories (`--index-only`) to build index only on chooses repositories 
+skipping any other found in repos location
 
 You may optionally pass the option `-f` to enable a full index rebuild. Without
 the `-f` option, indexing will run always in "incremental" mode.
 
 For an incremental index build use::
 
-	paster make-index production.ini --repo-location=<location for repos> 
+	paster make-index production.ini 
 
 For a full index rebuild use::
 
-	paster make-index production.ini -f --repo-location=<location for repos>
+	paster make-index production.ini -f 
+
 
-- For full text search you can either put crontab entry for
+building index just for chosen repositories is possible with such command::
+ 
+ paster make-index production.ini --index-only=vcs,rhodecode
+
 
 In order to do periodical index builds and keep your index always up to date.
 It's recommended to do a crontab entry for incremental indexing. 
 An example entry might look like this::
  
- /path/to/python/bin/paster /path/to/rhodecode/production.ini --repo-location=<location for repos> 
+    /path/to/python/bin/paster make-index /path/to/rhodecode/production.ini 
   
 When using incremental mode (the default) whoosh will check the last
 modification date of each file and add it to be reindexed if a newer file is
@@ -138,55 +146,221 @@
 -----------------------
 
 RhodeCode starting from version 1.1 supports ldap authentication. In order
-to use LDAP, you have to install the python-ldap_ package. This package is available
-via pypi, so you can install it by running
+to use LDAP, you have to install the python-ldap_ package. This package is 
+available via pypi, so you can install it by running
 
-::
+using easy_install::
 
- easy_install python-ldap
+    easy_install python-ldap
  
-::
+using pip::
 
- pip install python-ldap
+    pip install python-ldap
 
 .. note::
    python-ldap requires some certain libs on your system, so before installing 
    it check that you have at least `openldap`, and `sasl` libraries.
 
-ldap settings are located in admin->ldap section,
+LDAP settings are located in admin->ldap section,
 
 Here's a typical ldap setup::
 
- Enable ldap  = checked                 #controls if ldap access is enabled
- Host         = host.domain.org         #actual ldap server to connect
- Port         = 389 or 689 for ldaps    #ldap server ports
- Enable LDAPS = unchecked               #enable disable ldaps
- Account      = <account>               #access for ldap server(if required)
- Password     = <password>              #password for ldap server(if required)
- Base DN      = uid=%(user)s,CN=users,DC=host,DC=domain,DC=org
- 
+ Connection settings
+ Enable LDAP          = checked
+ Host                 = host.example.org
+ Port                 = 389
+ Account              = <account>
+ Password             = <password>
+ Connection Security  = LDAPS connection
+ Certificate Checks   = DEMAND
+
+ Search settings
+ Base DN              = CN=users,DC=host,DC=example,DC=org
+ LDAP Filter          = (&(objectClass=user)(!(objectClass=computer)))
+ LDAP Search Scope    = SUBTREE
+
+ Attribute mappings
+ Login Attribute      = uid
+ First Name Attribute = firstName
+ Last Name Attribute  = lastName
+ E-mail Attribute     = mail
+
+.. _enable_ldap:
+
+Enable LDAP : required
+    Whether to use LDAP for authenticating users.
+
+.. _ldap_host:
+
+Host : required
+    LDAP server hostname or IP address.
+
+.. _Port:
+
+Port : required
+    389 for un-encrypted LDAP, 636 for SSL-encrypted LDAP.
+
+.. _ldap_account:
+
+Account : optional
+    Only required if the LDAP server does not allow anonymous browsing of
+    records.  This should be a special account for record browsing.  This
+    will require `LDAP Password`_ below.
+
+.. _LDAP Password:
+
+Password : optional
+    Only required if the LDAP server does not allow anonymous browsing of
+    records.
 
-`Account` and `Password` are optional, and used for two-phase ldap 
-authentication so those are credentials to access your ldap, if it doesn't 
-support anonymous search/user lookups. 
+.. _Enable LDAPS:
+
+Connection Security : required
+    Defines the connection to LDAP server
+
+    No encryption
+        Plain non encrypted connection
+        
+    LDAPS connection
+        Enable ldaps connection. It will likely require `Port`_ to be set to 
+        a different value (standard LDAPS port is 636). When LDAPS is enabled 
+        then `Certificate Checks`_ is required.
+        
+    START_TLS on LDAP connection
+        START TLS connection
+
+.. _Certificate Checks:
+
+Certificate Checks : optional
+    How SSL certificates verification is handled - this is only useful when
+    `Enable LDAPS`_ is enabled.  Only DEMAND or HARD offer full SSL security 
+    while the other options are susceptible to man-in-the-middle attacks.  SSL
+    certificates can be installed to /etc/openldap/cacerts so that the
+    DEMAND or HARD options can be used with self-signed certificates or
+    certificates that do not have traceable certificates of authority.
+
+    NEVER
+        A serve certificate will never be requested or checked.
+
+    ALLOW
+        A server certificate is requested.  Failure to provide a
+        certificate or providing a bad certificate will not terminate the
+        session.
+
+    TRY
+        A server certificate is requested.  Failure to provide a
+        certificate does not halt the session; providing a bad certificate
+        halts the session.
+
+    DEMAND
+        A server certificate is requested and must be provided and
+        authenticated for the session to proceed.
+
+    HARD
+        The same as DEMAND.
+
+.. _Base DN:
 
-Base DN must have the %(user)s template inside, it's a place holder where your uid
-used to login would go. It allows admins to specify non-standard schema for the
-uid variable.
+Base DN : required
+    The Distinguished Name (DN) where searches for users will be performed.
+    Searches can be controlled by `LDAP Filter`_ and `LDAP Search Scope`_.
+
+.. _LDAP Filter:
+
+LDAP Filter : optional
+    A LDAP filter defined by RFC 2254.  This is more useful when `LDAP
+    Search Scope`_ is set to SUBTREE.  The filter is useful for limiting
+    which LDAP objects are identified as representing Users for
+    authentication.  The filter is augmented by `Login Attribute`_ below.
+    This can commonly be left blank.
+
+.. _LDAP Search Scope:
+
+LDAP Search Scope : required
+    This limits how far LDAP will search for a matching object.
+
+    BASE
+        Only allows searching of `Base DN`_ and is usually not what you
+        want.
+
+    ONELEVEL
+        Searches all entries under `Base DN`_, but not Base DN itself.
+
+    SUBTREE
+        Searches all entries below `Base DN`_, but not Base DN itself.
+        When using SUBTREE `LDAP Filter`_ is useful to limit object
+        location.
+
+.. _Login Attribute:
+
+Login Attribute : required        
+    The LDAP record attribute that will be matched as the USERNAME or
+    ACCOUNT used to connect to RhodeCode.  This will be added to `LDAP
+    Filter`_ for locating the User object.  If `LDAP Filter`_ is specified as
+    "LDAPFILTER", `Login Attribute`_ is specified as "uid" and the user has
+    connected as "jsmith" then the `LDAP Filter`_ will be augmented as below
+    ::
+
+        (&(LDAPFILTER)(uid=jsmith))
+
+.. _ldap_attr_firstname:
+
+First Name Attribute : required
+    The LDAP record attribute which represents the user's first name.
+
+.. _ldap_attr_lastname:
 
-If all of the data is correctly entered, and `python-ldap` is properly
-installed, then users should be granted access to RhodeCode with ldap accounts.
-When logging in the first time a special ldap account is created inside
-RhodeCode, so you can control the permissions even on ldap users. If such users
-already exist in the RhodeCode database, then the ldap user with the same
-username would be not be able to access RhodeCode.
+Last Name Attribute : required
+    The LDAP record attribute which represents the user's last name.
+
+.. _ldap_attr_email:
+
+Email Attribute : required
+    The LDAP record attribute which represents the user's email address.
+
+If all data are entered correctly, and python-ldap_ is properly installed
+users should be granted access to RhodeCode with ldap accounts.  At this
+time user information is copied from LDAP into the RhodeCode user database.
+This means that updates of an LDAP user object may not be reflected as a
+user update in RhodeCode.
+
+If You have problems with LDAP access and believe You entered correct
+information check out the RhodeCode logs, any error messages sent from LDAP
+will be saved there.
+
+Active Directory
+''''''''''''''''
 
-If you have problems with ldap access and believe you have correctly entered the
-required information then proceed by investigating the RhodeCode logs. Any
-error messages sent from ldap will be saved there.
+RhodeCode can use Microsoft Active Directory for user authentication.  This
+is done through an LDAP or LDAPS connection to Active Directory.  The
+following LDAP configuration settings are typical for using Active
+Directory ::
+
+ Base DN              = OU=SBSUsers,OU=Users,OU=MyBusiness,DC=v3sys,DC=local
+ Login Attribute      = sAMAccountName
+ First Name Attribute = givenName
+ Last Name Attribute  = sn
+ E-mail Attribute     = mail
+
+All other LDAP settings will likely be site-specific and should be
+appropriately configured.
 
 
 
+Hook management
+---------------
+
+Hooks can be managed in similar way to this used in .hgrc files.
+To access hooks setting click `advanced setup` on Hooks section of Mercurial
+Settings in Admin. 
+
+There are 4 built in hooks that cannot be changed (only enable/disable by
+checkboxes on previos section).
+To add another custom hook simply fill in first section with 
+<name>.<hook_type> and the second one with hook path. Example hooks
+can be found at *rhodecode.lib.hooks*. 
+
+
 Setting Up Celery
 -----------------
 
@@ -204,8 +378,8 @@
 
 
 .. note::
-   Make sure you run this command from the same virtualenv, and with the same user
-   that rhodecode runs.
+   Make sure you run this command from the same virtualenv, and with the same 
+   user that rhodecode runs.
    
 HTTPS support
 -------------
@@ -214,8 +388,8 @@
 
 - Set HTTP_X_URL_SCHEME in your http server headers, than rhodecode will
   recognize this headers and make proper https redirections
-- Alternatively, set `force_https = true` in the ini configuration to force using
-  https, no headers are needed than to enable https
+- Alternatively, change the `force_https = true` flag in the ini configuration 
+  to force using https, no headers are needed than to enable https
 
 
 Nginx virtual host example
@@ -251,13 +425,10 @@
     client_max_body_size        400m;
     client_body_buffer_size     128k;
     proxy_buffering             off;
-    proxy_connect_timeout       3600;
-    proxy_send_timeout          3600;
-    proxy_read_timeout          3600;
-    proxy_buffer_size           16k;
-    proxy_buffers               4 16k;
-    proxy_busy_buffers_size     64k;
-    proxy_temp_file_write_size  64k;
+    proxy_connect_timeout       7200;
+    proxy_send_timeout          7200;
+    proxy_read_timeout          7200;
+    proxy_buffers               8 32k;
  
 Also, when using root path with nginx you might set the static files to false
 in the production.ini file::
@@ -315,7 +486,8 @@
       SetEnvIf X-Url-Scheme https HTTPS=1
     </Location> 
 
-Besides the regular apache setup you will need to add the following to your .ini file::
+Besides the regular apache setup you will need to add the following line
+into [app:main] section of your .ini file::
 
     filter-with = proxy-prefix
 
@@ -328,59 +500,24 @@
 
 then change <someprefix> into your choosen prefix
 
-Apache's example WSGI+SSL config
---------------------------------
-
-virtual host example::
-
-    <VirtualHost *:443>
-        ServerName hg.domain.eu:443
-        DocumentRoot /var/www
-    
-        SSLEngine on
-        SSLCertificateFile /etc/apache2/ssl/hg.domain.eu.cert
-        SSLCertificateKeyFile /etc/apache2/ssl/hg.domain.eu.key
-        SSLCertificateChainFile /etc/apache2/ssl/ca.cert
-        SetEnv HTTP_X_URL_SCHEME https
-    
-        Alias /css /home/web/virtualenvs/hg/lib/python2.6/site-packages/rhodecode/public/css
-        Alias /images /home/web/virtualenvs/hg/lib/python2.6/site-packages/rhodecode/public/images
-        Alias /js /home/web/virtualenvs/hg/lib/python2.6/site-packages/rhodecode/public/js
-    
-        WSGIDaemonProcess hg user=web group=web processes=1 threads=10 display-name=%{GROUP} python-path=/home/web/virtualenvs/hg/lib/python2.6/site-packages
-    
-        WSGIPassAuthorization On
-        WSGIProcessGroup hg
-        WSGIApplicationGroup hg
-        WSGIScriptAlias / /home/web/apache/conf/hg.wsgi
-    
-        <Directory /home/web/apache/conf>
-            Order deny,allow
-            Allow from all
-        </Directory>
-        <Directory /var/www>
-            Order deny,allow
-            Allow from all
-        </Directory>
-    
-    </VirtualHost>
-
-    <VirtualHost *:80>
-        ServerName hg.domain.eu
-        Redirect permanent / https://hg.domain.eu/
-    </VirtualHost>
+Apache's WSGI config
+--------------------
 
 
-HG.WSGI::
+Example wsgi dispatch script::
 
     import os
     os.environ["HGENCODING"] = "UTF-8"
+    os.environ['PYTHON_EGG_CACHE'] = '/home/web/rhodecode/.egg-cache'
+    
+    # sometimes it's needed to set the curent dir
+    os.chdir('/home/web/rhodecode/') 
     
     from paste.deploy import loadapp
     from paste.script.util.logging_config import fileConfig
-    
-    fileConfig('/home/web/virtualenvs/hg/config/production.ini')
-    application = loadapp('config:/home/web/virtualenvs/hg/config/production.ini'
+
+    fileConfig('/home/web/rhodecode/production.ini')
+    application = loadapp('config:/home/web/rhodecode/production.ini')
 
 
 Other configuration files
@@ -421,7 +558,8 @@
 :Q: **Apache doesn't pass basicAuth on pull/push?**
 :A: Make sure you added `WSGIPassAuthorization true`.
 
-For further questions search the `Issues tracker`_, or post a message in the `google group rhodecode`_
+For further questions search the `Issues tracker`_, or post a message in the 
+`google group rhodecode`_
 
 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
 .. _python: http://www.python.org/
--- a/docs/statistics.rst	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-.. _statistics:
-
-
-Statistics
-==========
-
-The RhodeCode statistics system makes heavy demands of the server resources, so
-in order to keep a balance between usability and performance, the statistics are
-cached inside db and are gathered incrementally, this is how RhodeCode does
-this:
-
-With Celery disabled
-++++++++++++++++++++
-
-- On each first visit to the summary page a set of 250 commits are parsed and
-  updates statistics cache.
-- This happens on each single visit to the statistics page until all commits are
-  fetched. Statistics are kept cached until additional commits are added to the
-  repository. In such a case RhodeCode will only fetch the new commits when
-  updating it's cache.
-
-
-With Celery enabled
-+++++++++++++++++++
-
-- On the first visit to the summary page RhodeCode will create tasks that will
-  execute on celery workers. This task will gather all of the stats until all
-  commits are parsed, each task will parse 250 commits, and run the next task to
-  parse next 250 commits, until all of the commits are parsed.
-
-.. note::
-   At any time you can disable statistics on each repository via the repository
-   edit form in the admin panel. To do this just uncheck the statistics checkbox.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/usage/api_key_access.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,11 @@
+.. _api_key_access:
+
+Access to RhodeCode via API KEY
+===============================
+
+Starting from version 1.2 rss/atom feeds and journal feeds
+can be accessed via **api_key**. This unique key is automatically generated for
+each user in RhodeCode application. Using this key it is possible to access 
+feeds without having to log in. When user changes his password a new API KEY
+is generated for him automatically. You can check your API KEY in account 
+settings page. 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/usage/backup.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,25 @@
+.. _backup:
+
+Backing up RhodeCode
+====================
+
+
+Settings
+--------
+
+Just copy your .ini file, it contains all RhodeCode settings.
+
+Whoosh index
+------------
+
+Whoosh index is located in **/data/index** directory where you installed
+RhodeCode ie. the same place where the ini file is located
+
+
+Database
+--------
+
+When using sqlite just copy rhodecode.db.
+Any other database engine requires a manual backup operation.
+
+Database backup will contain all gathered statistics
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/usage/enable_git.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,24 @@
+.. _enable_git:
+
+Enabling GIT support (beta)
+===========================
+
+
+Git support in RhodeCode 1.1 was disabled due to current instability issues. 
+However,if you would like to test git support please feel free to re-enable it. 
+To re-enable GIT support just uncomment the git line in the 
+file **rhodecode/__init__.py**
+
+.. code-block:: python
+ 
+   BACKENDS = {
+       'hg': 'Mercurial repository',
+       #'git': 'Git repository',
+   }
+
+.. note::
+   Please note that the git support provided by RhodeCode is not yet fully
+   stable and RhodeCode might crash while using git repositories. (That is why
+   it is currently disabled.) Thus be careful about enabling git support, and
+   certainly don't use it in a production setting!
+   
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/usage/general.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,54 @@
+.. _general:
+
+General RhodeCode usage
+=======================
+
+
+Repository deleting
+-------------------
+
+Currently when admin/owner deletes a repository, RhodeCode does not physically
+delete a repository from filesystem, it renames it in a special way so it's
+not possible to push,clone or access repository. It's worth a notice that,
+even if someone will be given administrative access to RhodeCode and will 
+delete a repository You can easy restore such action by restoring `rm__<date>`
+from the repository name, and internal repository storage (.hg/.git)
+
+Follow current branch in file view
+----------------------------------
+
+In file view when this checkbox is checked the << and >> arrows will jump
+to changesets within the same branch currently viewing. So for example
+if someone is viewing files at 'beta' branch and marks `follow current branch`
+checkbox the << and >> buttons will only show him revisions for 'beta' branch
+
+
+Compare view from changelog
+---------------------------
+
+Checkboxes in compare view allow users to view combined compare view. You can
+only show the range between the first and last checkbox (no cherry pick).
+Clicking more than one checkbox will activate a link in top saying
+`Show selected changes <from-rev> -> <to-rev>` clicking this will bring
+compare view
+
+Compare view is also available from the journal on pushes having more than
+one changeset
+
+
+
+Mailing
+-------
+
+When administrator will fill up the mailing settings in .ini files
+RhodeCode will send mails on user registration, or when RhodeCode errors occur
+on errors the mails will have a detailed traceback of error.
+
+
+Trending source files
+---------------------
+
+Trending source files are calculated based on pre defined dict of known
+types and extensions. If You miss some extension or Would like to scan some
+custom files it's possible to add new types in `LANGUAGES_EXTENSIONS_MAP` dict
+located in `/rhodecode/lib/celerylib/tasks.py`
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/usage/statistics.rst	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,33 @@
+.. _statistics:
+
+
+Statistics
+==========
+
+The RhodeCode statistics system makes heavy demands of the server resources, so
+in order to keep a balance between usability and performance, the statistics are
+cached inside db and are gathered incrementally, this is how RhodeCode does
+this:
+
+With Celery disabled
+--------------------
+
+- On each first visit to the summary page a set of 250 commits are parsed and
+  updates statistics cache.
+- This happens on each single visit to the statistics page until all commits are
+  fetched. Statistics are kept cached until additional commits are added to the
+  repository. In such a case RhodeCode will only fetch the new commits when
+  updating it's cache.
+
+
+With Celery enabled
+-------------------
+
+- On the first visit to the summary page RhodeCode will create tasks that will
+  execute on celery workers. This task will gather all of the stats until all
+  commits are parsed, each task will parse 250 commits, and run the next task to
+  parse next 250 commits, until all of the commits are parsed.
+
+.. note::
+   At any time you can disable statistics on each repository via the repository
+   edit form in the admin panel. To do this just uncheck the statistics checkbox.
--- a/ez_setup.py	Thu May 12 19:50:48 2011 +0200
+++ b/ez_setup.py	Fri Oct 07 01:08:50 2011 +0200
@@ -202,14 +202,13 @@
         except ImportError:
             from easy_install import main
         main(list(argv) + [download_setuptools(delay=0)])
-        sys.exit(0)  # try to force an exit
+        sys.exit(0) # try to force an exit
     else:
         if argv:
             from setuptools.command.easy_install import main
             main(argv)
         else:
-            print "Setuptools version", version, ("or greater has "
-                                                  "been installed.")
+            print "Setuptools version", version, "or greater has been installed."
             print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
 
 
--- a/init.d/rhodecode-daemon2	Thu May 12 19:50:48 2011 +0200
+++ b/init.d/rhodecode-daemon2	Fri Oct 07 01:08:50 2011 +0200
@@ -1,6 +1,6 @@
 #!/bin/sh -e
 ########################################
-#### THIS IS AN DEBIAN INIT.D SCRIPT####
+#### THIS IS A DEBIAN INIT.D SCRIPT ####
 ########################################
 
 ### BEGIN INIT INFO
@@ -29,49 +29,48 @@
 DAEMON="$PYTHON_PATH/bin/paster"
 
 DAEMON_OPTS="serve --daemon \
---user=$RUN_AS \
---group=$RUN_AS \
---pid-file=$PID_PATH \
---log-file=$LOG_PATH  $APP_PATH/$CONF_NAME"
+  --user=$RUN_AS \
+  --group=$RUN_AS \
+  --pid-file=$PID_PATH \
+  --log-file=$LOG_PATH  $APP_PATH/$CONF_NAME"
+
 
+start() {
+  echo "Starting $APP_NAME"
+  PYTHON_EGG_CACHE="/tmp" start-stop-daemon -d $APP_PATH \
+      --start --quiet \
+      --pidfile $PID_PATH \
+      --user $RUN_AS \
+      --exec $DAEMON -- $DAEMON_OPTS
+}
+
+stop() {
+  echo "Stopping $APP_NAME"
+  start-stop-daemon -d $APP_PATH \
+      --stop --quiet \
+      --pidfile $PID_PATH || echo "$APP_NAME - Not running!"
+  
+  if [ -f $PID_PATH ]; then
+    rm $PID_PATH
+  fi
+}
 
 case "$1" in
   start)
-    echo "Starting $APP_NAME"
-    start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \
-        --start --quiet \
-        --pidfile $PID_PATH \
-        --user $RUN_AS \
-        --exec $DAEMON -- $DAEMON_OPTS
+    start
     ;;
   stop)
-    echo "Stopping $APP_NAME"
-    start-stop-daemon -d $APP_PATH \
-        --stop --quiet \
-        --pidfile $PID_PATH || echo "$APP_NAME - Not running!"
-    if [ -f $PID_PATH ]; then
-        rm $PID_PATH
-    fi
+    stop
     ;;
   restart)
     echo "Restarting $APP_NAME"
     ### stop ###
-    echo "Stopping $APP_NAME"
-    start-stop-daemon -d $APP_PATH \
-        --stop --quiet \
-        --pidfile $PID_PATH || echo "$APP_NAME - Not running!"
-    if [ -f $PID_PATH ]; then
-        rm $PID_PATH
-    fi
+    stop
+    wait
     ### start ###
-    echo "Starting $APP_NAME"
-    start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \
-        --start --quiet \
-        --pidfile $PID_PATH \
-        --user $RUN_AS \
-        --exec $DAEMON -- $DAEMON_OPTS
+    start
     ;;
   *)
     echo "Usage: $0 {start|stop|restart}"
     exit 1
-esac
\ No newline at end of file
+esac
--- a/production.ini	Thu May 12 19:50:48 2011 +0200
+++ b/production.ini	Fri Oct 07 01:08:50 2011 +0200
@@ -7,6 +7,7 @@
 
 [DEFAULT]
 debug = true
+pdebug = false
 ################################################################################
 ## Uncomment and replace with the address which should receive                ## 
 ## any error reports after application crash                                  ##
@@ -29,7 +30,7 @@
 threadpool_workers = 5
 
 ##max request before thread respawn
-threadpool_max_requests = 2
+threadpool_max_requests = 10
 
 ##option to use threads of process
 use_threadpool = true
@@ -41,12 +42,15 @@
 [app:main]
 use = egg:rhodecode
 full_stack = true
-static_files = false
+static_files = true
 lang=en
 cache_dir = %(here)s/data
 index_dir = %(here)s/data/index
+app_instance_uuid = prod1234
 cut_off_limit = 256000
-force_https = false
+force_https = false 
+commit_parse_limit = 50
+use_gravatar = true
 
 ####################################
 ###        CELERY CONFIG        ####
@@ -70,7 +74,7 @@
 celeryd.concurrency = 2
 #celeryd.log.file = celeryd.log
 celeryd.log.level = debug
-celeryd.max.tasks.per.child = 3
+celeryd.max.tasks.per.child = 1
 
 #tasks will never be sent to the queue, but executed locally instead.
 celery.always.eager = false
@@ -92,9 +96,8 @@
 beaker.cache.long_term.type=memory
 beaker.cache.long_term.expire=36000
 
-
 beaker.cache.sql_cache_short.type=memory
-beaker.cache.sql_cache_short.expire=5
+beaker.cache.sql_cache_short.expire=10
 
 beaker.cache.sql_cache_med.type=memory
 beaker.cache.sql_cache_med.expire=360
@@ -139,9 +142,10 @@
 #########################################################
 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 #########################################################
-sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
-#sqlalchemy.db1.echo = False
-#sqlalchemy.db1.pool_recycle = 3600
+#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
+sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
+sqlalchemy.db1.echo = false
+sqlalchemy.db1.pool_recycle = 3600
 sqlalchemy.convert_unicode = true
 
 ################################
@@ -202,13 +206,13 @@
 class = StreamHandler
 args = (sys.stderr,)
 level = INFO
-formatter = color_formatter
+formatter = generic
 
 [handler_console_sql]
 class = StreamHandler
 args = (sys.stderr,)
 level = WARN
-formatter = color_formatter_sql
+formatter = generic
 
 ################
 ## FORMATTERS ##
--- a/rhodecode/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -25,14 +25,14 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import platform
 
-VERSION = (1, 1, 8)
+VERSION = (1, 2, 0)
 __version__ = '.'.join((str(each) for each in VERSION[:4]))
-__dbversion__ = 2  # defines current db version for migrations
+__dbversion__ = 3 #defines current db version for migrations
 __platform__ = platform.system()
 __license__ = 'GPLv3'
 
 PLATFORM_WIN = ('Windows')
-PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD')
+PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD', 'SunOS')
 
 try:
     from rhodecode.lib.utils import get_current_revision
--- a/rhodecode/config/deployment.ini_tmpl	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/config/deployment.ini_tmpl	Fri Oct 07 01:08:50 2011 +0200
@@ -7,6 +7,7 @@
 
 [DEFAULT]
 debug = true
+pdebug = false
 ################################################################################
 ## Uncomment and replace with the address which should receive                ## 
 ## any error reports after application crash                                  ##
@@ -48,6 +49,8 @@
 app_instance_uuid = ${app_instance_uuid}
 cut_off_limit = 256000
 force_https = false 
+commit_parse_limit = 50
+use_gravatar = true
 
 ####################################
 ###        CELERY CONFIG        ####
@@ -139,58 +142,68 @@
 #########################################################
 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 #########################################################
+
+# SQLITE [default]
 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
-#sqlalchemy.db1.echo = False
-#sqlalchemy.db1.pool_recycle = 3600
+ 
+# POSTGRES
+# sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
+
+# MySQL
+# sqlalchemy.db1.url = mysql://user:pass@localhost/rhodecode
+
+
+sqlalchemy.db1.echo = false
+sqlalchemy.db1.pool_recycle = 3600
 sqlalchemy.convert_unicode = true
 
 ################################
 ### LOGGING CONFIGURATION   ####
 ################################
 [loggers]
-keys = root, routes, rhodecode, sqlalchemy,beaker,templates
+keys = root, routes, rhodecode, sqlalchemy, beaker, templates
 
 [handlers]
-keys = console
+keys = console, console_sql
 
 [formatters]
-keys = generic,color_formatter
+keys = generic, color_formatter, color_formatter_sql
 
 #############
 ## LOGGERS ##
 #############
 [logger_root]
-level = INFO
+level = NOTSET
 handlers = console
 
 [logger_routes]
-level = INFO
-handlers = console
+level = DEBUG
+handlers = 
 qualname = routes.middleware
 # "level = DEBUG" logs the route matched and routing variables.
-propagate = 0
+propagate = 1
 
 [logger_beaker]
-level = ERROR
-handlers = console
+level = DEBUG
+handlers = 
 qualname = beaker.container
-propagate = 0
+propagate = 1
 
 [logger_templates]
 level = INFO
-handlers = console
+handlers = 
 qualname = pylons.templating
-propagate = 0
+propagate = 1
 
 [logger_rhodecode]
 level = DEBUG
-handlers = console
+handlers = 
 qualname = rhodecode
-propagate = 0
+propagate = 1
 
 [logger_sqlalchemy]
-level = ERROR
-handlers = console
+level = INFO
+handlers = console_sql
 qualname = sqlalchemy.engine
 propagate = 0
 
@@ -201,9 +214,15 @@
 [handler_console]
 class = StreamHandler
 args = (sys.stderr,)
-level = NOTSET
+level = INFO
 formatter = color_formatter
 
+[handler_console_sql]
+class = StreamHandler
+args = (sys.stderr,)
+level = WARN
+formatter = color_formatter_sql
+
 ################
 ## FORMATTERS ##
 ################
@@ -215,4 +234,9 @@
 [formatter_color_formatter]
 class=rhodecode.lib.colored_formatter.ColorFormatter
 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %Y-%m-%d %H:%M:%S
+
+[formatter_color_formatter_sql]
+class=rhodecode.lib.colored_formatter.ColorFormatterSql
+format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
 datefmt = %Y-%m-%d %H:%M:%S
\ No newline at end of file
--- a/rhodecode/config/environment.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/config/environment.py	Fri Oct 07 01:08:50 2011 +0200
@@ -6,18 +6,18 @@
 from mako.lookup import TemplateLookup
 from pylons.configuration import PylonsConfig
 from pylons.error import handle_mako_error
-from sqlalchemy import engine_from_config
 
 import rhodecode.lib.app_globals as app_globals
 import rhodecode.lib.helpers
 
 from rhodecode.config.routing import make_map
 from rhodecode.lib import celerypylons
-from rhodecode.lib.auth import set_available_permissions, set_base_path
+from rhodecode.lib import engine_from_config
+from rhodecode.lib.timerproxy import TimerProxy
+from rhodecode.lib.auth import set_available_permissions
 from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config
 from rhodecode.model import init_model
 from rhodecode.model.scm import ScmModel
-from rhodecode.lib.timerproxy import TimerProxy
 
 log = logging.getLogger(__name__)
 
@@ -61,25 +61,18 @@
         from rhodecode.lib.utils import create_test_env, create_test_index
         from rhodecode.tests import  TESTS_TMP_PATH
         create_test_env(TESTS_TMP_PATH, config)
-        create_test_index(TESTS_TMP_PATH, True)
+        create_test_index(TESTS_TMP_PATH, config, True)
 
     #MULTIPLE DB configs
     # Setup the SQLAlchemy database engine
-    if config['debug'] and not test:
-        #use query time debugging.
-        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.',
-                                           proxy=TimerProxy())
-    else:
-        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
+    sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
 
     init_model(sa_engine_db1)
-    #init baseui
-    config['pylons.app_globals'].baseui = make_ui('db')
 
-    g = config['pylons.app_globals']
-    repo2db_mapper(ScmModel().repo_scan(g.paths[0][1], g.baseui))
+    repos_path = make_ui('db').configitems('paths')[0][1]
+    repo2db_mapper(ScmModel().repo_scan(repos_path))
     set_available_permissions(config)
-    set_base_path(config)
+    config['base_path'] = repos_path
     set_rhodecode_config(config)
     # CONFIGURATION OPTIONS HERE (note: all config options will override
     # any Pylons config options)
--- a/rhodecode/config/middleware.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/config/middleware.py	Fri Oct 07 01:08:50 2011 +0200
@@ -47,9 +47,9 @@
     app = SessionMiddleware(app, config)
 
     # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
-
-    app = SimpleHg(app, config)
-    app = SimpleGit(app, config)
+    if asbool(config['pdebug']):
+        from rhodecode.lib.profiler import ProfilingMiddleware
+        app = ProfilingMiddleware(app)
 
     if asbool(full_stack):
         # Handle Python exceptions
@@ -74,6 +74,11 @@
         app = Cascade([static_app, app])
         app = make_gzip_middleware(app, global_conf, compress_level=1)
 
+    # we want our low level middleware to get to the request ASAP. We don't
+    # need any pylons stack middleware in them
+    app = SimpleHg(app, config)
+    app = SimpleGit(app, config)
+
     app.config = config
 
     return app
--- a/rhodecode/config/routing.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/config/routing.py	Fri Oct 07 01:08:50 2011 +0200
@@ -7,7 +7,10 @@
 """
 from __future__ import with_statement
 from routes import Mapper
-from rhodecode.lib.utils import check_repo_fast as cr
+
+
+# prefix for non repository related links needs to be prefixed with `/`
+ADMIN_PREFIX = '/_admin'
 
 
 def make_map(config):
@@ -16,15 +19,35 @@
                  always_scan=config['debug'])
     rmap.minimization = False
     rmap.explicit = False
-
+    
+    from rhodecode.lib.utils import is_valid_repo
+    from rhodecode.lib.utils import is_valid_repos_group
+    
     def check_repo(environ, match_dict):
         """
         check for valid repository for proper 404 handling
+        
         :param environ:
         :param match_dict:
         """
+         
         repo_name = match_dict.get('repo_name')
-        return not cr(repo_name, config['base_path'])
+        return is_valid_repo(repo_name, config['base_path'])
+
+    def check_group(environ, match_dict):
+        """
+        check for valid repositories group for proper 404 handling
+        
+        :param environ:
+        :param match_dict:
+        """
+        repos_group_name = match_dict.get('group_name')
+        
+        return is_valid_repos_group(repos_group_name, config['base_path'])
+
+
+    def check_int(environ, match_dict):
+        return match_dict.get('id').isdigit()
 
     # The ErrorController route (handles 404/500 error pages); it should
     # likely stay at the top, ensuring it can always be resolved
@@ -37,13 +60,16 @@
 
     #MAIN PAGE
     rmap.connect('home', '/', controller='home', action='index')
+    rmap.connect('repo_switcher', '/repos', controller='home',
+                 action='repo_switcher')
     rmap.connect('bugtracker',
                  "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
                  _static=True)
     rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
 
     #ADMIN REPOSITORY REST ROUTES
-    with rmap.submapper(path_prefix='/_admin', controller='admin/repos') as m:
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
+                        controller='admin/repos') as m:
         m.connect("repos", "/repos",
              action="create", conditions=dict(method=["POST"]))
         m.connect("repos", "/repos",
@@ -77,6 +103,12 @@
         m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
              action="delete_perm_user", conditions=dict(method=["DELETE"],
                                                         function=check_repo))
+        #ajax delete repo perm users_group
+        m.connect('delete_repo_users_group',
+                  "/repos_delete_users_group/{repo_name:.*}",
+                  action="delete_perm_users_group",
+                  conditions=dict(method=["DELETE"], function=check_repo))
+
         #settings actions
         m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
              action="repo_stats", conditions=dict(method=["DELETE"],
@@ -84,23 +116,126 @@
         m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
              action="repo_cache", conditions=dict(method=["DELETE"],
                                                         function=check_repo))
+        m.connect('repo_public_journal',
+                  "/repos_public_journal/{repo_name:.*}",
+                  action="repo_public_journal", conditions=dict(method=["PUT"],
+                  function=check_repo))
+        m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
+             action="repo_pull", conditions=dict(method=["PUT"],
+                                                        function=check_repo))
+
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
+                        controller='admin/repos_groups') as m:
+        m.connect("repos_groups", "/repos_groups",
+                  action="create", conditions=dict(method=["POST"]))
+        m.connect("repos_groups", "/repos_groups",
+                  action="index", conditions=dict(method=["GET"]))
+        m.connect("formatted_repos_groups", "/repos_groups.{format}",
+                  action="index", conditions=dict(method=["GET"]))
+        m.connect("new_repos_group", "/repos_groups/new",
+                  action="new", conditions=dict(method=["GET"]))
+        m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
+                  action="new", conditions=dict(method=["GET"]))
+        m.connect("update_repos_group", "/repos_groups/{id}",
+                  action="update", conditions=dict(method=["PUT"],
+                                                   function=check_int))
+        m.connect("delete_repos_group", "/repos_groups/{id}",
+                  action="delete", conditions=dict(method=["DELETE"],
+                                                   function=check_int))
+        m.connect("edit_repos_group", "/repos_groups/{id}/edit",
+                  action="edit", conditions=dict(method=["GET"],
+                                                 function=check_int))
+        m.connect("formatted_edit_repos_group",
+                  "/repos_groups/{id}.{format}/edit",
+                  action="edit", conditions=dict(method=["GET"],
+                                                 function=check_int))
+        m.connect("repos_group", "/repos_groups/{id}",
+                  action="show", conditions=dict(method=["GET"],
+                                                 function=check_int))
+        m.connect("formatted_repos_group", "/repos_groups/{id}.{format}",
+                  action="show", conditions=dict(method=["GET"],
+                                                 function=check_int))
+
     #ADMIN USER REST ROUTES
-    rmap.resource('user', 'users', controller='admin/users',
-                  path_prefix='/_admin')
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
+                        controller='admin/users') as m:
+        m.connect("users", "/users",
+                  action="create", conditions=dict(method=["POST"]))
+        m.connect("users", "/users",
+                  action="index", conditions=dict(method=["GET"]))
+        m.connect("formatted_users", "/users.{format}",
+                  action="index", conditions=dict(method=["GET"]))
+        m.connect("new_user", "/users/new",
+                  action="new", conditions=dict(method=["GET"]))
+        m.connect("formatted_new_user", "/users/new.{format}",
+                  action="new", conditions=dict(method=["GET"]))
+        m.connect("update_user", "/users/{id}",
+                  action="update", conditions=dict(method=["PUT"]))
+        m.connect("delete_user", "/users/{id}",
+                  action="delete", conditions=dict(method=["DELETE"]))
+        m.connect("edit_user", "/users/{id}/edit",
+                  action="edit", conditions=dict(method=["GET"]))
+        m.connect("formatted_edit_user",
+                  "/users/{id}.{format}/edit",
+                  action="edit", conditions=dict(method=["GET"]))
+        m.connect("user", "/users/{id}",
+                  action="show", conditions=dict(method=["GET"]))
+        m.connect("formatted_user", "/users/{id}.{format}",
+                  action="show", conditions=dict(method=["GET"]))
+
+        #EXTRAS USER ROUTES
+        m.connect("user_perm", "/users_perm/{id}",
+                  action="update_perm", conditions=dict(method=["PUT"]))
+
+    #ADMIN USERS REST ROUTES
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
+                        controller='admin/users_groups') as m:
+        m.connect("users_groups", "/users_groups",
+                  action="create", conditions=dict(method=["POST"]))
+        m.connect("users_groups", "/users_groups",
+                  action="index", conditions=dict(method=["GET"]))
+        m.connect("formatted_users_groups", "/users_groups.{format}",
+                  action="index", conditions=dict(method=["GET"]))
+        m.connect("new_users_group", "/users_groups/new",
+                  action="new", conditions=dict(method=["GET"]))
+        m.connect("formatted_new_users_group", "/users_groups/new.{format}",
+                  action="new", conditions=dict(method=["GET"]))
+        m.connect("update_users_group", "/users_groups/{id}",
+                  action="update", conditions=dict(method=["PUT"]))
+        m.connect("delete_users_group", "/users_groups/{id}",
+                  action="delete", conditions=dict(method=["DELETE"]))
+        m.connect("edit_users_group", "/users_groups/{id}/edit",
+                  action="edit", conditions=dict(method=["GET"]))
+        m.connect("formatted_edit_users_group",
+                  "/users_groups/{id}.{format}/edit",
+                  action="edit", conditions=dict(method=["GET"]))
+        m.connect("users_group", "/users_groups/{id}",
+                  action="show", conditions=dict(method=["GET"]))
+        m.connect("formatted_users_group", "/users_groups/{id}.{format}",
+                  action="show", conditions=dict(method=["GET"]))
+
+        #EXTRAS USER ROUTES
+        m.connect("users_group_perm", "/users_groups_perm/{id}",
+                  action="update_perm", conditions=dict(method=["PUT"]))
+
+    #ADMIN GROUP REST ROUTES
+    rmap.resource('group', 'groups',
+                  controller='admin/groups', path_prefix=ADMIN_PREFIX)
 
     #ADMIN PERMISSIONS REST ROUTES
-    rmap.resource('permission', 'permissions', controller='admin/permissions',
-                  path_prefix='/_admin')
+    rmap.resource('permission', 'permissions',
+                  controller='admin/permissions', path_prefix=ADMIN_PREFIX)
 
     ##ADMIN LDAP SETTINGS
-    rmap.connect('ldap_settings', '/_admin/ldap',
+    rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
                  controller='admin/ldap_settings', action='ldap_settings',
                  conditions=dict(method=["POST"]))
-    rmap.connect('ldap_home', '/_admin/ldap',
-                 controller='admin/ldap_settings',)
+
+    rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
+                 controller='admin/ldap_settings')
 
     #ADMIN SETTINGS REST ROUTES
-    with rmap.submapper(path_prefix='/_admin',
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
                         controller='admin/settings') as m:
         m.connect("admin_settings", "/settings",
                   action="create", conditions=dict(method=["POST"]))
@@ -132,41 +267,79 @@
         m.connect("admin_settings_create_repository", "/create_repository",
                   action="create_repository", conditions=dict(method=["GET"]))
 
+
     #ADMIN MAIN PAGES
-    with rmap.submapper(path_prefix='/_admin', controller='admin/admin') as m:
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
+                        controller='admin/admin') as m:
         m.connect('admin_home', '', action='index')
         m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
                   action='add_repo')
 
+    #==========================================================================
+    # API V1
+    #==========================================================================
+    with rmap.submapper(path_prefix=ADMIN_PREFIX,
+                        controller='api/api') as m:
+        m.connect('api', '/api')
+
+
     #USER JOURNAL
-    rmap.connect('journal', '/_admin/journal', controller='journal',)
-    rmap.connect('toggle_following', '/_admin/toggle_following',
+    rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, controller='journal')
+
+    rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
+                 controller='journal', action="public_journal")
+
+    rmap.connect('public_journal_rss', '%s/public_journal_rss' % ADMIN_PREFIX,
+                 controller='journal', action="public_journal_rss")
+
+    rmap.connect('public_journal_atom',
+                 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
+                 action="public_journal_atom")
+
+    rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
                  controller='journal', action='toggle_following',
                  conditions=dict(method=["POST"]))
 
     #SEARCH
-    rmap.connect('search', '/_admin/search', controller='search',)
-    rmap.connect('search_repo', '/_admin/search/{search_repo:.*}',
+    rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
+    rmap.connect('search_repo', '%s/search/{search_repo:.*}' % ADMIN_PREFIX,
                   controller='search')
 
     #LOGIN/LOGOUT/REGISTER/SIGN IN
-    rmap.connect('login_home', '/_admin/login', controller='login')
-    rmap.connect('logout_home', '/_admin/logout', controller='login',
+    rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
+    rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
                  action='logout')
-    rmap.connect('register', '/_admin/register', controller='login',
+
+    rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
                  action='register')
-    rmap.connect('reset_password', '/_admin/password_reset',
+
+    rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
                  controller='login', action='password_reset')
 
+    rmap.connect('reset_password_confirmation',
+                 '%s/password_reset_confirmation' % ADMIN_PREFIX,
+                 controller='login', action='password_reset_confirmation')
+
     #FEEDS
     rmap.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
                 controller='feed', action='rss',
                 conditions=dict(function=check_repo))
+
     rmap.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
                 controller='feed', action='atom',
                 conditions=dict(function=check_repo))
 
-    #REPOSITORY ROUTES
+    #==========================================================================
+    # REPOSITORY ROUTES
+    #==========================================================================
+    rmap.connect('summary_home', '/{repo_name:.*}',
+                controller='summary', 
+                conditions=dict(function=check_repo))
+    
+#    rmap.connect('repo_group_home', '/{group_name:.*}',
+#                controller='admin/repos_groups',action="show_by_name", 
+#                conditions=dict(function=check_group))
+    
     rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
                 controller='changeset', revision='tip',
                 conditions=dict(function=check_repo))
@@ -176,9 +349,6 @@
                  controller='changeset', action='raw_changeset',
                  revision='tip', conditions=dict(function=check_repo))
 
-    rmap.connect('summary_home_', '/{repo_name:.*}',
-                controller='summary', conditions=dict(function=check_repo))
-
     rmap.connect('summary_home', '/{repo_name:.*}/summary',
                 controller='summary', conditions=dict(function=check_repo))
 
@@ -194,6 +364,10 @@
     rmap.connect('changelog_home', '/{repo_name:.*}/changelog',
                 controller='changelog', conditions=dict(function=check_repo))
 
+    rmap.connect('changelog_details', '/{repo_name:.*}/changelog_details/{cs}',
+                controller='changelog', action='changelog_details',
+                conditions=dict(function=check_repo))
+
     rmap.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
                 controller='files', revision='tip', f_path='',
                 conditions=dict(function=check_repo))
@@ -217,28 +391,51 @@
                  controller='files', action='annotate', revision='tip',
                  f_path='', conditions=dict(function=check_repo))
 
-    rmap.connect('files_archive_home',
-                 '/{repo_name:.*}/archive/{revision}/{fileformat}',
-                 controller='files', action='archivefile', revision='tip',
-                 conditions=dict(function=check_repo))
+    rmap.connect('files_edit_home',
+                 '/{repo_name:.*}/edit/{revision}/{f_path:.*}',
+                 controller='files', action='edit', revision='tip',
+                 f_path='', conditions=dict(function=check_repo))
+
+    rmap.connect('files_add_home',
+                 '/{repo_name:.*}/add/{revision}/{f_path:.*}',
+                 controller='files', action='add', revision='tip',
+                 f_path='', conditions=dict(function=check_repo))
+
+    rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
+                controller='files', action='archivefile',
+                conditions=dict(function=check_repo))
+
+    rmap.connect('files_nodelist_home',
+                 '/{repo_name:.*}/nodelist/{revision}/{f_path:.*}',
+                controller='files', action='nodelist',
+                conditions=dict(function=check_repo))
 
     rmap.connect('repo_settings_delete', '/{repo_name:.*}/settings',
-                 controller='settings', action="delete",
-                 conditions=dict(method=["DELETE"], function=check_repo))
+                controller='settings', action="delete",
+                conditions=dict(method=["DELETE"], function=check_repo))
 
     rmap.connect('repo_settings_update', '/{repo_name:.*}/settings',
-                 controller='settings', action="update",
-                 conditions=dict(method=["PUT"], function=check_repo))
+                controller='settings', action="update",
+                conditions=dict(method=["PUT"], function=check_repo))
 
     rmap.connect('repo_settings_home', '/{repo_name:.*}/settings',
-                 controller='settings', action='index',
-                 conditions=dict(function=check_repo))
+                controller='settings', action='index',
+                conditions=dict(function=check_repo))
 
     rmap.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
                 controller='settings', action='fork_create',
                 conditions=dict(function=check_repo, method=["POST"]))
+
     rmap.connect('repo_fork_home', '/{repo_name:.*}/fork',
                 controller='settings', action='fork',
                 conditions=dict(function=check_repo))
 
+    rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
+                 controller='followers', action='followers',
+                 conditions=dict(function=check_repo))
+
+    rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
+                 controller='forks', action='forks',
+                 conditions=dict(function=check_repo))
+
     return rmap
--- a/rhodecode/controllers/admin/admin.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/admin/admin.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Controller for Admin panel of Rhodecode
-    
+
     :created_on: Apr 7, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -24,14 +24,18 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import logging
+
 from pylons import request, tmpl_context as c
+from sqlalchemy.orm import joinedload
+from webhelpers.paginate import Page
+
+from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
 from rhodecode.lib.base import BaseController, render
 from rhodecode.model.db import UserLog
-from webhelpers.paginate import Page
-from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
 
 log = logging.getLogger(__name__)
 
+
 class AdminController(BaseController):
 
     @LoginRequired()
@@ -41,11 +45,15 @@
     @HasPermissionAllDecorator('hg.admin')
     def index(self):
 
-        users_log = self.sa.query(UserLog).order_by(UserLog.action_date.desc())
+        users_log = self.sa.query(UserLog)\
+                .options(joinedload(UserLog.user))\
+                .options(joinedload(UserLog.repository))\
+                .order_by(UserLog.action_date.desc())
+
         p = int(request.params.get('page', 1))
         c.users_log = Page(users_log, page=p, items_per_page=10)
         c.log_data = render('admin/admin_log.html')
-        if request.params.get('partial'):
+
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
             return c.log_data
         return render('admin/admin.html')
-
--- a/rhodecode/controllers/admin/ldap_settings.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/admin/ldap_settings.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     ldap controller for RhodeCode
-    
+
     :created_on: Nov 26, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -32,29 +32,61 @@
 from pylons.controllers.util import abort, redirect
 from pylons.i18n.translation import _
 
+from sqlalchemy.exc import DatabaseError
+
 from rhodecode.lib.base import BaseController, render
 from rhodecode.lib import helpers as h
 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
-from rhodecode.lib.auth_ldap import LdapImportError
-from rhodecode.model.settings import SettingsModel
+from rhodecode.lib.exceptions import LdapImportError
 from rhodecode.model.forms import LdapSettingsForm
-from sqlalchemy.exc import DatabaseError
+from rhodecode.model.db import RhodeCodeSettings
 
 log = logging.getLogger(__name__)
 
 
+class LdapSettingsController(BaseController):
 
-class LdapSettingsController(BaseController):
+    search_scope_choices = [('BASE', _('BASE'),),
+                            ('ONELEVEL', _('ONELEVEL'),),
+                            ('SUBTREE', _('SUBTREE'),),
+                            ]
+    search_scope_default = 'SUBTREE'
+
+    tls_reqcert_choices = [('NEVER', _('NEVER'),),
+                           ('ALLOW', _('ALLOW'),),
+                           ('TRY', _('TRY'),),
+                           ('DEMAND', _('DEMAND'),),
+                           ('HARD', _('HARD'),),
+                           ]
+    tls_reqcert_default = 'DEMAND'
+
+    tls_kind_choices = [('PLAIN', _('No encryption'),),
+                        ('LDAPS', _('LDAPS connection'),),
+                        ('START_TLS', _('START_TLS on LDAP connection'),)
+                        ]
+
+    tls_kind_default = 'PLAIN'
 
     @LoginRequired()
     @HasPermissionAllDecorator('hg.admin')
     def __before__(self):
         c.admin_user = session.get('admin_user')
         c.admin_username = session.get('admin_username')
+        c.search_scope_choices = self.search_scope_choices
+        c.tls_reqcert_choices = self.tls_reqcert_choices
+        c.tls_kind_choices = self.tls_kind_choices
+
+        c.search_scope_cur = self.search_scope_default
+        c.tls_reqcert_cur = self.tls_reqcert_default
+        c.tls_kind_cur = self.tls_kind_default
+
         super(LdapSettingsController, self).__before__()
 
     def index(self):
-        defaults = SettingsModel().get_ldap_settings()
+        defaults = RhodeCodeSettings.get_ldap_settings()
+        c.search_scope_cur = defaults.get('ldap_search_scope')
+        c.tls_reqcert_cur = defaults.get('ldap_tls_reqcert')
+        c.tls_kind_cur = defaults.get('ldap_tls_kind')
 
         return htmlfill.render(
                     render('admin/ldap/ldap.html'),
@@ -65,17 +97,17 @@
     def ldap_settings(self):
         """POST ldap create and store ldap settings"""
 
-        settings_model = SettingsModel()
-        post_data = dict(request.POST)
-        _form = LdapSettingsForm(post_data.get('ldap_active'))()
+        _form = LdapSettingsForm([x[0] for x in self.tls_reqcert_choices],
+                                 [x[0] for x in self.search_scope_choices],
+                                 [x[0] for x in self.tls_kind_choices])()
 
         try:
-            form_result = _form.to_python(post_data)
+            form_result = _form.to_python(dict(request.POST))
             try:
 
                 for k, v in form_result.items():
                     if k.startswith('ldap_'):
-                        setting = settings_model.get(k)
+                        setting = RhodeCodeSettings.get_by_name(k)
                         setting.app_settings_value = v
                         self.sa.add(setting)
 
@@ -89,11 +121,12 @@
                       'is missing.'), category='warning')
 
         except formencode.Invalid, errors:
+            e = errors.error_dict or {}
 
             return htmlfill.render(
                 render('admin/ldap/ldap.html'),
                 defaults=errors.value,
-                errors=errors.error_dict or {},
+                errors=e,
                 prefix_error=False,
                 encoding="UTF-8")
         except Exception:
--- a/rhodecode/controllers/admin/permissions.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/admin/permissions.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,12 +2,12 @@
 """
     rhodecode.controllers.admin.permissions
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-    
+
     permissions controller for Rhodecode
-    
+
     :created_on: Apr 27, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -23,24 +23,25 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import logging
+import traceback
+import formencode
 from formencode import htmlfill
+
 from pylons import request, session, tmpl_context as c, url
 from pylons.controllers.util import abort, redirect
 from pylons.i18n.translation import _
+
 from rhodecode.lib import helpers as h
 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
-from rhodecode.lib.auth_ldap import LdapImportError
 from rhodecode.lib.base import BaseController, render
-from rhodecode.model.forms import LdapSettingsForm, DefaultPermissionsForm
+from rhodecode.model.forms import DefaultPermissionsForm
 from rhodecode.model.permission import PermissionModel
-from rhodecode.model.settings import SettingsModel
-from rhodecode.model.user import UserModel
-import formencode
-import logging
-import traceback
+from rhodecode.model.db import User
 
 log = logging.getLogger(__name__)
 
+
 class PermissionsController(BaseController):
     """REST Controller styled on the Atom Publishing Protocol"""
     # To properly map this controller, ensure your config/routing.py
@@ -69,7 +70,6 @@
         self.create_choices = [('hg.create.none', _('Disabled')),
                                ('hg.create.repository', _('Enabled'))]
 
-
     def index(self, format='html'):
         """GET /permissions: All items in the collection"""
         # url('permissions')
@@ -99,7 +99,7 @@
 
         try:
             form_result = _form.to_python(dict(request.POST))
-            form_result.update({'perm_user_name':id})
+            form_result.update({'perm_user_name': id})
             permission_model.update(form_result)
             h.flash(_('Default permissions updated successfully'),
                     category='success')
@@ -123,8 +123,6 @@
 
         return redirect(url('edit_permission', id=id))
 
-
-
     def delete(self, id):
         """DELETE /permissions/id: Delete an existing item"""
         # Forms posted to this method should contain a hidden field:
@@ -146,9 +144,9 @@
         c.create_choices = self.create_choices
 
         if id == 'default':
-            default_user = UserModel().get_by_username('default')
-            defaults = {'_method':'put',
-                        'anonymous':default_user.active}
+            default_user = User.by_username('default')
+            defaults = {'_method': 'put',
+                        'anonymous': default_user.active}
 
             for p in default_user.user_perms:
                 if p.permission.permission_name.startswith('repository.'):
--- a/rhodecode/controllers/admin/repos.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/admin/repos.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,12 +2,12 @@
 """
     rhodecode.controllers.admin.repos
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-    
+
     Admin controller for RhodeCode
-    
+
     :created_on: Apr 7, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -38,17 +38,20 @@
 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
     HasPermissionAnyDecorator
 from rhodecode.lib.base import BaseController, render
-from rhodecode.lib.utils import invalidate_cache, action_logger
-from rhodecode.model.db import User
+from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
+from rhodecode.lib.helpers import get_token
+from rhodecode.model.db import User, Repository, UserFollowing, Group
 from rhodecode.model.forms import RepoForm
 from rhodecode.model.scm import ScmModel
 from rhodecode.model.repo import RepoModel
-
+from sqlalchemy.exc import IntegrityError
 
 log = logging.getLogger(__name__)
 
+
 class ReposController(BaseController):
-    """REST Controller styled on the Atom Publishing Protocol"""
+    """
+    REST Controller styled on the Atom Publishing Protocol"""
     # To properly map this controller, ensure your config/routing.py
     # file has a resource setup:
     #     map.resource('repo', 'repos')
@@ -60,35 +63,129 @@
         c.admin_username = session.get('admin_username')
         super(ReposController, self).__before__()
 
+    def __load_defaults(self):
+        repo_model = RepoModel()
+
+        c.repo_groups = [('', '')]
+        parents_link = lambda k: h.literal('&raquo;'.join(
+                                    map(lambda k: k.group_name,
+                                        k.parents + [k])
+                                    )
+                                )
+
+        c.repo_groups.extend([(x.group_id, parents_link(x)) for \
+                                            x in self.sa.query(Group).all()])
+        c.repo_groups = sorted(c.repo_groups,
+                               key=lambda t: t[1].split('&raquo;')[0])
+        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
+        c.users_array = repo_model.get_users_js()
+        c.users_groups_array = repo_model.get_users_groups_js()
+
+    def __load_data(self, repo_name=None):
+        """
+        Load defaults settings for edit, and update
+
+        :param repo_name:
+        """
+        self.__load_defaults()
+
+        c.repo_info = db_repo = Repository.by_repo_name(repo_name)
+        repo = scm_repo = db_repo.scm_instance
+
+        if c.repo_info is None:
+            h.flash(_('%s repository is not mapped to db perhaps'
+                      ' it was created or renamed from the filesystem'
+                      ' please run the application again'
+                      ' in order to rescan repositories') % repo_name,
+                      category='error')
+
+            return redirect(url('repos'))
+
+        c.default_user_id = User.by_username('default').user_id
+        c.in_public_journal = self.sa.query(UserFollowing)\
+            .filter(UserFollowing.user_id == c.default_user_id)\
+            .filter(UserFollowing.follows_repository == c.repo_info).scalar()
+
+        if c.repo_info.stats:
+            last_rev = c.repo_info.stats.stat_on_revision
+        else:
+            last_rev = 0
+        c.stats_revision = last_rev
+
+        c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
+
+        if last_rev == 0 or c.repo_last_rev == 0:
+            c.stats_percentage = 0
+        else:
+            c.stats_percentage = '%.2f' % ((float((last_rev)) /
+                                            c.repo_last_rev) * 100)
+
+        defaults = c.repo_info.get_dict()
+        group, repo_name = c.repo_info.groups_and_repo
+        defaults['repo_name'] = repo_name
+        defaults['repo_group'] = getattr(group[-1] if group else None,
+                                         'group_id', None)
+
+        #fill owner
+        if c.repo_info.user:
+            defaults.update({'user': c.repo_info.user.username})
+        else:
+            replacement_user = self.sa.query(User)\
+            .filter(User.admin == True).first().username
+            defaults.update({'user': replacement_user})
+
+        #fill repository users
+        for p in c.repo_info.repo_to_perm:
+            defaults.update({'u_perm_%s' % p.user.username:
+                             p.permission.permission_name})
+
+        #fill repository groups
+        for p in c.repo_info.users_group_to_perm:
+            defaults.update({'g_perm_%s' % p.users_group.users_group_name:
+                             p.permission.permission_name})
+
+        return defaults
+
     @HasPermissionAllDecorator('hg.admin')
     def index(self, format='html'):
         """GET /repos: All items in the collection"""
         # url('repos')
-        cached_repo_list = ScmModel().get_repos()
-        c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
+
+        c.repos_list = ScmModel().get_repos(Repository.query()
+                                            .order_by(Repository.repo_name)
+                                            .all(), sort_key='name_sort')
         return render('admin/repos/repos.html')
 
     @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
     def create(self):
-        """POST /repos: Create a new item"""
+        """
+        POST /repos: Create a new item"""
         # url('repos')
         repo_model = RepoModel()
-        _form = RepoForm()()
+        self.__load_defaults()
         form_result = {}
         try:
-            form_result = _form.to_python(dict(request.POST))
-            repo_model.create(form_result, c.rhodecode_user)
-            h.flash(_('created repository %s') % form_result['repo_name'],
+            form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
+                            .to_python(dict(request.POST))
+            repo_model.create(form_result, self.rhodecode_user)
+            if form_result['clone_uri']:
+                h.flash(_('created repository %s from %s') \
+                    % (form_result['repo_name'], form_result['clone_uri']),
+                    category='success')
+            else:
+                h.flash(_('created repository %s') % form_result['repo_name'],
                     category='success')
 
             if request.POST.get('user_created'):
+                #created by regular non admin user
                 action_logger(self.rhodecode_user, 'user_created_repo',
-                              form_result['repo_name'], '', self.sa)
+                              form_result['repo_name_full'], '', self.sa)
             else:
                 action_logger(self.rhodecode_user, 'admin_created_repo',
-                              form_result['repo_name'], '', self.sa)
+                              form_result['repo_name_full'], '', self.sa)
 
         except formencode.Invalid, errors:
+
             c.new_repo = errors.value['repo_name']
 
             if request.POST.get('user_created'):
@@ -116,54 +213,41 @@
     def new(self, format='html'):
         """GET /repos/new: Form to create a new item"""
         new_repo = request.GET.get('repo', '')
-        c.new_repo = h.repo_name_slug(new_repo)
-
+        c.new_repo = repo_name_slug(new_repo)
+        self.__load_defaults()
         return render('admin/repos/repo_add.html')
 
     @HasPermissionAllDecorator('hg.admin')
     def update(self, repo_name):
-        """PUT /repos/repo_name: Update an existing item"""
+        """
+        PUT /repos/repo_name: Update an existing item"""
         # Forms posted to this method should contain a hidden field:
         #    <input type="hidden" name="_method" value="PUT" />
         # Or using helpers:
         #    h.form(url('repo', repo_name=ID),
         #           method='put')
         # url('repo', repo_name=ID)
+        self.__load_defaults()
         repo_model = RepoModel()
         changed_name = repo_name
-        _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
-
+        _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
+                         repo_groups=c.repo_groups_choices)()
         try:
             form_result = _form.to_python(dict(request.POST))
             repo_model.update(repo_name, form_result)
             invalidate_cache('get_repo_cached_%s' % repo_name)
             h.flash(_('Repository %s updated successfully' % repo_name),
                     category='success')
-            changed_name = form_result['repo_name']
+            changed_name = form_result['repo_name_full']
             action_logger(self.rhodecode_user, 'admin_updated_repo',
                               changed_name, '', self.sa)
 
         except formencode.Invalid, errors:
-            c.repo_info = repo_model.get_by_repo_name(repo_name)
-            if c.repo_info.stats:
-                last_rev = c.repo_info.stats.stat_on_revision
-            else:
-                last_rev = 0
-            c.stats_revision = last_rev
-            r = ScmModel().get(repo_name)
-            c.repo_last_rev = r.revisions[-1] if r.revisions else 0
-
-            if last_rev == 0:
-                c.stats_percentage = 0
-            else:
-                c.stats_percentage = '%.2f' % ((float((last_rev)) /
-                                                c.repo_last_rev) * 100)
-
-            c.users_array = repo_model.get_users_js()
-            errors.value.update({'user':c.repo_info.user.username})
+            defaults = self.__load_data(repo_name)
+            defaults.update(errors.value)
             return htmlfill.render(
                 render('admin/repos/repo_edit.html'),
-                defaults=errors.value,
+                defaults=defaults,
                 errors=errors.error_dict or {},
                 prefix_error=False,
                 encoding="UTF-8")
@@ -172,12 +256,12 @@
             log.error(traceback.format_exc())
             h.flash(_('error occurred during update of repository %s') \
                     % repo_name, category='error')
-
         return redirect(url('edit_repo', repo_name=changed_name))
 
     @HasPermissionAllDecorator('hg.admin')
     def delete(self, repo_name):
-        """DELETE /repos/repo_name: Delete an existing item"""
+        """
+        DELETE /repos/repo_name: Delete an existing item"""
         # Forms posted to this method should contain a hidden field:
         #    <input type="hidden" name="_method" value="DELETE" />
         # Or using helpers:
@@ -202,6 +286,18 @@
             invalidate_cache('get_repo_cached_%s' % repo_name)
             h.flash(_('deleted repository %s') % repo_name, category='success')
 
+        except IntegrityError, e:
+            if e.message.find('repositories_fork_id_fkey'):
+                log.error(traceback.format_exc())
+                h.flash(_('Cannot delete %s it still contains attached '
+                          'forks') % repo_name,
+                        category='warning')
+            else:
+                log.error(traceback.format_exc())
+                h.flash(_('An error occurred during '
+                          'deletion of %s') % repo_name,
+                        category='error')
+
         except Exception, e:
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during deletion of %s') % repo_name,
@@ -213,6 +309,7 @@
     def delete_perm_user(self, repo_name):
         """
         DELETE an existing repository permission user
+
         :param repo_name:
         """
 
@@ -225,9 +322,26 @@
             raise HTTPInternalServerError()
 
     @HasPermissionAllDecorator('hg.admin')
+    def delete_perm_users_group(self, repo_name):
+        """
+        DELETE an existing repository permission users group
+
+        :param repo_name:
+        """
+        try:
+            repo_model = RepoModel()
+            repo_model.delete_perm_users_group(request.POST, repo_name)
+        except Exception, e:
+            h.flash(_('An error occurred during deletion of repository'
+                      ' users groups'),
+                    category='error')
+            raise HTTPInternalServerError()
+
+    @HasPermissionAllDecorator('hg.admin')
     def repo_stats(self, repo_name):
         """
         DELETE an existing repository statistics
+
         :param repo_name:
         """
 
@@ -243,6 +357,7 @@
     def repo_cache(self, repo_name):
         """
         INVALIDATE existing repository cache
+
         :param repo_name:
         """
 
@@ -254,6 +369,50 @@
         return redirect(url('edit_repo', repo_name=repo_name))
 
     @HasPermissionAllDecorator('hg.admin')
+    def repo_public_journal(self, repo_name):
+        """
+        Set's this repository to be visible in public journal,
+        in other words assing default user to follow this repo
+
+        :param repo_name:
+        """
+
+        cur_token = request.POST.get('auth_token')
+        token = get_token()
+        if cur_token == token:
+            try:
+                repo_id = Repository.by_repo_name(repo_name).repo_id
+                user_id = User.by_username('default').user_id
+                self.scm_model.toggle_following_repo(repo_id, user_id)
+                h.flash(_('Updated repository visibility in public journal'),
+                        category='success')
+            except:
+                h.flash(_('An error occurred during setting this'
+                          ' repository in public journal'),
+                        category='error')
+
+        else:
+            h.flash(_('Token mismatch'), category='error')
+        return redirect(url('edit_repo', repo_name=repo_name))
+
+    @HasPermissionAllDecorator('hg.admin')
+    def repo_pull(self, repo_name):
+        """
+        Runs task to update given repository with remote changes,
+        ie. make pull on remote location
+
+        :param repo_name:
+        """
+        try:
+            ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
+            h.flash(_('Pulled from remote location'), category='success')
+        except Exception, e:
+            h.flash(_('An error occurred during pull from remote location'),
+                    category='error')
+
+        return redirect(url('edit_repo', repo_name=repo_name))
+
+    @HasPermissionAllDecorator('hg.admin')
     def show(self, repo_name, format='html'):
         """GET /repos/repo_name: Show a specific item"""
         # url('repo', repo_name=ID)
@@ -262,46 +421,7 @@
     def edit(self, repo_name, format='html'):
         """GET /repos/repo_name/edit: Form to edit an existing item"""
         # url('edit_repo', repo_name=ID)
-        repo_model = RepoModel()
-        r = ScmModel().get(repo_name)
-        c.repo_info = repo_model.get_by_repo_name(repo_name)
-
-        if c.repo_info is None:
-            h.flash(_('%s repository is not mapped to db perhaps'
-                      ' it was created or renamed from the filesystem'
-                      ' please run the application again'
-                      ' in order to rescan repositories') % repo_name,
-                      category='error')
-
-            return redirect(url('repos'))
-
-        if c.repo_info.stats:
-            last_rev = c.repo_info.stats.stat_on_revision
-        else:
-            last_rev = 0
-        c.stats_revision = last_rev
-
-        c.repo_last_rev = r.revisions[-1] if r.revisions else 0
-
-        if last_rev == 0 or c.repo_last_rev == 0:
-            c.stats_percentage = 0
-        else:
-            c.stats_percentage = '%.2f' % ((float((last_rev)) /
-                                            c.repo_last_rev) * 100)
-
-        defaults = c.repo_info.get_dict()
-        if c.repo_info.user:
-            defaults.update({'user':c.repo_info.user.username})
-        else:
-            replacement_user = self.sa.query(User)\
-            .filter(User.admin == True).first().username
-            defaults.update({'user':replacement_user})
-
-        c.users_array = repo_model.get_users_js()
-
-        for p in c.repo_info.repo_to_perm:
-            defaults.update({'perm_%s' % p.user.username:
-                             p.permission.permission_name})
+        defaults = self.__load_data(repo_name)
 
         return htmlfill.render(
             render('admin/repos/repo_edit.html'),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/admin/repos_groups.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,223 @@
+import logging
+import traceback
+import formencode
+
+from formencode import htmlfill
+from operator import itemgetter
+
+from pylons import request, response, session, tmpl_context as c, url
+from pylons.controllers.util import abort, redirect
+from pylons.i18n.translation import _
+
+from rhodecode.lib import helpers as h
+from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
+    HasPermissionAnyDecorator
+from rhodecode.lib.base import BaseController, render
+from rhodecode.model.db import Group
+from rhodecode.model.repos_group import ReposGroupModel
+from rhodecode.model.forms import ReposGroupForm
+
+log = logging.getLogger(__name__)
+
+
+class ReposGroupsController(BaseController):
+    """REST Controller styled on the Atom Publishing Protocol"""
+    # To properly map this controller, ensure your config/routing.py
+    # file has a resource setup:
+    #     map.resource('repos_group', 'repos_groups')
+
+    @LoginRequired()
+    def __before__(self):
+        super(ReposGroupsController, self).__before__()
+
+    def __load_defaults(self):
+
+        c.repo_groups = [('', '')]
+        parents_link = lambda k: h.literal('&raquo;'.join(
+                                    map(lambda k: k.group_name,
+                                        k.parents + [k])
+                                    )
+                                )
+
+        c.repo_groups.extend([(x.group_id, parents_link(x)) for \
+                                            x in self.sa.query(Group).all()])
+
+        c.repo_groups = sorted(c.repo_groups,
+                               key=lambda t: t[1].split('&raquo;')[0])
+        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
+
+    def __load_data(self, group_id):
+        """
+        Load defaults settings for edit, and update
+
+        :param group_id:
+        """
+        self.__load_defaults()
+
+        repo_group = Group.get(group_id)
+
+        data = repo_group.get_dict()
+
+        return data
+
+    @HasPermissionAnyDecorator('hg.admin')
+    def index(self, format='html'):
+        """GET /repos_groups: All items in the collection"""
+        # url('repos_groups')
+
+        sk = lambda g:g.parents[0].group_name if g.parents else g.group_name
+        c.groups = sorted(Group.query().all(), key=sk)
+        return render('admin/repos_groups/repos_groups_show.html')
+
+    @HasPermissionAnyDecorator('hg.admin')
+    def create(self):
+        """POST /repos_groups: Create a new item"""
+        # url('repos_groups')
+        self.__load_defaults()
+        repos_group_model = ReposGroupModel()
+        repos_group_form = ReposGroupForm(available_groups=
+                                          c.repo_groups_choices)()
+        try:
+            form_result = repos_group_form.to_python(dict(request.POST))
+            repos_group_model.create(form_result)
+            h.flash(_('created repos group %s') \
+                    % form_result['group_name'], category='success')
+            #TODO: in futureaction_logger(, '', '', '', self.sa)
+        except formencode.Invalid, errors:
+
+            return htmlfill.render(
+                render('admin/repos_groups/repos_groups_add.html'),
+                defaults=errors.value,
+                errors=errors.error_dict or {},
+                prefix_error=False,
+                encoding="UTF-8")
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('error occurred during creation of repos group %s') \
+                    % request.POST.get('group_name'), category='error')
+
+        return redirect(url('repos_groups'))
+
+
+    @HasPermissionAnyDecorator('hg.admin')
+    def new(self, format='html'):
+        """GET /repos_groups/new: Form to create a new item"""
+        # url('new_repos_group')
+        self.__load_defaults()
+        return render('admin/repos_groups/repos_groups_add.html')
+
+    @HasPermissionAnyDecorator('hg.admin')
+    def update(self, id):
+        """PUT /repos_groups/id: Update an existing item"""
+        # Forms posted to this method should contain a hidden field:
+        #    <input type="hidden" name="_method" value="PUT" />
+        # Or using helpers:
+        #    h.form(url('repos_group', id=ID),
+        #           method='put')
+        # url('repos_group', id=ID)
+
+        self.__load_defaults()
+        c.repos_group = Group.get(id)
+
+        repos_group_model = ReposGroupModel()
+        repos_group_form = ReposGroupForm(edit=True,
+                                          old_data=c.repos_group.get_dict(),
+                                          available_groups=
+                                            c.repo_groups_choices)()
+        try:
+            form_result = repos_group_form.to_python(dict(request.POST))
+            repos_group_model.update(id, form_result)
+            h.flash(_('updated repos group %s') \
+                    % form_result['group_name'], category='success')
+            #TODO: in futureaction_logger(, '', '', '', self.sa)
+        except formencode.Invalid, errors:
+
+            return htmlfill.render(
+                render('admin/repos_groups/repos_groups_edit.html'),
+                defaults=errors.value,
+                errors=errors.error_dict or {},
+                prefix_error=False,
+                encoding="UTF-8")
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('error occurred during update of repos group %s') \
+                    % request.POST.get('group_name'), category='error')
+
+        return redirect(url('repos_groups'))
+
+
+    @HasPermissionAnyDecorator('hg.admin')
+    def delete(self, id):
+        """DELETE /repos_groups/id: Delete an existing item"""
+        # Forms posted to this method should contain a hidden field:
+        #    <input type="hidden" name="_method" value="DELETE" />
+        # Or using helpers:
+        #    h.form(url('repos_group', id=ID),
+        #           method='delete')
+        # url('repos_group', id=ID)
+
+        repos_group_model = ReposGroupModel()
+        gr = Group.get(id)
+        repos = gr.repositories.all()
+        if repos:
+            h.flash(_('This group contains %s repositores and cannot be '
+                      'deleted' % len(repos)),
+                    category='error')
+            return redirect(url('repos_groups'))
+
+        try:
+            repos_group_model.delete(id)
+            h.flash(_('removed repos group %s' % gr.group_name), category='success')
+            #TODO: in future action_logger(, '', '', '', self.sa)
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('error occurred during deletion of repos group %s' % gr.group_name),
+                    category='error')
+
+        return redirect(url('repos_groups'))
+
+    def show(self, id, format='html'):
+        """GET /repos_groups/id: Show a specific item"""
+        # url('repos_group', id=ID)
+
+        c.group = Group.get(id)
+
+        if c.group:
+            c.group_repos = c.group.repositories.all()
+        else:
+            return redirect(url('home'))
+
+        #overwrite our cached list with current filter
+        gr_filter = c.group_repos
+        c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter)
+
+        c.repos_list = c.cached_repo_list
+
+        c.repo_cnt = 0
+
+        c.groups = self.sa.query(Group).order_by(Group.group_name)\
+            .filter(Group.group_parent_id == id).all()
+
+        return render('admin/repos_groups/repos_groups.html')
+
+    @HasPermissionAnyDecorator('hg.admin')
+    def edit(self, id, format='html'):
+        """GET /repos_groups/id/edit: Form to edit an existing item"""
+        # url('edit_repos_group', id=ID)
+
+        id_ = int(id)
+
+        c.repos_group = Group.get(id_)
+        defaults = self.__load_data(id_)
+
+        # we need to exclude this group from the group list for editing
+        c.repo_groups = filter(lambda x:x[0] != id_, c.repo_groups)
+
+        return htmlfill.render(
+            render('admin/repos_groups/repos_groups_edit.html'),
+            defaults=defaults,
+            encoding="UTF-8",
+            force_defaults=False
+        )
+
+
--- a/rhodecode/controllers/admin/settings.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/admin/settings.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,12 +2,12 @@
 """
     rhodecode.controllers.admin.settings
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-    
+
     settings controller for rhodecode admin
-        
+
     :created_on: Jul 14, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -23,28 +23,30 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import logging
+import traceback
+import formencode
+
+from sqlalchemy import func
 from formencode import htmlfill
-from pylons import request, session, tmpl_context as c, url, app_globals as g, \
-    config
+from pylons import request, session, tmpl_context as c, url, config
 from pylons.controllers.util import abort, redirect
 from pylons.i18n.translation import _
+
 from rhodecode.lib import helpers as h
 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
     HasPermissionAnyDecorator, NotAnonymous
 from rhodecode.lib.base import BaseController, render
 from rhodecode.lib.celerylib import tasks, run_task
 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
-    set_rhodecode_config
-from rhodecode.model.db import RhodeCodeUi, Repository
+    set_rhodecode_config, repo_name_slug
+from rhodecode.model.db import RhodeCodeUi, Repository, Group, \
+    RhodeCodeSettings
 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
     ApplicationUiSettingsForm
 from rhodecode.model.scm import ScmModel
-from rhodecode.model.settings import SettingsModel
 from rhodecode.model.user import UserModel
-from sqlalchemy import func
-import formencode
-import logging
-import traceback
+from rhodecode.model.db import User
 
 log = logging.getLogger(__name__)
 
@@ -53,23 +55,21 @@
     """REST Controller styled on the Atom Publishing Protocol"""
     # To properly map this controller, ensure your config/routing.py
     # file has a resource setup:
-    #     map.resource('setting', 'settings', controller='admin/settings', 
+    #     map.resource('setting', 'settings', controller='admin/settings',
     #         path_prefix='/admin', name_prefix='admin_')
 
-
     @LoginRequired()
     def __before__(self):
         c.admin_user = session.get('admin_user')
         c.admin_username = session.get('admin_username')
         super(SettingsController, self).__before__()
 
-
     @HasPermissionAllDecorator('hg.admin')
     def index(self, format='html'):
         """GET /admin/settings: All items in the collection"""
         # url('admin_settings')
 
-        defaults = SettingsModel().get_app_settings()
+        defaults = RhodeCodeSettings.get_app_settings()
         defaults.update(self.get_hg_ui_settings())
         return htmlfill.render(
             render('admin/settings/settings.html'),
@@ -100,19 +100,21 @@
         if setting_id == 'mapping':
             rm_obsolete = request.POST.get('destroy', False)
             log.debug('Rescanning directories with destroy=%s', rm_obsolete)
-
-            initial = ScmModel().repo_scan(g.paths[0][1], g.baseui)
+            initial = ScmModel().repo_scan()
+            log.debug('invalidating all repositories')
             for repo_name in initial.keys():
                 invalidate_cache('get_repo_cached_%s' % repo_name)
 
-            repo2db_mapper(initial, rm_obsolete)
+            added, removed = repo2db_mapper(initial, rm_obsolete)
 
-            h.flash(_('Repositories successfully rescanned'), category='success')
+            h.flash(_('Repositories successfully'
+                      ' rescanned added: %s,removed: %s') % (added, removed),
+                    category='success')
 
         if setting_id == 'whoosh':
             repo_location = self.get_hg_ui_settings()['paths_root_path']
             full_index = request.POST.get('full_index', False)
-            task = run_task(tasks.whoosh_index, repo_location, full_index)
+            run_task(tasks.whoosh_index, repo_location, full_index)
 
             h.flash(_('Whoosh reindex task scheduled'), category='success')
         if setting_id == 'global':
@@ -120,30 +122,36 @@
             application_form = ApplicationSettingsForm()()
             try:
                 form_result = application_form.to_python(dict(request.POST))
-                settings_model = SettingsModel()
+
                 try:
-                    hgsettings1 = settings_model.get('title')
-                    hgsettings1.app_settings_value = form_result['rhodecode_title']
+                    hgsettings1 = RhodeCodeSettings.get_by_name('title')
+                    hgsettings1.app_settings_value = \
+                        form_result['rhodecode_title']
 
-                    hgsettings2 = settings_model.get('realm')
-                    hgsettings2.app_settings_value = form_result['rhodecode_realm']
+                    hgsettings2 = RhodeCodeSettings.get_by_name('realm')
+                    hgsettings2.app_settings_value = \
+                        form_result['rhodecode_realm']
 
+                    hgsettings3 = RhodeCodeSettings.get_by_name('ga_code')
+                    hgsettings3.app_settings_value = \
+                        form_result['rhodecode_ga_code']
 
                     self.sa.add(hgsettings1)
                     self.sa.add(hgsettings2)
+                    self.sa.add(hgsettings3)
                     self.sa.commit()
                     set_rhodecode_config(config)
                     h.flash(_('Updated application settings'),
                             category='success')
 
-                except:
+                except Exception:
                     log.error(traceback.format_exc())
-                    h.flash(_('error occurred during updating'
-                              ' application settings'), category='error')
+                    h.flash(_('error occurred during updating '
+                              'application settings'),
+                            category='error')
 
                     self.sa.rollback()
 
-
             except formencode.Invalid, errors:
                 return htmlfill.render(
                      render('admin/settings/settings.html'),
@@ -167,24 +175,30 @@
                     .filter(RhodeCodeUi.ui_key == '/').one()
                     hgsettings2.ui_value = form_result['paths_root_path']
 
-
                     #HOOKS
                     hgsettings3 = self.sa.query(RhodeCodeUi)\
                     .filter(RhodeCodeUi.ui_key == 'changegroup.update').one()
-                    hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
+                    hgsettings3.ui_active = \
+                        bool(form_result['hooks_changegroup_update'])
 
                     hgsettings4 = self.sa.query(RhodeCodeUi)\
-                    .filter(RhodeCodeUi.ui_key == 'changegroup.repo_size').one()
-                    hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
+                    .filter(RhodeCodeUi.ui_key ==
+                            'changegroup.repo_size').one()
+                    hgsettings4.ui_active = \
+                        bool(form_result['hooks_changegroup_repo_size'])
 
                     hgsettings5 = self.sa.query(RhodeCodeUi)\
-                    .filter(RhodeCodeUi.ui_key == 'pretxnchangegroup.push_logger').one()
-                    hgsettings5.ui_active = bool(form_result['hooks_pretxnchangegroup_push_logger'])
+                    .filter(RhodeCodeUi.ui_key ==
+                            'pretxnchangegroup.push_logger').one()
+                    hgsettings5.ui_active = \
+                        bool(form_result['hooks_pretxnchangegroup'
+                                         '_push_logger'])
 
                     hgsettings6 = self.sa.query(RhodeCodeUi)\
-                    .filter(RhodeCodeUi.ui_key == 'preoutgoing.pull_logger').one()
-                    hgsettings6.ui_active = bool(form_result['hooks_preoutgoing_pull_logger'])
-
+                    .filter(RhodeCodeUi.ui_key ==
+                            'preoutgoing.pull_logger').one()
+                    hgsettings6.ui_active = \
+                        bool(form_result['hooks_preoutgoing_pull_logger'])
 
                     self.sa.add(hgsettings1)
                     self.sa.add(hgsettings2)
@@ -199,12 +213,11 @@
 
                 except:
                     log.error(traceback.format_exc())
-                    h.flash(_('error occurred during updating application settings'),
-                            category='error')
+                    h.flash(_('error occurred during updating '
+                              'application settings'), category='error')
 
                     self.sa.rollback()
 
-
             except formencode.Invalid, errors:
                 return htmlfill.render(
                      render('admin/settings/settings.html'),
@@ -214,6 +227,32 @@
                      encoding="UTF-8")
 
 
+        if setting_id == 'hooks':
+            ui_key = request.POST.get('new_hook_ui_key')
+            ui_value = request.POST.get('new_hook_ui_value')
+            try:
+                
+                if ui_value and ui_key:
+                    RhodeCodeUi.create_or_update_hook(ui_key, ui_value)
+                    h.flash(_('Added new hook'),
+                            category='success')
+
+                # check for edits
+                update = False
+                _d = request.POST.dict_of_lists()
+                for k, v in zip(_d.get('hook_ui_key',[]), _d.get('hook_ui_value_new',[])):
+                    RhodeCodeUi.create_or_update_hook(k, v)
+                    update = True
+
+                if update:
+                    h.flash(_('Updated hooks'), category='success')
+
+            except:
+                log.error(traceback.format_exc())
+                h.flash(_('error occurred during hook creation'),
+                        category='error')
+
+            return redirect(url('admin_edit_setting', setting_id='hooks'))
 
         return redirect(url('admin_settings'))
 
@@ -226,29 +265,45 @@
         #    h.form(url('admin_setting', setting_id=ID),
         #           method='delete')
         # url('admin_setting', setting_id=ID)
-
+        if setting_id == 'hooks':
+            hook_id = request.POST.get('hook_id')
+            RhodeCodeUi.delete(hook_id)
+            
+            
     @HasPermissionAllDecorator('hg.admin')
     def show(self, setting_id, format='html'):
-        """GET /admin/settings/setting_id: Show a specific item"""
+        """
+        GET /admin/settings/setting_id: Show a specific item"""
         # url('admin_setting', setting_id=ID)
 
     @HasPermissionAllDecorator('hg.admin')
     def edit(self, setting_id, format='html'):
-        """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
+        """
+        GET /admin/settings/setting_id/edit: Form to
+        edit an existing item"""
         # url('admin_edit_setting', setting_id=ID)
 
+        c.hooks = RhodeCodeUi.get_builtin_hooks()
+        c.custom_hooks = RhodeCodeUi.get_custom_hooks()
+
+        return htmlfill.render(
+            render('admin/settings/hooks.html'),
+            defaults={},
+            encoding="UTF-8",
+            force_defaults=False
+        )
+
     @NotAnonymous()
     def my_account(self):
         """
-        GET /_admin/my_account Displays info about my account 
+        GET /_admin/my_account Displays info about my account
         """
         # url('admin_settings_my_account')
 
-        c.user = UserModel().get(c.rhodecode_user.user_id, cache=False)
+        c.user = User.get(self.rhodecode_user.user_id)
         all_repos = self.sa.query(Repository)\
-            .filter(Repository.user_id == c.user.user_id)\
-            .order_by(func.lower(Repository.repo_name))\
-            .all()
+                     .filter(Repository.user_id == c.user.user_id)\
+                     .order_by(func.lower(Repository.repo_name)).all()
 
         c.user_repos = ScmModel().get_repos(all_repos)
 
@@ -274,9 +329,10 @@
         #           method='put')
         # url('admin_settings_my_account_update', id=ID)
         user_model = UserModel()
-        uid = c.rhodecode_user.user_id
-        _form = UserForm(edit=True, old_data={'user_id':uid,
-                                              'email':c.rhodecode_user.email})()
+        uid = self.rhodecode_user.user_id
+        _form = UserForm(edit=True,
+                         old_data={'user_id': uid,
+                                   'email': self.rhodecode_user.email})()
         form_result = {}
         try:
             form_result = _form.to_python(dict(request.POST))
@@ -285,8 +341,7 @@
                     category='success')
 
         except formencode.Invalid, errors:
-            c.user = user_model.get(c.rhodecode_user.user_id, cache=False)
-            c.user = UserModel().get(c.rhodecode_user.user_id, cache=False)
+            c.user = User.get(self.rhodecode_user.user_id)
             all_repos = self.sa.query(Repository)\
                 .filter(Repository.user_id == c.user.user_id)\
                 .order_by(func.lower(Repository.repo_name))\
@@ -310,8 +365,22 @@
     @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
     def create_repository(self):
         """GET /_admin/create_repository: Form to create a new item"""
+
+        c.repo_groups = [('', '')]
+        parents_link = lambda k: h.literal('&raquo;'.join(
+                                    map(lambda k: k.group_name,
+                                        k.parents + [k])
+                                    )
+                                )
+
+        c.repo_groups.extend([(x.group_id, parents_link(x)) for \
+                                            x in self.sa.query(Group).all()])
+        c.repo_groups = sorted(c.repo_groups,
+                               key=lambda t: t[1].split('&raquo;')[0])
+        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
+
         new_repo = request.GET.get('repo', '')
-        c.new_repo = h.repo_name_slug(new_repo)
+        c.new_repo = repo_name_slug(new_repo)
 
         return render('admin/repos/repo_add_create_repository.html')
 
--- a/rhodecode/controllers/admin/users.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/admin/users.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Users crud controller for pylons
-    
+
     :created_on: Apr 4, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -28,21 +28,23 @@
 import formencode
 
 from formencode import htmlfill
-from pylons import request, session, tmpl_context as c, url
+from pylons import request, session, tmpl_context as c, url, config
 from pylons.controllers.util import abort, redirect
 from pylons.i18n.translation import _
 
-from rhodecode.lib.exceptions import *
+from rhodecode.lib.exceptions import DefaultUserException, \
+    UserOwnsReposException
 from rhodecode.lib import helpers as h
 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
 from rhodecode.lib.base import BaseController, render
 
-from rhodecode.model.db import User
+from rhodecode.model.db import User, RepoToPerm, UserToPerm, Permission
 from rhodecode.model.forms import UserForm
 from rhodecode.model.user import UserModel
 
 log = logging.getLogger(__name__)
 
+
 class UsersController(BaseController):
     """REST Controller styled on the Atom Publishing Protocol"""
     # To properly map this controller, ensure your config/routing.py
@@ -55,7 +57,7 @@
         c.admin_user = session.get('admin_user')
         c.admin_username = session.get('admin_username')
         super(UsersController, self).__before__()
-
+        c.available_permissions = config['available_permissions']
 
     def index(self, format='html'):
         """GET /users: All items in the collection"""
@@ -99,25 +101,28 @@
         # Forms posted to this method should contain a hidden field:
         #    <input type="hidden" name="_method" value="PUT" />
         # Or using helpers:
-        #    h.form(url('user', id=ID),
+        #    h.form(url('update_user', id=ID),
         #           method='put')
         # url('user', id=ID)
         user_model = UserModel()
         c.user = user_model.get(id)
 
-        _form = UserForm(edit=True, old_data={'user_id':id,
-                                              'email':c.user.email})()
+        _form = UserForm(edit=True, old_data={'user_id': id,
+                                              'email': c.user.email})()
         form_result = {}
         try:
             form_result = _form.to_python(dict(request.POST))
             user_model.update(id, form_result)
-            h.flash(_('User updated succesfully'), category='success')
+            h.flash(_('User updated successfully'), category='success')
 
         except formencode.Invalid, errors:
+            e = errors.error_dict or {}
+            perm = Permission.get_by_key('hg.create.repository')
+            e.update({'create_repo_perm': UserToPerm.has_perm(id, perm)})
             return htmlfill.render(
                 render('admin/users/user_edit.html'),
                 defaults=errors.value,
-                errors=errors.error_dict or {},
+                errors=e,
                 prefix_error=False,
                 encoding="UTF-8")
         except Exception:
@@ -132,13 +137,13 @@
         # Forms posted to this method should contain a hidden field:
         #    <input type="hidden" name="_method" value="DELETE" />
         # Or using helpers:
-        #    h.form(url('user', id=ID),
+        #    h.form(url('delete_user', id=ID),
         #           method='delete')
         # url('user', id=ID)
         user_model = UserModel()
         try:
             user_model.delete(id)
-            h.flash(_('sucessfully deleted user'), category='success')
+            h.flash(_('successfully deleted user'), category='success')
         except (UserOwnsReposException, DefaultUserException), e:
             h.flash(str(e), category='warning')
         except Exception:
@@ -150,21 +155,53 @@
         """GET /users/id: Show a specific item"""
         # url('user', id=ID)
 
-
     def edit(self, id, format='html'):
         """GET /users/id/edit: Form to edit an existing item"""
         # url('edit_user', id=ID)
-        c.user = self.sa.query(User).get(id)
+        user_model = UserModel()
+        c.user = user_model.get(id)
         if not c.user:
             return redirect(url('users'))
         if c.user.username == 'default':
             h.flash(_("You can't edit this user"), category='warning')
             return redirect(url('users'))
+        c.user.permissions = {}
+        c.granted_permissions = user_model.fill_perms(c.user)\
+            .permissions['global']
 
         defaults = c.user.get_dict()
+        perm = Permission.get_by_key('hg.create.repository')
+        defaults.update({'create_repo_perm': UserToPerm.has_perm(id, perm)})
+
         return htmlfill.render(
             render('admin/users/user_edit.html'),
             defaults=defaults,
             encoding="UTF-8",
             force_defaults=False
         )
+
+    def update_perm(self, id):
+        """PUT /users_perm/id: Update an existing item"""
+        # url('user_perm', id=ID, method='put')
+
+        grant_perm = request.POST.get('create_repo_perm', False)
+
+        if grant_perm:
+            perm = Permission.get_by_key('hg.create.none')
+            UserToPerm.revoke_perm(id, perm)
+
+            perm = Permission.get_by_key('hg.create.repository')
+            UserToPerm.grant_perm(id, perm)
+            h.flash(_("Granted 'repository create' permission to user"),
+                    category='success')
+
+        else:
+            perm = Permission.get_by_key('hg.create.repository')
+            UserToPerm.revoke_perm(id, perm)
+
+            perm = Permission.get_by_key('hg.create.none')
+            UserToPerm.grant_perm(id, perm)
+            h.flash(_("Revoked 'repository create' permission to user"),
+                    category='success')
+
+        return redirect(url('edit_user', id=id))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/admin/users_groups.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,214 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.controllers.admin.users_groups
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Users Groups crud controller for pylons
+
+    :created_on: Jan 25, 2011
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+import traceback
+import formencode
+
+from formencode import htmlfill
+from pylons import request, session, tmpl_context as c, url, config
+from pylons.controllers.util import abort, redirect
+from pylons.i18n.translation import _
+
+from rhodecode.lib.exceptions import UsersGroupsAssignedException
+from rhodecode.lib import helpers as h
+from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
+from rhodecode.lib.base import BaseController, render
+
+from rhodecode.model.db import User, UsersGroup, Permission, UsersGroupToPerm
+from rhodecode.model.forms import UserForm, UsersGroupForm
+
+log = logging.getLogger(__name__)
+
+
+class UsersGroupsController(BaseController):
+    """REST Controller styled on the Atom Publishing Protocol"""
+    # To properly map this controller, ensure your config/routing.py
+    # file has a resource setup:
+    #     map.resource('users_group', 'users_groups')
+
+    @LoginRequired()
+    @HasPermissionAllDecorator('hg.admin')
+    def __before__(self):
+        c.admin_user = session.get('admin_user')
+        c.admin_username = session.get('admin_username')
+        super(UsersGroupsController, self).__before__()
+        c.available_permissions = config['available_permissions']
+
+    def index(self, format='html'):
+        """GET /users_groups: All items in the collection"""
+        # url('users_groups')
+        c.users_groups_list = self.sa.query(UsersGroup).all()
+        return render('admin/users_groups/users_groups.html')
+
+    def create(self):
+        """POST /users_groups: Create a new item"""
+        # url('users_groups')
+
+        users_group_form = UsersGroupForm()()
+        try:
+            form_result = users_group_form.to_python(dict(request.POST))
+            UsersGroup.create(form_result)
+            h.flash(_('created users group %s') \
+                    % form_result['users_group_name'], category='success')
+            #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
+        except formencode.Invalid, errors:
+            return htmlfill.render(
+                render('admin/users_groups/users_group_add.html'),
+                defaults=errors.value,
+                errors=errors.error_dict or {},
+                prefix_error=False,
+                encoding="UTF-8")
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('error occurred during creation of users group %s') \
+                    % request.POST.get('users_group_name'), category='error')
+
+        return redirect(url('users_groups'))
+
+    def new(self, format='html'):
+        """GET /users_groups/new: Form to create a new item"""
+        # url('new_users_group')
+        return render('admin/users_groups/users_group_add.html')
+
+    def update(self, id):
+        """PUT /users_groups/id: Update an existing item"""
+        # Forms posted to this method should contain a hidden field:
+        #    <input type="hidden" name="_method" value="PUT" />
+        # Or using helpers:
+        #    h.form(url('users_group', id=ID),
+        #           method='put')
+        # url('users_group', id=ID)
+
+        c.users_group = UsersGroup.get(id)
+        c.group_members = [(x.user_id, x.user.username) for x in
+                           c.users_group.members]
+
+        c.available_members = [(x.user_id, x.username) for x in
+                               self.sa.query(User).all()]
+        users_group_form = UsersGroupForm(edit=True,
+                                          old_data=c.users_group.get_dict(),
+                                          available_members=[str(x[0]) for x
+                                                in c.available_members])()
+
+        try:
+            form_result = users_group_form.to_python(request.POST)
+            UsersGroup.update(id, form_result)
+            h.flash(_('updated users group %s') \
+                        % form_result['users_group_name'],
+                    category='success')
+            #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
+        except formencode.Invalid, errors:
+            e = errors.error_dict or {}
+
+            perm = Permission.get_by_key('hg.create.repository')
+            e.update({'create_repo_perm':
+                         UsersGroupToPerm.has_perm(id, perm)})
+
+            return htmlfill.render(
+                render('admin/users_groups/users_group_edit.html'),
+                defaults=errors.value,
+                errors=e,
+                prefix_error=False,
+                encoding="UTF-8")
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('error occurred during update of users group %s') \
+                    % request.POST.get('users_group_name'), category='error')
+
+        return redirect(url('users_groups'))
+
+    def delete(self, id):
+        """DELETE /users_groups/id: Delete an existing item"""
+        # Forms posted to this method should contain a hidden field:
+        #    <input type="hidden" name="_method" value="DELETE" />
+        # Or using helpers:
+        #    h.form(url('users_group', id=ID),
+        #           method='delete')
+        # url('users_group', id=ID)
+
+        try:
+            UsersGroup.delete(id)
+            h.flash(_('successfully deleted users group'), category='success')
+        except UsersGroupsAssignedException, e:
+            h.flash(e, category='error')
+        except Exception:
+            h.flash(_('An error occurred during deletion of users group'),
+                    category='error')
+        return redirect(url('users_groups'))
+
+    def show(self, id, format='html'):
+        """GET /users_groups/id: Show a specific item"""
+        # url('users_group', id=ID)
+
+    def edit(self, id, format='html'):
+        """GET /users_groups/id/edit: Form to edit an existing item"""
+        # url('edit_users_group', id=ID)
+
+        c.users_group = self.sa.query(UsersGroup).get(id)
+        if not c.users_group:
+            return redirect(url('users_groups'))
+
+        c.users_group.permissions = {}
+        c.group_members = [(x.user_id, x.user.username) for x in
+                           c.users_group.members]
+        c.available_members = [(x.user_id, x.username) for x in
+                               self.sa.query(User).all()]
+        defaults = c.users_group.get_dict()
+        perm = Permission.get_by_key('hg.create.repository')
+        defaults.update({'create_repo_perm':
+                         UsersGroupToPerm.has_perm(id, perm)})
+        return htmlfill.render(
+            render('admin/users_groups/users_group_edit.html'),
+            defaults=defaults,
+            encoding="UTF-8",
+            force_defaults=False
+        )
+
+    def update_perm(self, id):
+        """PUT /users_perm/id: Update an existing item"""
+        # url('users_group_perm', id=ID, method='put')
+
+        grant_perm = request.POST.get('create_repo_perm', False)
+
+        if grant_perm:
+            perm = Permission.get_by_key('hg.create.none')
+            UsersGroupToPerm.revoke_perm(id, perm)
+
+            perm = Permission.get_by_key('hg.create.repository')
+            UsersGroupToPerm.grant_perm(id, perm)
+            h.flash(_("Granted 'repository create' permission to user"),
+                    category='success')
+
+        else:
+            perm = Permission.get_by_key('hg.create.repository')
+            UsersGroupToPerm.revoke_perm(id, perm)
+
+            perm = Permission.get_by_key('hg.create.none')
+            UsersGroupToPerm.grant_perm(id, perm)
+            h.flash(_("Revoked 'repository create' permission to user"),
+                    category='success')
+
+        return redirect(url('edit_users_group', id=id))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/api/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,241 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.controllers.api
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    JSON RPC controller
+    
+    :created_on: Aug 20, 2011
+    :author: marcink
+    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License or (at your opinion) any later version of the license.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+
+import inspect
+import json
+import logging
+import types
+import urllib
+import traceback
+from itertools import izip_longest
+
+from paste.response import replace_header
+
+from pylons.controllers import WSGIController
+from pylons.controllers.util import Response
+
+from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
+HTTPBadRequest, HTTPError
+
+from rhodecode.model.db import User
+from rhodecode.lib.auth import AuthUser
+
+log = logging.getLogger('JSONRPC')
+
+class JSONRPCError(BaseException):
+
+    def __init__(self, message):
+        self.message = message
+
+    def __str__(self):
+        return str(self.message)
+
+
+def jsonrpc_error(message, code=None):
+    """Generate a Response object with a JSON-RPC error body"""
+    return Response(body=json.dumps(dict(result=None,
+                                         error=message)))
+
+
+class JSONRPCController(WSGIController):
+    """
+     A WSGI-speaking JSON-RPC controller class
+    
+     See the specification:
+     <http://json-rpc.org/wiki/specification>`.
+   
+     Valid controller return values should be json-serializable objects.
+    
+     Sub-classes should catch their exceptions and raise JSONRPCError
+     if they want to pass meaningful errors to the client.
+    
+     """
+
+    def _get_method_args(self):
+        """
+        Return `self._rpc_args` to dispatched controller method
+        chosen by __call__
+        """
+        return self._rpc_args
+
+    def __call__(self, environ, start_response):
+        """
+        Parse the request body as JSON, look up the method on the
+        controller and if it exists, dispatch to it.
+        """
+        if 'CONTENT_LENGTH' not in environ:
+            log.debug("No Content-Length")
+            return jsonrpc_error(message="No Content-Length in request")
+        else:
+            length = environ['CONTENT_LENGTH'] or 0
+            length = int(environ['CONTENT_LENGTH'])
+            log.debug('Content-Length: %s', length)
+
+        if length == 0:
+            log.debug("Content-Length is 0")
+            return jsonrpc_error(message="Content-Length is 0")
+
+        raw_body = environ['wsgi.input'].read(length)
+
+        try:
+            json_body = json.loads(urllib.unquote_plus(raw_body))
+        except ValueError as e:
+            #catch JSON errors Here
+            return jsonrpc_error(message="JSON parse error ERR:%s RAW:%r" \
+                                 % (e, urllib.unquote_plus(raw_body)))
+
+        #check AUTH based on API KEY
+        try:
+            self._req_api_key = json_body['api_key']
+            self._req_method = json_body['method']
+            self._req_params = json_body['args']
+            log.debug('method: %s, params: %s',
+                      self._req_method,
+                      self._req_params)
+        except KeyError as e:
+            return jsonrpc_error(message='Incorrect JSON query missing %s' % e)
+
+        #check if we can find this session using api_key
+        try:
+            u = User.get_by_api_key(self._req_api_key)
+            auth_u = AuthUser(u.user_id, self._req_api_key)
+        except Exception as e:
+            return jsonrpc_error(message='Invalid API KEY')
+
+        self._error = None
+        try:
+            self._func = self._find_method()
+        except AttributeError, e:
+            return jsonrpc_error(message=str(e))
+
+        # now that we have a method, add self._req_params to
+        # self.kargs and dispatch control to WGIController
+        argspec = inspect.getargspec(self._func)
+        arglist = argspec[0][1:]
+        defaults = argspec[3] or []
+        default_empty = types.NotImplementedType
+        
+        kwarglist = list(izip_longest(reversed(arglist),reversed(defaults),
+                                fillvalue=default_empty))
+
+        # this is little trick to inject logged in user for 
+        # perms decorators to work they expect the controller class to have
+        # rhodecode_user attribute set
+        self.rhodecode_user = auth_u
+
+        # This attribute will need to be first param of a method that uses
+        # api_key, which is translated to instance of user at that name
+        USER_SESSION_ATTR = 'apiuser'
+
+        if USER_SESSION_ATTR not in arglist:
+            return jsonrpc_error(message='This method [%s] does not support '
+                                 'authentication (missing %s param)' %
+                                 (self._func.__name__, USER_SESSION_ATTR))
+
+        # get our arglist and check if we provided them as args
+        for arg,default in kwarglist:
+            if arg == USER_SESSION_ATTR:
+                # USER_SESSION_ATTR is something translated from api key and 
+                # this is checked before so we don't need validate it
+                continue
+            
+            # skip the required param check if it's default value is 
+            # NotImplementedType (default_empty)
+            if not self._req_params or (type(default) == default_empty
+                                        and arg not in self._req_params):
+                return jsonrpc_error(message=('Missing non optional %s arg '
+                                              'in JSON DATA') % arg)
+
+        self._rpc_args = {USER_SESSION_ATTR:u}
+        self._rpc_args.update(self._req_params)
+
+        self._rpc_args['action'] = self._req_method
+        self._rpc_args['environ'] = environ
+        self._rpc_args['start_response'] = start_response
+
+        status = []
+        headers = []
+        exc_info = []
+        def change_content(new_status, new_headers, new_exc_info=None):
+            status.append(new_status)
+            headers.extend(new_headers)
+            exc_info.append(new_exc_info)
+
+        output = WSGIController.__call__(self, environ, change_content)
+        output = list(output)
+        headers.append(('Content-Length', str(len(output[0]))))
+        replace_header(headers, 'Content-Type', 'application/json')
+        start_response(status[0], headers, exc_info[0])
+
+        return output
+
+    def _dispatch_call(self):
+        """
+        Implement dispatch interface specified by WSGIController
+        """
+        try:
+            raw_response = self._inspect_call(self._func)
+            if isinstance(raw_response, HTTPError):
+                self._error = str(raw_response)
+        except JSONRPCError as e:
+            self._error = str(e)
+        except Exception as e:
+            log.error('Encountered unhandled exception: %s' % traceback.format_exc())
+            json_exc = JSONRPCError('Internal server error')
+            self._error = str(json_exc)
+
+        if self._error is not None:
+            raw_response = None
+
+        response = dict(result=raw_response, error=self._error)
+
+        try:
+            return json.dumps(response)
+        except TypeError, e:
+            log.debug('Error encoding response: %s', e)
+            return json.dumps(dict(result=None,
+                                   error="Error encoding response"))
+
+    def _find_method(self):
+        """
+        Return method named by `self._req_method` in controller if able
+        """
+        log.debug('Trying to find JSON-RPC method: %s', self._req_method)
+        if self._req_method.startswith('_'):
+            raise AttributeError("Method not allowed")
+
+        try:
+            func = getattr(self, self._req_method, None)
+        except UnicodeEncodeError:
+            raise AttributeError("Problem decoding unicode in requested "
+                                 "method name.")
+
+        if isinstance(func, types.MethodType):
+            return func
+        else:
+            raise AttributeError("No such method: %s" % self._req_method)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/api/api.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,98 @@
+import traceback
+import logging
+
+from rhodecode.controllers.api import JSONRPCController, JSONRPCError
+from rhodecode.lib.auth import HasPermissionAllDecorator
+from rhodecode.model.scm import ScmModel
+
+from rhodecode.model.db import User, UsersGroup, Repository
+
+log = logging.getLogger(__name__)
+
+
+class ApiController(JSONRPCController):
+    """
+    API Controller
+    
+    
+    Each method needs to have USER as argument this is then based on given
+    API_KEY propagated as instance of user object
+    
+    Preferably this should be first argument also
+    
+    
+    Each function should also **raise** JSONRPCError for any 
+    errors that happens
+    
+    """
+
+    @HasPermissionAllDecorator('hg.admin')
+    def pull(self, apiuser, repo):
+        """
+        Dispatch pull action on given repo
+        
+        
+        :param user:
+        :param repo:
+        """
+
+        if Repository.is_valid(repo) is False:
+            raise JSONRPCError('Unknown repo "%s"' % repo)
+        
+        try:
+            ScmModel().pull_changes(repo, self.rhodecode_user.username)
+            return 'Pulled from %s' % repo
+        except Exception:
+            raise JSONRPCError('Unable to pull changes from "%s"' % repo)
+
+
+    @HasPermissionAllDecorator('hg.admin')
+    def create_user(self, apiuser, username, password, active, admin, name, 
+                    lastname, email):
+        """
+        Creates new user
+        
+        :param apiuser:
+        :param username:
+        :param password:
+        :param active:
+        :param admin:
+        :param name:
+        :param lastname:
+        :param email:
+        """
+        
+        form_data = dict(username=username,
+                         password=password,
+                         active=active,
+                         admin=admin,
+                         name=name,
+                         lastname=lastname,
+                         email=email)
+        try:
+            u = User.create(form_data)
+            return {'id':u.user_id,
+                    'msg':'created new user %s' % name}
+        except Exception:
+            log.error(traceback.format_exc())
+            raise JSONRPCError('failed to create user %s' % name)
+
+
+    @HasPermissionAllDecorator('hg.admin')
+    def create_users_group(self, apiuser, name, active):
+        """
+        Creates an new usergroup
+        
+        :param name:
+        :param active:
+        """
+        form_data = {'users_group_name':name,
+                     'users_group_active':active}
+        try:
+            ug = UsersGroup.create(form_data)
+            return {'id':ug.users_group_id,
+                    'msg':'created new users group %s' % name}
+        except Exception:
+            log.error(traceback.format_exc())
+            raise JSONRPCError('failed to create group %s' % name)
+        
\ No newline at end of file
--- a/rhodecode/controllers/branches.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/branches.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     branches controller for rhodecode
-    
+
     :created_on: Apr 21, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -26,15 +26,16 @@
 import logging
 
 from pylons import tmpl_context as c
+import binascii
 
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
-from rhodecode.lib.utils import OrderedDict
-from rhodecode.model.scm import ScmModel
-
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.lib.odict import OrderedDict
+from rhodecode.lib import safe_unicode
 log = logging.getLogger(__name__)
 
-class BranchesController(BaseController):
+
+class BranchesController(BaseRepoController):
 
     @LoginRequired()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
@@ -43,10 +44,35 @@
         super(BranchesController, self).__before__()
 
     def index(self):
-        hg_model = ScmModel()
-        c.repo_info = hg_model.get_repo(c.repo_name)
-        c.repo_branches = OrderedDict()
-        for name, hash_ in c.repo_info.branches.items():
-            c.repo_branches[name] = c.repo_info.get_changeset(hash_)
+
+        def _branchtags(localrepo):
+
+            bt = {}
+            bt_closed = {}
+
+            for bn, heads in localrepo.branchmap().iteritems():
+                tip = heads[-1]
+                if 'close' not in localrepo.changelog.read(tip)[5]:
+                    bt[bn] = tip
+                else:
+                    bt_closed[bn] = tip
+            return bt, bt_closed
+
+
+        bt, bt_closed = _branchtags(c.rhodecode_repo._repo)
+        cs_g = c.rhodecode_repo.get_changeset
+        _branches = [(safe_unicode(n), cs_g(binascii.hexlify(h)),) for n, h in
+                     bt.items()]
+
+        _closed_branches = [(safe_unicode(n), cs_g(binascii.hexlify(h)),) for n, h in
+                     bt_closed.items()]
+
+        c.repo_branches = OrderedDict(sorted(_branches,
+                                             key=lambda ctx: ctx[0],
+                                             reverse=False))
+        c.repo_closed_branches = OrderedDict(sorted(_closed_branches,
+                                                    key=lambda ctx: ctx[0],
+                                                    reverse=False))
+
 
         return render('branches/branches.html')
--- a/rhodecode/controllers/changelog.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/changelog.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     changelog controller for rhodecode
-    
+
     :created_on: Apr 21, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -31,24 +31,24 @@
     #python 2.5 compatibility
     import simplejson as json
 
-from mercurial.graphmod import colored, CHANGESET, revisions as graph_rev
+from mercurial import graphmod
 from pylons import request, session, tmpl_context as c
 
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
-from rhodecode.model.scm import ScmModel
-
-from webhelpers.paginate import Page
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.lib.helpers import RepoPage
 
 log = logging.getLogger(__name__)
 
-class ChangelogController(BaseController):
+
+class ChangelogController(BaseRepoController):
 
     @LoginRequired()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def __before__(self):
         super(ChangelogController, self).__before__()
+        c.affected_files_cut_off = 60
 
     def index(self):
         limit = 100
@@ -65,40 +65,57 @@
         else:
             c.size = int(session.get('changelog_size', default))
 
-        changesets = ScmModel().get_repo(c.repo_name)
+        p = int(request.params.get('page', 1))
+        branch_name = request.params.get('branch', None)
+        c.total_cs = len(c.rhodecode_repo)
+        c.pagination = RepoPage(c.rhodecode_repo, page=p,
+                                item_count=c.total_cs, items_per_page=c.size,
+                                branch_name=branch_name)
 
-        p = int(request.params.get('page', 1))
-        c.total_cs = len(changesets)
-        c.pagination = Page(changesets, page=p, item_count=c.total_cs,
-                            items_per_page=c.size)
-
-        self._graph(changesets, c.size, p)
+        self._graph(c.rhodecode_repo, c.total_cs, c.size, p)
 
         return render('changelog/changelog.html')
 
+    def changelog_details(self, cs):
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            c.cs = c.rhodecode_repo.get_changeset(cs)
+            return render('changelog/changelog_details.html')
 
-    def _graph(self, repo, size, p):
-        revcount = size
-        if not repo.revisions or repo.alias == 'git':
+    def _graph(self, repo, repo_size, size, p):
+        """
+        Generates a DAG graph for mercurial
+
+        :param repo: repo instance
+        :param size: number of commits to show
+        :param p: page number
+        """
+        if not repo.revisions:
             c.jsdata = json.dumps([])
             return
 
-        max_rev = repo.revisions[-1]
-
+        revcount = min(repo_size, size)
         offset = 1 if p == 1 else  ((p - 1) * revcount + 1)
+        try:
+            rev_end = repo.revisions.index(repo.revisions[(-1 * offset)])
+        except IndexError:
+            rev_end = repo.revisions.index(repo.revisions[-1])
+        rev_start = max(0, rev_end - revcount)
 
-        rev_start = repo.revisions[(-1 * offset)]
+        data = []
+        rev_end += 1
 
-        revcount = min(max_rev, revcount)
-        rev_end = max(0, rev_start - revcount)
-        dag = graph_rev(repo.repo, rev_start, rev_end)
+        if repo.alias == 'git':
+            for _ in xrange(rev_start, rev_end):
+                vtx = [0, 1]
+                edges = [[0, 0, 1]]
+                data.append(['', vtx, edges])
 
-        c.dag = tree = list(colored(dag))
-        data = []
-        for (id, type, ctx, vtx, edges) in tree:
-            if type != CHANGESET:
-                continue
-            data.append(('', vtx, edges))
+        elif repo.alias == 'hg':
+            revs = list(reversed(xrange(rev_start, rev_end)))
+            c.dag = graphmod.colored(graphmod.dagwalker(repo._repo, revs))
+            for (id, type, ctx, vtx, edges) in c.dag:
+                if type != graphmod.CHANGESET:
+                    continue
+                data.append(['', vtx, edges])
 
         c.jsdata = json.dumps(data)
-
--- a/rhodecode/controllers/changeset.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/changeset.py	Fri Oct 07 01:08:50 2011 +0200
@@ -3,11 +3,12 @@
     rhodecode.controllers.changeset
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    changeset controller for pylons
-    
+    changeset controller for pylons showoing changes beetween
+    revisions
+
     :created_on: Apr 25, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -31,26 +32,28 @@
 
 import rhodecode.lib.helpers as h
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
+from rhodecode.lib.base import BaseRepoController, render
 from rhodecode.lib.utils import EmptyChangeset
-from rhodecode.model.scm import ScmModel
+from rhodecode.lib.odict import OrderedDict
 
-from vcs.exceptions import RepositoryError, ChangesetError
+from vcs.exceptions import RepositoryError, ChangesetError, \
+ChangesetDoesNotExistError
 from vcs.nodes import FileNode
 from vcs.utils import diffs as differ
 
 log = logging.getLogger(__name__)
 
-class ChangesetController(BaseController):
+
+class ChangesetController(BaseRepoController):
 
     @LoginRequired()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def __before__(self):
         super(ChangesetController, self).__before__()
+        c.affected_files_cut_off = 60
 
     def index(self, revision):
-        hg_model = ScmModel()
 
         def wrap_to_table(str):
 
@@ -61,94 +64,150 @@
                         </tr>
                       </table>''' % str
 
+        #get ranges of revisions if preset
+        rev_range = revision.split('...')[:2]
+
         try:
-            c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
-        except RepositoryError, e:
+            if len(rev_range) == 2:
+                rev_start = rev_range[0]
+                rev_end = rev_range[1]
+                rev_ranges = c.rhodecode_repo.get_changesets(start=rev_start,
+                                                            end=rev_end)
+            else:
+                rev_ranges = [c.rhodecode_repo.get_changeset(revision)]
+
+            c.cs_ranges = list(rev_ranges)
+
+        except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
             log.error(traceback.format_exc())
             h.flash(str(e), category='warning')
             return redirect(url('home'))
-        else:
+
+        c.changes = OrderedDict()
+        c.sum_added = 0
+        c.sum_removed = 0
+        c.lines_added = 0
+        c.lines_deleted = 0
+        c.cut_off = False  # defines if cut off limit is reached
+
+        # Iterate over ranges (default changeset view is always one changeset)
+        for changeset in c.cs_ranges:
+            c.changes[changeset.raw_id] = []
             try:
-                c.changeset_old = c.changeset.parents[0]
+                changeset_parent = changeset.parents[0]
             except IndexError:
-                c.changeset_old = None
-            c.changes = []
+                changeset_parent = None
 
-            #===================================================================
+            #==================================================================
             # ADDED FILES
-            #===================================================================
-            c.sum_added = 0
-            for node in c.changeset.added:
+            #==================================================================
+            for node in changeset.added:
 
                 filenode_old = FileNode(node.path, '', EmptyChangeset())
                 if filenode_old.is_binary or node.is_binary:
                     diff = wrap_to_table(_('binary file'))
+                    st = (0, 0)
                 else:
+                    # in this case node.size is good parameter since those are
+                    # added nodes and their size defines how many changes were
+                    # made
                     c.sum_added += node.size
                     if c.sum_added < self.cut_off_limit:
-                        f_udiff = differ.get_udiff(filenode_old, node)
-                        diff = differ.DiffProcessor(f_udiff).as_html()
+                        f_gitdiff = differ.get_gitdiff(filenode_old, node)
+                        d = differ.DiffProcessor(f_gitdiff, format='gitdiff')
+
+                        st = d.stat()
+                        diff = d.as_html()
 
                     else:
-                        diff = wrap_to_table(_('Changeset is to big and was cut'
-                                            ' off, see raw changeset instead'))
+                        diff = wrap_to_table(_('Changeset is to big and '
+                                               'was cut off, see raw '
+                                               'changeset instead'))
+                        c.cut_off = True
+                        break
 
                 cs1 = None
                 cs2 = node.last_changeset.raw_id
-                c.changes.append(('added', node, diff, cs1, cs2))
+                c.lines_added += st[0]
+                c.lines_deleted += st[1]
+                c.changes[changeset.raw_id].append(('added', node, diff,
+                                                    cs1, cs2, st))
 
-            #===================================================================
+            #==================================================================
             # CHANGED FILES
-            #===================================================================
-            c.sum_removed = 0
-            for node in c.changeset.changed:
-                try:
-                    filenode_old = c.changeset_old.get_node(node.path)
-                except ChangesetError:
-                    filenode_old = FileNode(node.path, '', EmptyChangeset())
+            #==================================================================
+            if not c.cut_off:
+                for node in changeset.changed:
+                    try:
+                        filenode_old = changeset_parent.get_node(node.path)
+                    except ChangesetError:
+                        log.warning('Unable to fetch parent node for diff')
+                        filenode_old = FileNode(node.path, '',
+                                                EmptyChangeset())
 
-                if filenode_old.is_binary or node.is_binary:
-                    diff = wrap_to_table(_('binary file'))
-                else:
+                    if filenode_old.is_binary or node.is_binary:
+                        diff = wrap_to_table(_('binary file'))
+                        st = (0, 0)
+                    else:
 
-                    if c.sum_removed < self.cut_off_limit:
-                        f_udiff = differ.get_udiff(filenode_old, node)
-                        diff = differ.DiffProcessor(f_udiff).as_html()
-                        if diff:
-                            c.sum_removed += len(diff)
-                    else:
-                        diff = wrap_to_table(_('Changeset is to big and was cut'
-                                            ' off, see raw changeset instead'))
+                        if c.sum_removed < self.cut_off_limit:
+                            f_gitdiff = differ.get_gitdiff(filenode_old, node)
+                            d = differ.DiffProcessor(f_gitdiff,
+                                                     format='gitdiff')
+                            st = d.stat()
+                            if (st[0] + st[1]) * 256 > self.cut_off_limit:
+                                diff = wrap_to_table(_('Diff is to big '
+                                                       'and was cut off, see '
+                                                       'raw diff instead'))
+                            else:
+                                diff = d.as_html()
 
+                            if diff:
+                                c.sum_removed += len(diff)
+                        else:
+                            diff = wrap_to_table(_('Changeset is to big and '
+                                                   'was cut off, see raw '
+                                                   'changeset instead'))
+                            c.cut_off = True
+                            break
 
-                cs1 = filenode_old.last_changeset.raw_id
-                cs2 = node.last_changeset.raw_id
-                c.changes.append(('changed', node, diff, cs1, cs2))
+                    cs1 = filenode_old.last_changeset.raw_id
+                    cs2 = node.last_changeset.raw_id
+                    c.lines_added += st[0]
+                    c.lines_deleted += st[1]
+                    c.changes[changeset.raw_id].append(('changed', node, diff,
+                                                        cs1, cs2, st))
 
-            #===================================================================
-            # REMOVED FILES    
-            #===================================================================
-            for node in c.changeset.removed:
-                c.changes.append(('removed', node, None, None, None))
+            #==================================================================
+            # REMOVED FILES
+            #==================================================================
+            if not c.cut_off:
+                for node in changeset.removed:
+                    c.changes[changeset.raw_id].append(('removed', node, None,
+                                                        None, None, (0, 0)))
 
-        return render('changeset/changeset.html')
+        if len(c.cs_ranges) == 1:
+            c.changeset = c.cs_ranges[0]
+            c.changes = c.changes[c.changeset.raw_id]
+
+            return render('changeset/changeset.html')
+        else:
+            return render('changeset/changeset_range.html')
 
     def raw_changeset(self, revision):
 
-        hg_model = ScmModel()
         method = request.GET.get('diff', 'show')
         try:
-            r = hg_model.get_repo(c.repo_name)
-            c.scm_type = r.alias
-            c.changeset = r.get_changeset(revision)
+            c.scm_type = c.rhodecode_repo.alias
+            c.changeset = c.rhodecode_repo.get_changeset(revision)
         except RepositoryError:
             log.error(traceback.format_exc())
             return redirect(url('home'))
         else:
             try:
-                c.changeset_old = c.changeset.parents[0]
+                c.changeset_parent = c.changeset.parents[0]
             except IndexError:
-                c.changeset_old = None
+                c.changeset_parent = None
             c.changes = []
 
             for node in c.changeset.added:
@@ -156,20 +215,22 @@
                 if filenode_old.is_binary or node.is_binary:
                     diff = _('binary file') + '\n'
                 else:
-                    f_udiff = differ.get_udiff(filenode_old, node)
-                    diff = differ.DiffProcessor(f_udiff).raw_diff()
+                    f_gitdiff = differ.get_gitdiff(filenode_old, node)
+                    diff = differ.DiffProcessor(f_gitdiff,
+                                                format='gitdiff').raw_diff()
 
                 cs1 = None
                 cs2 = node.last_changeset.raw_id
                 c.changes.append(('added', node, diff, cs1, cs2))
 
             for node in c.changeset.changed:
-                filenode_old = c.changeset_old.get_node(node.path)
+                filenode_old = c.changeset_parent.get_node(node.path)
                 if filenode_old.is_binary or node.is_binary:
                     diff = _('binary file')
                 else:
-                    f_udiff = differ.get_udiff(filenode_old, node)
-                    diff = differ.DiffProcessor(f_udiff).raw_diff()
+                    f_gitdiff = differ.get_gitdiff(filenode_old, node)
+                    diff = differ.DiffProcessor(f_gitdiff,
+                                                format='gitdiff').raw_diff()
 
                 cs1 = filenode_old.last_changeset.raw_id
                 cs2 = node.last_changeset.raw_id
@@ -178,10 +239,11 @@
         response.content_type = 'text/plain'
 
         if method == 'download':
-            response.content_disposition = 'attachment; filename=%s.patch' % revision
+            response.content_disposition = 'attachment; filename=%s.patch' \
+                                            % revision
 
-        parent = True if len(c.changeset.parents) > 0 else False
-        c.parent_tmpl = 'Parent  %s' % c.changeset.parents[0].raw_id if parent else ''
+        c.parent_tmpl = ''.join(['# Parent  %s\n' % x.raw_id for x in
+                                                 c.changeset.parents])
 
         c.diffs = ''
         for x in c.changes:
--- a/rhodecode/controllers/error.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/error.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 """
-    package.rhodecode.controllers.error
-    ~~~~~~~~~~~~~~
+    rhodecode.controllers.error
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     RhodeCode error controller
-    
+
     :created_on: Dec 8, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -27,7 +27,7 @@
 import logging
 import paste.fileapp
 
-from pylons import tmpl_context as c, request, config
+from pylons import tmpl_context as c, request, config, url
 from pylons.i18n.translation import _
 from pylons.middleware import  media_path
 
@@ -35,6 +35,7 @@
 
 log = logging.getLogger(__name__)
 
+
 class ErrorController(BaseController):
     """Generates error documents as and when they are required.
 
@@ -46,31 +47,30 @@
     """
 
     def __before__(self):
-        c.rhodecode_name = config.get('rhodecode_title')
+        #disable all base actions since we don't need them here
+        pass
 
     def document(self):
         resp = request.environ.get('pylons.original_response')
+        c.rhodecode_name = config.get('rhodecode_title')
 
         log.debug('### %s ###', resp.status)
 
         e = request.environ
-        c.serv_p = r'%(protocol)s://%(host)s/' % {
-                                                'protocol': e.get('wsgi.url_scheme'),
-                                                'host':e.get('HTTP_HOST'),
-                                                }
-
+        c.serv_p = r'%(protocol)s://%(host)s/' \
+                                    % {'protocol': e.get('wsgi.url_scheme'),
+                                       'host': e.get('HTTP_HOST'), }
 
         c.error_message = cgi.escape(request.GET.get('code', str(resp.status)))
         c.error_explanation = self.get_error_explanation(resp.status_int)
 
-        #redirect to when error with given seconds
+        #  redirect to when error with given seconds
         c.redirect_time = 0
-        c.redirect_module = _('Home page')# name to what your going to be redirected
+        c.redirect_module = _('Home page')
         c.url_redirect = "/"
 
         return render('/errors/error_document.html')
 
-
     def img(self, id):
         """Serve Pylons' stock images"""
         return self._serve_file(os.path.join(media_path, 'img', id))
@@ -95,7 +95,8 @@
             code = 500
 
         if code == 400:
-            return _('The request could not be understood by the server due to malformed syntax.')
+            return _('The request could not be understood by the server'
+                     ' due to malformed syntax.')
         if code == 401:
             return _('Unauthorized access to resource')
         if code == 403:
@@ -103,6 +104,5 @@
         if code == 404:
             return _('The resource could not be found')
         if code == 500:
-            return _('The server encountered an unexpected condition which prevented it from fulfilling the request.')
-
-
+            return _('The server encountered an unexpected condition'
+                     ' which prevented it from fulfilling the request.')
--- a/rhodecode/controllers/feed.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/feed.py	Fri Oct 07 01:08:50 2011 +0200
@@ -25,64 +25,92 @@
 
 import logging
 
-from pylons import url, response
+from pylons import url, response, tmpl_context as c
+from pylons.i18n.translation import _
 
+from rhodecode.lib import safe_unicode
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController
-from rhodecode.model.scm import ScmModel
+from rhodecode.lib.base import BaseRepoController
 
 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 
 log = logging.getLogger(__name__)
 
-class FeedController(BaseController):
 
-    @LoginRequired()
+class FeedController(BaseRepoController):
+
+    @LoginRequired(api_access=True)
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def __before__(self):
         super(FeedController, self).__before__()
         #common values for feeds
-        self.description = 'Changes on %s repository'
-        self.title = "%s feed"
+        self.description = _('Changes on %s repository')
+        self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
         self.language = 'en-us'
         self.ttl = "5"
         self.feed_nr = 10
 
+    def __changes(self, cs):
+        changes = []
+
+        a = [safe_unicode(n.path) for n in cs.added]
+        if a:
+            changes.append('\nA ' + '\nA '.join(a))
+
+        m = [safe_unicode(n.path) for n in cs.changed]
+        if m:
+            changes.append('\nM ' + '\nM '.join(m))
+
+        d = [safe_unicode(n.path) for n in cs.removed]
+        if d:
+            changes.append('\nD ' + '\nD '.join(d))
+
+        changes.append('</pre>')
+
+        return ''.join(changes)
+
     def atom(self, repo_name):
         """Produce an atom-1.0 feed via feedgenerator module"""
         feed = Atom1Feed(title=self.title % repo_name,
-                         link=url('summary_home', repo_name=repo_name, qualified=True),
+                         link=url('summary_home', repo_name=repo_name,
+                                  qualified=True),
                          description=self.description % repo_name,
                          language=self.language,
                          ttl=self.ttl)
+        desc_msg = []
+        for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
+            desc_msg.append('%s - %s<br/><pre>' % (cs.author, cs.date))
+            desc_msg.append(self.__changes(cs))
 
-        changesets = ScmModel().get_repo(repo_name)
-
-        for cs in changesets[:self.feed_nr]:
             feed.add_item(title=cs.message,
                           link=url('changeset_home', repo_name=repo_name,
                                    revision=cs.raw_id, qualified=True),
-                                   description=str(cs.date))
+                          author_name=cs.author,
+                          description=''.join(desc_msg))
 
         response.content_type = feed.mime_type
         return feed.writeString('utf-8')
 
-
     def rss(self, repo_name):
         """Produce an rss2 feed via feedgenerator module"""
         feed = Rss201rev2Feed(title=self.title % repo_name,
-                         link=url('summary_home', repo_name=repo_name, qualified=True),
+                         link=url('summary_home', repo_name=repo_name,
+                                  qualified=True),
                          description=self.description % repo_name,
                          language=self.language,
                          ttl=self.ttl)
+        desc_msg = []
+        for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
+            desc_msg.append('%s - %s<br/><pre>' % (cs.author, cs.date))
+            desc_msg.append(self.__changes(cs))
 
-        changesets = ScmModel().get_repo(repo_name)
-        for cs in changesets[:self.feed_nr]:
             feed.add_item(title=cs.message,
                           link=url('changeset_home', repo_name=repo_name,
                                    revision=cs.raw_id, qualified=True),
-                          description=str(cs.date))
+                          author_name=cs.author,
+                          description=''.join(desc_msg),
+                         )
 
         response.content_type = feed.mime_type
         return feed.writeString('utf-8')
--- a/rhodecode/controllers/files.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/files.py	Fri Oct 07 01:08:50 2011 +0200
@@ -22,40 +22,42 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
 import os
-import tempfile
 import logging
-import rhodecode.lib.helpers as h
+import traceback
 
-from mercurial import archival
+from os.path import join as jn
 
 from pylons import request, response, session, tmpl_context as c, url
 from pylons.i18n.translation import _
 from pylons.controllers.util import redirect
+from pylons.decorators import jsonify
 
+from vcs.conf import settings
+from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
+    EmptyRepositoryError, ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError
+from vcs.nodes import FileNode, NodeKind
+from vcs.utils import diffs as differ
+
+from rhodecode.lib import convert_line_endings, detect_mode, safe_str
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
+from rhodecode.lib.base import BaseRepoController, render
 from rhodecode.lib.utils import EmptyChangeset
-from rhodecode.model.scm import ScmModel
-
-from vcs.exceptions import RepositoryError, ChangesetError, \
-    ChangesetDoesNotExistError, EmptyRepositoryError
-from vcs.nodes import FileNode
-from vcs.utils import diffs as differ
+import rhodecode.lib.helpers as h
+from rhodecode.model.repo import RepoModel
 
 log = logging.getLogger(__name__)
 
 
-class FilesController(BaseController):
+class FilesController(BaseRepoController):
 
     @LoginRequired()
-    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
-                                   'repository.admin')
     def __before__(self):
         super(FilesController, self).__before__()
         c.cut_off_limit = self.cut_off_limit
 
-    def __get_cs_or_redirect(self, rev, repo_name):
+    def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True):
         """
         Safe way to get changeset if error occur it redirects to tip with
         proper message
@@ -64,196 +66,412 @@
         :param repo_name: repo name to redirect after
         """
 
-        _repo = ScmModel().get_repo(c.repo_name)
         try:
-            return _repo.get_changeset(rev)
+            return c.rhodecode_repo.get_changeset(rev)
         except EmptyRepositoryError, e:
-            h.flash(_('There are no files yet'), category='warning')
+            if not redirect_after:
+                return None
+            url_ = url('files_add_home',
+                       repo_name=c.repo_name,
+                       revision=0, f_path='')
+            add_new = '<a href="%s">[%s]</a>' % (url_, _('add new'))
+            h.flash(h.literal(_('There are no files yet %s' % add_new)),
+                    category='warning')
             redirect(h.url('summary_home', repo_name=repo_name))
 
         except RepositoryError, e:
             h.flash(str(e), category='warning')
             redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
 
-    def index(self, repo_name, revision, f_path):
-        cs = self.__get_cs_or_redirect(revision, repo_name)
-        c.repo = ScmModel().get_repo(c.repo_name)
-
-        revision = request.POST.get('at_rev', None) or revision
-
-        def get_next_rev(cur):
-            max_rev = len(c.repo.revisions) - 1
-            r = cur + 1
-            if r > max_rev:
-                r = max_rev
-            return r
+    def __get_filenode_or_redirect(self, repo_name, cs, path):
+        """
+        Returns file_node, if error occurs or given path is directory,
+        it'll redirect to top level path
 
-        def get_prev_rev(cur):
-            r = cur - 1
-            return r
-
-        c.f_path = f_path
-        c.changeset = cs
-        cur_rev = c.changeset.revision
-        prev_rev = c.repo.get_changeset(get_prev_rev(cur_rev)).raw_id
-        next_rev = c.repo.get_changeset(get_next_rev(cur_rev)).raw_id
-
-        c.url_prev = url('files_home', repo_name=c.repo_name,
-                         revision=prev_rev, f_path=f_path)
-        c.url_next = url('files_home', repo_name=c.repo_name,
-                     revision=next_rev, f_path=f_path)
+        :param repo_name: repo_name
+        :param cs: given changeset
+        :param path: path to lookup
+        """
 
         try:
-            c.files_list = c.changeset.get_node(f_path)
-            c.file_history = self._get_history(c.repo, c.files_list, f_path)
-        except RepositoryError, e:
-            h.flash(str(e), category='warning')
-            redirect(h.url('files_home', repo_name=repo_name,
-                           revision=revision))
-
-
-        return render('files/files.html')
-
-    def rawfile(self, repo_name, revision, f_path):
-        cs = self.__get_cs_or_redirect(revision, repo_name)
-        try:
-            file_node = cs.get_node(f_path)
-        except RepositoryError, e:
-            h.flash(str(e), category='warning')
-            redirect(h.url('files_home', repo_name=repo_name,
-                           revision=cs.raw_id))
-
-        fname = f_path.split(os.sep)[-1].encode('utf8', 'replace')
-
-        response.content_disposition = 'attachment; filename=%s' % fname
-        response.content_type = file_node.mimetype
-        return file_node.content
-
-    def raw(self, repo_name, revision, f_path):
-        cs = self.__get_cs_or_redirect(revision, repo_name)
-        try:
-            file_node = cs.get_node(f_path)
+            file_node = cs.get_node(path)
+            if file_node.is_dir():
+                raise RepositoryError('given path is a directory')
         except RepositoryError, e:
             h.flash(str(e), category='warning')
             redirect(h.url('files_home', repo_name=repo_name,
                            revision=cs.raw_id))
 
-        response.content_type = 'text/plain'
-        return file_node.content
+        return file_node
+
 
-    def annotate(self, repo_name, revision, f_path):
-        cs = self.__get_cs_or_redirect(revision, repo_name)
+    def __get_paths(self, changeset, starting_path):
+        """recursive walk in root dir and return a set of all path in that dir
+        based on repository walk function
+        """
+        _files = list()
+        _dirs = list()
+
         try:
-            c.file = cs.get_node(f_path)
+            tip = changeset
+            for topnode, dirs, files in tip.walk(starting_path):
+                for f in files:
+                    _files.append(f.path)
+                for d in dirs:
+                    _dirs.append(d.path)
         except RepositoryError, e:
-            h.flash(str(e), category='warning')
-            redirect(h.url('files_home', repo_name=repo_name, revision=cs.raw_id))
+            log.debug(traceback.format_exc())
+            pass
+        return _dirs, _files
 
-        c.file_history = self._get_history(ScmModel().get_repo(c.repo_name), c.file, f_path)
-        c.cs = cs
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def index(self, repo_name, revision, f_path):
+        #reditect to given revision from form if given
+        post_revision = request.POST.get('at_rev', None)
+        if post_revision:
+            cs = self.__get_cs_or_redirect(post_revision, repo_name)
+            redirect(url('files_home', repo_name=c.repo_name,
+                         revision=cs.raw_id, f_path=f_path))
+
+        c.changeset = self.__get_cs_or_redirect(revision, repo_name)
+        c.branch = request.GET.get('branch', None)
         c.f_path = f_path
 
+        cur_rev = c.changeset.revision
+
+        #prev link
+        try:
+            prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
+            c.url_prev = url('files_home', repo_name=c.repo_name,
+                         revision=prev_rev.raw_id, f_path=f_path)
+            if c.branch:
+                c.url_prev += '?branch=%s' % c.branch
+        except (ChangesetDoesNotExistError, VCSError):
+            c.url_prev = '#'
+
+        #next link
+        try:
+            next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
+            c.url_next = url('files_home', repo_name=c.repo_name,
+                     revision=next_rev.raw_id, f_path=f_path)
+            if c.branch:
+                c.url_next += '?branch=%s' % c.branch
+        except (ChangesetDoesNotExistError, VCSError):
+            c.url_next = '#'
+
+        #files or dirs
+        try:
+            c.files_list = c.changeset.get_node(f_path)
+
+            if c.files_list.is_file():
+                c.file_history = self._get_node_history(c.changeset, f_path)
+            else:
+                c.file_history = []
+        except RepositoryError, e:
+            h.flash(str(e), category='warning')
+            redirect(h.url('files_home', repo_name=repo_name,
+                           revision=revision))
+
+        return render('files/files.html')
+
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def rawfile(self, repo_name, revision, f_path):
+        cs = self.__get_cs_or_redirect(revision, repo_name)
+        file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
+
+        response.content_disposition = 'attachment; filename=%s' % \
+            safe_str(f_path.split(os.sep)[-1])
+
+        response.content_type = file_node.mimetype
+        return file_node.content
+
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def raw(self, repo_name, revision, f_path):
+        cs = self.__get_cs_or_redirect(revision, repo_name)
+        file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
+
+        raw_mimetype_mapping = {
+            # map original mimetype to a mimetype used for "show as raw"
+            # you can also provide a content-disposition to override the
+            # default "attachment" disposition.
+            # orig_type: (new_type, new_dispo)
+
+            # show images inline:
+            'image/x-icon': ('image/x-icon', 'inline'),
+            'image/png': ('image/png', 'inline'),
+            'image/gif': ('image/gif', 'inline'),
+            'image/jpeg': ('image/jpeg', 'inline'),
+            'image/svg+xml': ('image/svg+xml', 'inline'),
+        }
+
+        mimetype = file_node.mimetype
+        try:
+            mimetype, dispo = raw_mimetype_mapping[mimetype]
+        except KeyError:
+            # we don't know anything special about this, handle it safely
+            if file_node.is_binary:
+                # do same as download raw for binary files
+                mimetype, dispo = 'application/octet-stream', 'attachment'
+            else:
+                # do not just use the original mimetype, but force text/plain,
+                # otherwise it would serve text/html and that might be unsafe.
+                # Note: underlying vcs library fakes text/plain mimetype if the
+                # mimetype can not be determined and it thinks it is not
+                # binary.This might lead to erroneous text display in some
+                # cases, but helps in other cases, like with text files
+                # without extension.
+                mimetype, dispo = 'text/plain', 'inline'
+
+        if dispo == 'attachment':
+            dispo = 'attachment; filename=%s' % \
+                        safe_str(f_path.split(os.sep)[-1])
+
+        response.content_disposition = dispo
+        response.content_type = mimetype
+        return file_node.content
+
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def annotate(self, repo_name, revision, f_path):
+        c.cs = self.__get_cs_or_redirect(revision, repo_name)
+        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
+
+        c.file_history = self._get_node_history(c.cs, f_path)
+        c.f_path = f_path
         return render('files/files_annotate.html')
 
-    def archivefile(self, repo_name, revision, fileformat):
-        archive_specs = {
-          '.tar.bz2': ('application/x-bzip2', 'tbz2'),
-          '.tar.gz': ('application/x-gzip', 'tgz'),
-          '.zip': ('application/zip', 'zip'),
-        }
-        if not archive_specs.has_key(fileformat):
-            return 'Unknown archive type %s' % fileformat
+    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
+    def edit(self, repo_name, revision, f_path):
+        r_post = request.POST
+
+        c.cs = self.__get_cs_or_redirect(revision, repo_name)
+        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
+
+        if c.file.is_binary:
+            return redirect(url('files_home', repo_name=c.repo_name,
+                         revision=c.cs.raw_id, f_path=f_path))
+
+        c.f_path = f_path
+
+        if r_post:
+
+            old_content = c.file.content
+            sl = old_content.splitlines(1)
+            first_line = sl[0] if sl else ''
+            # modes:  0 - Unix, 1 - Mac, 2 - DOS
+            mode = detect_mode(first_line, 0)
+            content = convert_line_endings(r_post.get('content'), mode)
+
+            message = r_post.get('message') or (_('Edited %s via RhodeCode')
+                                                % (f_path))
+            author = self.rhodecode_user.full_contact
+
+            if content == old_content:
+                h.flash(_('No changes'),
+                    category='warning')
+                return redirect(url('changeset_home', repo_name=c.repo_name,
+                                    revision='tip'))
+
+            try:
+                self.scm_model.commit_change(repo=c.rhodecode_repo,
+                                             repo_name=repo_name, cs=c.cs,
+                                             user=self.rhodecode_user,
+                                             author=author, message=message,
+                                             content=content, f_path=f_path)
+                h.flash(_('Successfully committed to %s' % f_path),
+                        category='success')
+
+            except Exception:
+                log.error(traceback.format_exc())
+                h.flash(_('Error occurred during commit'), category='error')
+            return redirect(url('changeset_home',
+                                repo_name=c.repo_name, revision='tip'))
+
+        return render('files/files_edit.html')
+
+    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
+    def add(self, repo_name, revision, f_path):
+        r_post = request.POST
+        c.cs = self.__get_cs_or_redirect(revision, repo_name,
+                                         redirect_after=False)
+        if c.cs is None:
+            c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias)
+
+        c.f_path = f_path
+
+        if r_post:
+            unix_mode = 0
+            content = convert_line_endings(r_post.get('content'), unix_mode)
+
+            message = r_post.get('message') or (_('Added %s via RhodeCode')
+                                                % (f_path))
+            location = r_post.get('location')
+            filename = r_post.get('filename')
+            file_obj = r_post.get('upload_file', None)
+
+            if file_obj is not None and hasattr(file_obj, 'filename'):
+                filename = file_obj.filename
+                content = file_obj.file
 
-        def read_in_chunks(file_object, chunk_size=1024 * 40):
-            """Lazy function (generator) to read a file piece by piece.
-            Default chunk size: 40k."""
+            node_path = os.path.join(location, filename)
+            author = self.rhodecode_user.full_contact
+
+            if not content:
+                h.flash(_('No content'), category='warning')
+                return redirect(url('changeset_home', repo_name=c.repo_name,
+                                    revision='tip'))
+            if not filename:
+                h.flash(_('No filename'), category='warning')
+                return redirect(url('changeset_home', repo_name=c.repo_name,
+                                    revision='tip'))
+
+            try:
+                self.scm_model.create_node(repo=c.rhodecode_repo,
+                                             repo_name=repo_name, cs=c.cs,
+                                             user=self.rhodecode_user,
+                                             author=author, message=message,
+                                             content=content, f_path=node_path)
+                h.flash(_('Successfully committed to %s' % node_path),
+                        category='success')
+            except NodeAlreadyExistsError, e:
+                h.flash(_(e), category='error')
+            except Exception:
+                log.error(traceback.format_exc())
+                h.flash(_('Error occurred during commit'), category='error')
+            return redirect(url('changeset_home',
+                                repo_name=c.repo_name, revision='tip'))
+
+        return render('files/files_add.html')
+
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def archivefile(self, repo_name, fname):
+
+        fileformat = None
+        revision = None
+        ext = None
+        subrepos = request.GET.get('subrepos') == 'true'
+
+        for a_type, ext_data in settings.ARCHIVE_SPECS.items():
+            archive_spec = fname.split(ext_data[1])
+            if len(archive_spec) == 2 and archive_spec[1] == '':
+                fileformat = a_type or ext_data[1]
+                revision = archive_spec[0]
+                ext = ext_data[1]
+
+        try:
+            dbrepo = RepoModel().get_by_repo_name(repo_name)
+            if dbrepo.enable_downloads is False:
+                return _('downloads disabled')
+
+            cs = c.rhodecode_repo.get_changeset(revision)
+            content_type = settings.ARCHIVE_SPECS[fileformat][0]
+        except ChangesetDoesNotExistError:
+            return _('Unknown revision %s') % revision
+        except EmptyRepositoryError:
+            return _('Empty repository')
+        except (ImproperArchiveTypeError, KeyError):
+            return _('Unknown archive type')
+
+        response.content_type = content_type
+        response.content_disposition = 'attachment; filename=%s-%s%s' \
+            % (repo_name, revision, ext)
+
+        import tempfile
+        archive = tempfile.mkstemp()[1]
+        t = open(archive, 'wb')
+        cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
+
+        def get_chunked_archive(archive):
+            stream = open(archive, 'rb')
             while True:
-                data = file_object.read(chunk_size)
+                data = stream.read(4096)
                 if not data:
+                    os.remove(archive)
                     break
                 yield data
 
-        archive = tempfile.TemporaryFile()
-        repo = ScmModel().get_repo(repo_name).repo
-        fname = '%s-%s%s' % (repo_name, revision, fileformat)
-        archival.archive(repo, archive, revision, archive_specs[fileformat][1],
-                         prefix='%s-%s' % (repo_name, revision))
-        response.content_type = archive_specs[fileformat][0]
-        response.content_disposition = 'attachment; filename=%s' % fname
-        archive.seek(0)
-        return read_in_chunks(archive)
+        return get_chunked_archive(archive)
 
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
     def diff(self, repo_name, f_path):
-        hg_model = ScmModel()
         diff1 = request.GET.get('diff1')
         diff2 = request.GET.get('diff2')
         c.action = request.GET.get('diff')
         c.no_changes = diff1 == diff2
         c.f_path = f_path
-        c.repo = hg_model.get_repo(c.repo_name)
+        c.big_diff = False
 
         try:
             if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
-                c.changeset_1 = c.repo.get_changeset(diff1)
+                c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
                 node1 = c.changeset_1.get_node(f_path)
             else:
-                c.changeset_1 = EmptyChangeset()
+                c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
                 node1 = FileNode('.', '', changeset=c.changeset_1)
 
             if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
-                c.changeset_2 = c.repo.get_changeset(diff2)
+                c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
                 node2 = c.changeset_2.get_node(f_path)
             else:
-                c.changeset_2 = EmptyChangeset()
+                c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
                 node2 = FileNode('.', '', changeset=c.changeset_2)
         except RepositoryError:
             return redirect(url('files_home',
                                 repo_name=c.repo_name, f_path=f_path))
 
-        f_udiff = differ.get_udiff(node1, node2)
-        diff = differ.DiffProcessor(f_udiff)
+        if c.action == 'download':
+            diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
+                                        format='gitdiff')
 
-        if c.action == 'download':
             diff_name = '%s_vs_%s.diff' % (diff1, diff2)
             response.content_type = 'text/plain'
             response.content_disposition = 'attachment; filename=%s' \
                                                     % diff_name
-            if node1.is_binary or node2.is_binary:
-                return _('binary file changed')
             return diff.raw_diff()
 
         elif c.action == 'raw':
+            diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
+                                        format='gitdiff')
             response.content_type = 'text/plain'
-            if node1.is_binary or node2.is_binary:
-                return _('binary file changed')
             return diff.raw_diff()
 
         elif c.action == 'diff':
-            if  node1.is_binary or node2.is_binary:
+            if node1.is_binary or node2.is_binary:
                 c.cur_diff = _('Binary file')
             elif node1.size > self.cut_off_limit or \
                     node2.size > self.cut_off_limit:
-                c.cur_diff = _('Diff is too big to display')
+                c.cur_diff = ''
+                c.big_diff = True
             else:
+                diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
+                                        format='gitdiff')
                 c.cur_diff = diff.as_html()
         else:
+
             #default option
-            if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
-                c.cur_diff = _('Diff is to big to display')
-            elif node1.is_binary or node2.is_binary:
+            if node1.is_binary or node2.is_binary:
                 c.cur_diff = _('Binary file')
+            elif node1.size > self.cut_off_limit or \
+                    node2.size > self.cut_off_limit:
+                c.cur_diff = ''
+                c.big_diff = True
+
             else:
+                diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
+                                        format='gitdiff')
                 c.cur_diff = diff.as_html()
 
-        if not c.cur_diff:
+        if not c.cur_diff and not c.big_diff:
             c.no_changes = True
         return render('files/file_diff.html')
 
-    def _get_history(self, repo, node, f_path):
-        from vcs.nodes import NodeKind
-        if not node.kind is NodeKind.FILE:
-            return []
-        changesets = node.history
+    def _get_node_history(self, cs, f_path):
+        changesets = cs.get_file_history(f_path)
         hist_l = []
 
         changesets_group = ([], _("Changesets"))
@@ -266,14 +484,24 @@
 
         hist_l.append(changesets_group)
 
-        for name, chs in c.repository_branches.items():
+        for name, chs in c.rhodecode_repo.branches.items():
             #chs = chs.split(':')[-1]
             branches_group[0].append((chs, name),)
         hist_l.append(branches_group)
 
-        for name, chs in c.repository_tags.items():
+        for name, chs in c.rhodecode_repo.tags.items():
             #chs = chs.split(':')[-1]
             tags_group[0].append((chs, name),)
         hist_l.append(tags_group)
 
         return hist_l
+
+    @jsonify
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def nodelist(self, repo_name, revision, f_path):
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            cs = self.__get_cs_or_redirect(revision, repo_name)
+            _d, _f = self.__get_paths(cs, f_path)
+            return _d + _f
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/followers.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.controllers.followers
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Followers controller for rhodecode
+
+    :created_on: Apr 23, 2011
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+import logging
+
+from pylons import tmpl_context as c, request
+
+from rhodecode.lib.helpers import Page
+from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.model.db import Repository, User, UserFollowing
+
+log = logging.getLogger(__name__)
+
+
+class FollowersController(BaseRepoController):
+
+    @LoginRequired()
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def __before__(self):
+        super(FollowersController, self).__before__()
+
+    def followers(self, repo_name):
+        p = int(request.params.get('page', 1))
+        repo_id = c.rhodecode_db_repo.repo_id
+        d = UserFollowing.get_repo_followers(repo_id)\
+            .order_by(UserFollowing.follows_from)
+        c.followers_pager = Page(d, page=p, items_per_page=20)
+
+        c.followers_data = render('/followers/followers_data.html')
+
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            return c.followers_data
+
+        return render('/followers/followers.html')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/forks.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.controllers.forks
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    forks controller for rhodecode
+
+    :created_on: Apr 23, 2011
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+import logging
+
+from pylons import tmpl_context as c, request
+
+from rhodecode.lib.helpers import Page
+from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.model.db import Repository, User, UserFollowing
+
+log = logging.getLogger(__name__)
+
+
+class ForksController(BaseRepoController):
+
+    @LoginRequired()
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def __before__(self):
+        super(ForksController, self).__before__()
+
+    def forks(self, repo_name):
+        p = int(request.params.get('page', 1))
+        repo_id = c.rhodecode_db_repo.repo_id
+        d = Repository.get_repo_forks(repo_id)
+        c.forks_pager = Page(d, page=p, items_per_page=20)
+
+        c.forks_data = render('/forks/forks_data.html')
+
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            return c.forks_data
+
+        return render('/forks/forks.html')
--- a/rhodecode/controllers/home.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/home.py	Fri Oct 07 01:08:50 2011 +0200
@@ -27,13 +27,15 @@
 from operator import itemgetter
 
 from pylons import tmpl_context as c, request
+from paste.httpexceptions import HTTPBadRequest
 
 from rhodecode.lib.auth import LoginRequired
 from rhodecode.lib.base import BaseController, render
-from rhodecode.model.scm import ScmModel
+from rhodecode.model.db import Group, Repository
 
 log = logging.getLogger(__name__)
 
+
 class HomeController(BaseController):
 
     @LoginRequired()
@@ -41,24 +43,18 @@
         super(HomeController, self).__before__()
 
     def index(self):
-        sortables = ['name', 'description', 'last_change', 'tip', 'owner']
-        current_sort = request.GET.get('sort', 'name')
-        current_sort_slug = current_sort.replace('-', '')
 
-        if current_sort_slug not in sortables:
-            c.sort_by = 'name'
-            current_sort_slug = c.sort_by
-        else:
-            c.sort_by = current_sort
-        c.sort_slug = current_sort_slug
-        cached_repo_list = ScmModel().get_repos()
+        c.repos_list = self.scm_model.get_repos()
 
-        sort_key = current_sort_slug + '_sort'
-        if c.sort_by.startswith('-'):
-            c.repos_list = sorted(cached_repo_list, key=itemgetter(sort_key),
-                                  reverse=True)
-        else:
-            c.repos_list = sorted(cached_repo_list, key=itemgetter(sort_key),
-                                  reverse=False)
+        c.groups = Group.query().filter(Group.group_parent_id == None).all()
 
         return render('/index.html')
+
+    def repo_switcher(self):
+        if request.is_xhr:
+            all_repos = Repository.query().order_by(Repository.repo_name).all()
+            c.repos_list = self.scm_model.get_repos(all_repos,
+                                                    sort_key='name_sort')
+            return render('/repo_switcher_list.html')
+        else:
+            return HTTPBadRequest()
--- a/rhodecode/controllers/journal.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/journal.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Journal controller for pylons
-    
+
     :created_on: Nov 21, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -22,77 +22,209 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
 import logging
-import traceback
-
-from pylons import request, response, session, tmpl_context as c, url
-from paste.httpexceptions import HTTPInternalServerError, HTTPBadRequest
 
 from sqlalchemy import or_
+from sqlalchemy.orm import joinedload, make_transient
+from webhelpers.paginate import Page
+from itertools import groupby
 
+from paste.httpexceptions import HTTPBadRequest
+from pylons import request, tmpl_context as c, response, url
+from pylons.i18n.translation import _
+from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
+
+import rhodecode.lib.helpers as h
 from rhodecode.lib.auth import LoginRequired, NotAnonymous
 from rhodecode.lib.base import BaseController, render
-from rhodecode.lib.helpers import get_token
 from rhodecode.model.db import UserLog, UserFollowing
-from rhodecode.model.scm import ScmModel
 
 log = logging.getLogger(__name__)
 
+
 class JournalController(BaseController):
 
+    def __before__(self):
+        super(JournalController, self).__before__()
+        self.rhodecode_user = self.rhodecode_user
+        self.title = _('%s public journal %s feed') % (c.rhodecode_name, '%s')
+        self.language = 'en-us'
+        self.ttl = "5"
+        self.feed_nr = 20
 
     @LoginRequired()
     @NotAnonymous()
-    def __before__(self):
-        super(JournalController, self).__before__()
-
     def index(self):
         # Return a rendered template
+        p = int(request.params.get('page', 1))
 
         c.following = self.sa.query(UserFollowing)\
-            .filter(UserFollowing.user_id == c.rhodecode_user.user_id).all()
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
+            .options(joinedload(UserFollowing.follows_repository))\
+            .all()
+
+        journal = self._get_journal_data(c.following)
+
+        c.journal_pager = Page(journal, page=p, items_per_page=20)
+
+        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
+
+        c.journal_data = render('journal/journal_data.html')
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            return c.journal_data
+        return render('journal/journal.html')
 
-        repo_ids = [x.follows_repository.repo_id for x in c.following
+    def _get_daily_aggregate(self, journal):
+        groups = []
+        for k, g in groupby(journal, lambda x: x.action_as_day):
+            user_group = []
+            for k2, g2 in groupby(list(g), lambda x: x.user.email):
+                l = list(g2)
+                user_group.append((l[0].user, l))
+
+            groups.append((k, user_group,))
+
+        return groups
+
+    def _get_journal_data(self, following_repos):
+        repo_ids = [x.follows_repository.repo_id for x in following_repos
                     if x.follows_repository is not None]
-        user_ids = [x.follows_user.user_id for x in c.following
+        user_ids = [x.follows_user.user_id for x in following_repos
                     if x.follows_user is not None]
 
-        c.journal = self.sa.query(UserLog)\
-            .filter(or_(
-                        UserLog.repository_id.in_(repo_ids),
-                        UserLog.user_id.in_(user_ids),
-                        ))\
-            .order_by(UserLog.action_date.desc())\
-            .limit(20)\
-            .all()
-        return render('/journal.html')
+        filtering_criterion = None
 
-    def toggle_following(self):
+        if repo_ids and user_ids:
+            filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
+                        UserLog.user_id.in_(user_ids))
+        if repo_ids and not user_ids:
+            filtering_criterion = UserLog.repository_id.in_(repo_ids)
+        if not repo_ids and user_ids:
+            filtering_criterion = UserLog.user_id.in_(user_ids)
+        if filtering_criterion is not None:
+            journal = self.sa.query(UserLog)\
+                .options(joinedload(UserLog.user))\
+                .options(joinedload(UserLog.repository))\
+                .filter(filtering_criterion)\
+                .order_by(UserLog.action_date.desc())
+        else:
+            journal = []
 
-        if request.POST.get('auth_token') == get_token():
-            scm_model = ScmModel()
+        return journal
+
+    @LoginRequired()
+    @NotAnonymous()
+    def toggle_following(self):
+        cur_token = request.POST.get('auth_token')
+        token = h.get_token()
+        if cur_token == token:
 
             user_id = request.POST.get('follows_user_id')
             if user_id:
                 try:
-                    scm_model.toggle_following_user(user_id,
-                                                    c.rhodecode_user.user_id)
+                    self.scm_model.toggle_following_user(user_id,
+                                                self.rhodecode_user.user_id)
                     return 'ok'
                 except:
-                    log.error(traceback.format_exc())
-                    raise HTTPInternalServerError()
+                    raise HTTPBadRequest()
 
             repo_id = request.POST.get('follows_repo_id')
             if repo_id:
                 try:
-                    scm_model.toggle_following_repo(repo_id,
-                                                    c.rhodecode_user.user_id)
+                    self.scm_model.toggle_following_repo(repo_id,
+                                                self.rhodecode_user.user_id)
                     return 'ok'
                 except:
-                    log.error(traceback.format_exc())
-                    raise HTTPInternalServerError()
+                    raise HTTPBadRequest()
+
+        log.debug('token mismatch %s vs %s', cur_token, token)
+        raise HTTPBadRequest()
+
+    @LoginRequired()
+    def public_journal(self):
+        # Return a rendered template
+        p = int(request.params.get('page', 1))
+
+        c.following = self.sa.query(UserFollowing)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
+            .options(joinedload(UserFollowing.follows_repository))\
+            .all()
+
+        journal = self._get_journal_data(c.following)
+
+        c.journal_pager = Page(journal, page=p, items_per_page=20)
+
+        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
+
+        c.journal_data = render('journal/journal_data.html')
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            return c.journal_data
+        return render('journal/public_journal.html')
+
+    @LoginRequired(api_access=True)
+    def public_journal_atom(self):
+        """
+        Produce an atom-1.0 feed via feedgenerator module
+        """
+        c.following = self.sa.query(UserFollowing)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
+            .options(joinedload(UserFollowing.follows_repository))\
+            .all()
+
+        journal = self._get_journal_data(c.following)
+
+        feed = Atom1Feed(title=self.title % 'atom',
+                         link=url('public_journal_atom', qualified=True),
+                         description=_('Public journal'),
+                         language=self.language,
+                         ttl=self.ttl)
 
+        for entry in journal[:self.feed_nr]:
+            #tmpl = h.action_parser(entry)[0]
+            action, action_extra = h.action_parser(entry, feed=True)
+            title = "%s - %s %s" % (entry.user.short_contact, action,
+                                 entry.repository.repo_name)
+            desc = action_extra()
+            feed.add_item(title=title,
+                          pubdate=entry.action_date,
+                          link=url('', qualified=True),
+                          author_email=entry.user.email,
+                          author_name=entry.user.full_contact,
+                          description=desc)
 
+        response.content_type = feed.mime_type
+        return feed.writeString('utf-8')
 
-        raise HTTPBadRequest()
+    @LoginRequired(api_access=True)
+    def public_journal_rss(self):
+        """
+        Produce an rss2 feed via feedgenerator module
+        """
+        c.following = self.sa.query(UserFollowing)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
+            .options(joinedload(UserFollowing.follows_repository))\
+            .all()
+
+        journal = self._get_journal_data(c.following)
+
+        feed = Rss201rev2Feed(title=self.title % 'rss',
+                         link=url('public_journal_rss', qualified=True),
+                         description=_('Public journal'),
+                         language=self.language,
+                         ttl=self.ttl)
+
+        for entry in journal[:self.feed_nr]:
+            #tmpl = h.action_parser(entry)[0]
+            action, action_extra = h.action_parser(entry, feed=True)
+            title = "%s - %s %s" % (entry.user.short_contact, action,
+                                 entry.repository.repo_name)
+            desc = action_extra()
+            feed.add_item(title=title,
+                          pubdate=entry.action_date,
+                          link=url('', qualified=True),
+                          author_email=entry.user.email,
+                          author_name=entry.user.full_contact,
+                          description=desc)
+
+        response.content_type = feed.mime_type
+        return feed.writeString('utf-8')
--- a/rhodecode/controllers/login.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/login.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Login controller for rhodeocode
-    
+
     :created_on: Apr 22, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -35,12 +35,14 @@
 import rhodecode.lib.helpers as h
 from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator
 from rhodecode.lib.base import BaseController, render
+from rhodecode.model.db import User
 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm
 from rhodecode.model.user import UserModel
 
 
 log = logging.getLogger(__name__)
 
+
 class LoginController(BaseController):
 
     def __before__(self):
@@ -50,8 +52,8 @@
         #redirect if already logged in
         c.came_from = request.GET.get('came_from', None)
 
-        if c.rhodecode_user.is_authenticated \
-                            and c.rhodecode_user.username != 'default':
+        if self.rhodecode_user.is_authenticated \
+                            and self.rhodecode_user.username != 'default':
 
             return redirect(url('home'))
 
@@ -60,19 +62,17 @@
             login_form = LoginForm()
             try:
                 c.form_result = login_form.to_python(dict(request.POST))
+                #form checks for username/password, now we're authenticated
                 username = c.form_result['username']
-                user = UserModel().get_by_username(username, case_insensitive=True)
-                auth_user = AuthUser()
-                auth_user.username = user.username
-                auth_user.is_authenticated = True
-                auth_user.is_admin = user.admin
-                auth_user.user_id = user.user_id
-                auth_user.name = user.name
-                auth_user.lastname = user.lastname
+                user = User.by_username(username,
+                                                   case_insensitive=True)
+                auth_user = AuthUser(user.user_id)
+                auth_user.set_authenticated()
                 session['rhodecode_user'] = auth_user
                 session.save()
-                log.info('user %s is now authenticated', username)
 
+                log.info('user %s is now authenticated and stored in session',
+                         username)
                 user.update_lastlogin()
 
                 if c.came_from:
@@ -95,7 +95,8 @@
     def register(self):
         user_model = UserModel()
         c.auto_active = False
-        for perm in user_model.get_by_username('default', cache=False).user_perms:
+        for perm in user_model.get_by_username('default',
+                                               cache=False).user_perms:
             if perm.permission.permission_name == 'hg.register.auto_activate':
                 c.auto_active = True
                 break
@@ -128,8 +129,8 @@
             password_reset_form = PasswordResetForm()()
             try:
                 form_result = password_reset_form.to_python(dict(request.POST))
-                user_model.reset_password(form_result)
-                h.flash(_('Your new password was sent'),
+                user_model.reset_password_link(form_result)
+                h.flash(_('Your password reset link was sent'),
                             category='success')
                 return redirect(url('login_home'))
 
@@ -143,8 +144,25 @@
 
         return render('/password_reset.html')
 
+    def password_reset_confirmation(self):
+
+        if request.GET and request.GET.get('key'):
+            try:
+                user_model = UserModel()
+                user = User.get_by_api_key(request.GET.get('key'))
+                data = dict(email=user.email)
+                user_model.reset_password(data)
+                h.flash(_('Your password reset was successful, '
+                          'new password has been sent to your email'),
+                            category='success')
+            except Exception, e:
+                log.error(e)
+                return redirect(url('reset_password'))
+
+        return redirect(url('login_home'))
+
     def logout(self):
-        session['rhodecode_user'] = AuthUser()
+        del session['rhodecode_user']
         session.save()
         log.info('Logging out and setting user as Empty')
         redirect(url('home'))
--- a/rhodecode/controllers/search.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/search.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Search controller for rhodecode
-    
+
     :created_on: Aug 7, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -26,8 +26,7 @@
 import traceback
 
 from pylons.i18n.translation import _
-from pylons import request, response, config, session, tmpl_context as c, url
-from pylons.controllers.util import abort, redirect
+from pylons import request, config, session, tmpl_context as c
 
 from rhodecode.lib.auth import LoginRequired
 from rhodecode.lib.base import BaseController, render
@@ -38,10 +37,11 @@
 
 from whoosh.index import open_dir, EmptyIndexError
 from whoosh.qparser import QueryParser, QueryParserError
-from whoosh.query import Phrase
+from whoosh.query import Phrase, Wildcard, Term, Prefix
 
 log = logging.getLogger(__name__)
 
+
 class SearchController(BaseController):
 
     @LoginRequired()
@@ -54,13 +54,12 @@
         c.runtime = ''
         c.cur_query = request.GET.get('q', None)
         c.cur_type = request.GET.get('type', 'source')
-        c.cur_search = search_type = {'content':'content',
-                                      'commit':'content',
-                                      'path':'path',
-                                      'repository':'repository'}\
+        c.cur_search = search_type = {'content': 'content',
+                                      'commit': 'content',
+                                      'path': 'path',
+                                      'repository': 'repository'}\
                                       .get(c.cur_type, 'content')
 
-
         if c.cur_query:
             cur_query = c.cur_query.lower()
 
@@ -68,8 +67,8 @@
             p = int(request.params.get('page', 1))
             highlight_items = set()
             try:
-                idx = open_dir(config['app_conf']['index_dir']
-                               , indexname=IDX_NAME)
+                idx = open_dir(config['app_conf']['index_dir'],
+                               indexname=IDX_NAME)
                 searcher = idx.searcher()
 
                 qp = QueryParser(search_type, schema=SCHEMA)
@@ -80,6 +79,8 @@
 
                     if isinstance(query, Phrase):
                         highlight_items.update(query.words)
+                    elif isinstance(query, Prefix):
+                        highlight_items.add(query.text)
                     else:
                         for i in query.all_terms():
                             if i[0] == 'content':
@@ -104,7 +105,6 @@
                                 page=p, item_count=res_ln,
                                 items_per_page=10, url=url_generator)
 
-
                 except QueryParserError:
                     c.runtime = _('Invalid search query. Try quoting it.')
                 searcher.close()
@@ -113,6 +113,9 @@
                 log.error('Empty Index data')
                 c.runtime = _('There is no index to search in. '
                               'Please run whoosh indexer')
+            except (Exception):
+                log.error(traceback.format_exc())
+                c.runtime = _('An error occurred during this search operation')
 
         # Return a rendered template
         return render('/search/search.html')
--- a/rhodecode/controllers/settings.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/settings.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Settings controller for rhodecode
-    
+
     :created_on: Jun 30, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -34,16 +34,20 @@
 from pylons.i18n.translation import _
 
 import rhodecode.lib.helpers as h
+
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator, \
     HasRepoPermissionAnyDecorator, NotAnonymous
-from rhodecode.lib.base import BaseController, render
+from rhodecode.lib.base import BaseRepoController, render
 from rhodecode.lib.utils import invalidate_cache, action_logger
+
 from rhodecode.model.forms import RepoSettingsForm, RepoForkForm
 from rhodecode.model.repo import RepoModel
+from rhodecode.model.db import User
 
 log = logging.getLogger(__name__)
 
-class SettingsController(BaseController):
+
+class SettingsController(BaseRepoController):
 
     @LoginRequired()
     def __before__(self):
@@ -61,12 +65,28 @@
                       category='error')
 
             return redirect(url('home'))
-        defaults = c.repo_info.get_dict()
-        defaults.update({'user':c.repo_info.user.username})
+
         c.users_array = repo_model.get_users_js()
+        c.users_groups_array = repo_model.get_users_groups_js()
 
+        defaults = c.repo_info.get_dict()
+
+        #fill owner
+        if c.repo_info.user:
+            defaults.update({'user': c.repo_info.user.username})
+        else:
+            replacement_user = self.sa.query(User)\
+            .filter(User.admin == True).first().username
+            defaults.update({'user': replacement_user})
+
+        #fill repository users
         for p in c.repo_info.repo_to_perm:
-            defaults.update({'perm_%s' % p.user.username:
+            defaults.update({'u_perm_%s' % p.user.username:
+                             p.permission.permission_name})
+
+        #fill repository groups
+        for p in c.repo_info.users_group_to_perm:
+            defaults.update({'g_perm_%s' % p.users_group.users_group_name:
                              p.permission.permission_name})
 
         return htmlfill.render(
@@ -80,7 +100,8 @@
     def update(self, repo_name):
         repo_model = RepoModel()
         changed_name = repo_name
-        _form = RepoSettingsForm(edit=True, old_data={'repo_name':repo_name})()
+        _form = RepoSettingsForm(edit=True,
+                                 old_data={'repo_name': repo_name})()
         try:
             form_result = _form.to_python(dict(request.POST))
             repo_model.update(repo_name, form_result)
@@ -93,7 +114,7 @@
         except formencode.Invalid, errors:
             c.repo_info = repo_model.get_by_repo_name(repo_name)
             c.users_array = repo_model.get_users_js()
-            errors.value.update({'user':c.repo_info.user.username})
+            errors.value.update({'user': c.repo_info.user.username})
             return htmlfill.render(
                 render('settings/repo_settings.html'),
                 defaults=errors.value,
@@ -107,7 +128,6 @@
 
         return redirect(url('repo_settings_home', repo_name=changed_name))
 
-
     @HasRepoPermissionAllDecorator('repository.admin')
     def delete(self, repo_name):
         """DELETE /repos/repo_name: Delete an existing item"""
@@ -135,6 +155,7 @@
             invalidate_cache('get_repo_cached_%s' % repo_name)
             h.flash(_('deleted repository %s') % repo_name, category='success')
         except Exception:
+            log.error(traceback.format_exc())
             h.flash(_('An error occurred during deletion of %s') % repo_name,
                     category='error')
 
@@ -163,12 +184,12 @@
     def fork_create(self, repo_name):
         repo_model = RepoModel()
         c.repo_info = repo_model.get_by_repo_name(repo_name)
-        _form = RepoForkForm(old_data={'repo_type':c.repo_info.repo_type})()
+        _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type})()
         form_result = {}
         try:
             form_result = _form.to_python(dict(request.POST))
-            form_result.update({'repo_name':repo_name})
-            repo_model.create_fork(form_result, c.rhodecode_user)
+            form_result.update({'repo_name': repo_name})
+            repo_model.create_fork(form_result, self.rhodecode_user)
             h.flash(_('forked %s repository as %s') \
                       % (repo_name, form_result['fork_name']),
                     category='success')
@@ -185,4 +206,9 @@
                 errors=errors.error_dict or {},
                 prefix_error=False,
                 encoding="UTF-8")
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('An error occurred during repository forking %s') %
+                    repo_name, category='error')
+
         return redirect(url('home'))
--- a/rhodecode/controllers/shortlog.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/shortlog.py	Fri Oct 07 01:08:50 2011 +0200
@@ -27,15 +27,14 @@
 
 from pylons import tmpl_context as c, request, url
 
-from webhelpers.paginate import Page
-
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
-from rhodecode.model.scm import ScmModel
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.lib.helpers import RepoPage
 
 log = logging.getLogger(__name__)
 
-class ShortlogController(BaseController):
+
+class ShortlogController(BaseRepoController):
 
     @LoginRequired()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
@@ -47,15 +46,14 @@
         p = int(request.params.get('page', 1))
         size = int(request.params.get('size', 20))
 
-        print repo_name
         def url_generator(**kw):
             return url('shortlog_home', repo_name=repo_name, size=size, **kw)
 
-        repo = ScmModel().get_repo(c.repo_name)
-        c.repo_changesets = Page(repo, page=p, items_per_page=size,
-                                                url=url_generator)
+        c.repo_changesets = RepoPage(c.rhodecode_repo, page=p,
+                                                       items_per_page=size,
+                                                       url=url_generator)
         c.shortlog_data = render('shortlog/shortlog_data.html')
-        if request.params.get('partial'):
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
             return c.shortlog_data
         r = render('shortlog/shortlog.html')
         return r
--- a/rhodecode/controllers/summary.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/summary.py	Fri Oct 07 01:08:50 2011 +0200
@@ -7,7 +7,7 @@
 
     :created_on: Apr 18, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -33,26 +33,29 @@
 from pylons import tmpl_context as c, request, url
 from pylons.i18n.translation import _
 
-from rhodecode.model.scm import ScmModel
-from rhodecode.model.db import Statistics
+from rhodecode.model.db import Statistics, Repository
+from rhodecode.model.repo import RepoModel
 
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
-from rhodecode.lib.utils import OrderedDict, EmptyChangeset
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.lib.utils import EmptyChangeset
+from rhodecode.lib.odict import OrderedDict
 
 from rhodecode.lib.celerylib import run_task
-from rhodecode.lib.celerylib.tasks import get_commits_stats
-
-from webhelpers.paginate import Page
+from rhodecode.lib.celerylib.tasks import get_commits_stats, \
+    LANGUAGES_EXTENSIONS_MAP
+from rhodecode.lib.helpers import RepoPage
 
 try:
     import json
 except ImportError:
     #python 2.5 compatibility
     import simplejson as json
+    
 log = logging.getLogger(__name__)
 
-class SummaryController(BaseController):
+
+class SummaryController(BaseRepoController):
 
     @LoginRequired()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
@@ -61,42 +64,51 @@
         super(SummaryController, self).__before__()
 
     def index(self, repo_name):
-        scm_model = ScmModel()
-        c.repo_info = scm_model.get_repo(c.repo_name)
-        c.following = scm_model.is_following_repo(c.repo_name,
-                                             c.rhodecode_user.user_id)
+
+        e = request.environ
+        c.dbrepo = dbrepo = c.rhodecode_db_repo
+
+        c.following = self.scm_model.is_following_repo(repo_name,
+                                                self.rhodecode_user.user_id)
+
         def url_generator(**kw):
             return url('shortlog_home', repo_name=repo_name, size=10, **kw)
 
-        c.repo_changesets = Page(c.repo_info, page=1,
-                                                items_per_page=10, url=url_generator)
-
-        e = request.environ
+        c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
+                                     items_per_page=10, url=url_generator)
 
         if self.rhodecode_user.username == 'default':
-            password = ':default'
+            #for default(anonymous) user we don't need to pass credentials
+            username = ''
+            password = ''
         else:
-            password = ''
+            username = str(self.rhodecode_user.username)
+            password = '@'
 
-        uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
-                                        'protocol': e.get('wsgi.url_scheme'),
-                                        'user':str(c.rhodecode_user.username),
-                                        'password':password,
-                                        'host':e.get('HTTP_HOST'),
-                                        'prefix':e.get('SCRIPT_NAME'),
-                                        'repo_name':c.repo_name, }
+        if e.get('wsgi.url_scheme') == 'https':
+            split_s = 'https://'
+        else:
+            split_s = 'http://'
+
+        qualified_uri = [split_s] + [url.current(qualified=True)\
+                                     .split(split_s)[-1]]
+        uri = u'%(proto)s%(user)s%(pass)s%(rest)s' \
+                % {'user': username,
+                     'pass': password,
+                     'proto': qualified_uri[0],
+                     'rest': qualified_uri[1]}
         c.clone_repo_url = uri
         c.repo_tags = OrderedDict()
-        for name, hash in c.repo_info.tags.items()[:10]:
+        for name, hash in c.rhodecode_repo.tags.items()[:10]:
             try:
-                c.repo_tags[name] = c.repo_info.get_changeset(hash)
+                c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash)
             except ChangesetError:
                 c.repo_tags[name] = EmptyChangeset(hash)
 
         c.repo_branches = OrderedDict()
-        for name, hash in c.repo_info.branches.items()[:10]:
+        for name, hash in c.rhodecode_repo.branches.items()[:10]:
             try:
-                c.repo_branches[name] = c.repo_info.get_changeset(hash)
+                c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash)
             except ChangesetError:
                 c.repo_branches[name] = EmptyChangeset(hash)
 
@@ -108,34 +120,70 @@
         ts_min_y = mktime(td_1y.timetuple())
         ts_max_y = mktime(td.timetuple())
 
-        if c.repo_info.dbrepo.enable_statistics:
+        if dbrepo.enable_statistics:
             c.no_data_msg = _('No data loaded yet')
-            run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
+            run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
         else:
-            c.no_data_msg = _('Statistics update are disabled for this repository')
+            c.no_data_msg = _('Statistics are disabled for this repository')
         c.ts_min = ts_min_m
         c.ts_max = ts_max_y
 
         stats = self.sa.query(Statistics)\
-            .filter(Statistics.repository == c.repo_info.dbrepo)\
+            .filter(Statistics.repository == dbrepo)\
             .scalar()
 
+        c.stats_percentage = 0
 
         if stats and stats.languages:
-            c.no_data = False is c.repo_info.dbrepo.enable_statistics
-            lang_stats = json.loads(stats.languages)
+            c.no_data = False is dbrepo.enable_statistics
+            lang_stats_d = json.loads(stats.languages)
             c.commit_data = stats.commit_activity
             c.overview_data = stats.commit_activity_combined
+            
+            lang_stats = ((x, {"count": y,
+                               "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
+                          for x, y in lang_stats_d.items())
+
             c.trending_languages = json.dumps(OrderedDict(
-                                       sorted(lang_stats.items(), reverse=True,
+                                       sorted(lang_stats, reverse=True,
                                             key=lambda k: k[1])[:10]
                                         )
                                     )
+            last_rev = stats.stat_on_revision
+            c.repo_last_rev = c.rhodecode_repo.count() - 1 \
+                if c.rhodecode_repo.revisions else 0
+            if last_rev == 0 or c.repo_last_rev == 0:
+                pass
+            else:
+                c.stats_percentage = '%.2f' % ((float((last_rev)) /
+                                                c.repo_last_rev) * 100)
         else:
             c.commit_data = json.dumps({})
-            c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10] ])
+            c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
             c.trending_languages = json.dumps({})
             c.no_data = True
+            
+        c.enable_downloads = dbrepo.enable_downloads
+        if c.enable_downloads:
+            c.download_options = self._get_download_links(c.rhodecode_repo)
 
         return render('summary/summary.html')
 
+    def _get_download_links(self, repo):
+
+        download_l = []
+
+        branches_group = ([], _("Branches"))
+        tags_group = ([], _("Tags"))
+
+        for name, chs in c.rhodecode_repo.branches.items():
+            #chs = chs.split(':')[-1]
+            branches_group[0].append((chs, name),)
+        download_l.append(branches_group)
+
+        for name, chs in c.rhodecode_repo.tags.items():
+            #chs = chs.split(':')[-1]
+            tags_group[0].append((chs, name),)
+        download_l.append(tags_group)
+
+        return download_l
--- a/rhodecode/controllers/tags.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/controllers/tags.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Tags controller for rhodecode
-    
+
     :created_on: Apr 21, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -27,13 +27,13 @@
 from pylons import tmpl_context as c
 
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
-from rhodecode.lib.base import BaseController, render
-from rhodecode.lib.utils import OrderedDict
-from rhodecode.model.scm import ScmModel
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.lib.odict import OrderedDict
 
 log = logging.getLogger(__name__)
 
-class TagsController(BaseController):
+
+class TagsController(BaseRepoController):
 
     @LoginRequired()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
@@ -42,10 +42,12 @@
         super(TagsController, self).__before__()
 
     def index(self):
-        hg_model = ScmModel()
-        c.repo_info = hg_model.get_repo(c.repo_name)
         c.repo_tags = OrderedDict()
-        for name, hash_ in c.repo_info.tags.items():
-            c.repo_tags[name] = c.repo_info.get_changeset(hash_)
+
+        tags = [(name, c.rhodecode_repo.get_changeset(hash_)) for \
+                 name, hash_ in c.rhodecode_repo.tags.items()]
+        ordered_tags = sorted(tags, key=lambda x: x[1].date, reverse=True)
+        for name, cs_tag in ordered_tags:
+            c.repo_tags[name] = cs_tag
 
         return render('tags/tags.html')
Binary file rhodecode/i18n/en/LC_MESSAGES/rhodecode.mo has changed
--- a/rhodecode/i18n/en/LC_MESSAGES/rhodecode.po	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/i18n/en/LC_MESSAGES/rhodecode.po	Fri Oct 07 01:08:50 2011 +0200
@@ -7,47 +7,2534 @@
 msgstr ""
 "Project-Id-Version: rhodecode 0.1\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2010-02-06 22:54+0100\n"
-"PO-Revision-Date: 2010-02-06 23:16+0100\n"
+"POT-Creation-Date: 2011-09-14 15:50-0300\n"
+"PO-Revision-Date: 2011-02-25 19:13+0100\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: en <LL@li.org>\n"
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
-
-#: rhodecode/controllers/error.py:34
+"Generated-By: Babel 0.9.6\n"
+
+#: rhodecode/controllers/changeset.py:108
+#: rhodecode/controllers/changeset.py:149
+#: rhodecode/controllers/changeset.py:216
+#: rhodecode/controllers/changeset.py:229
+msgid "binary file"
+msgstr ""
+
+#: rhodecode/controllers/changeset.py:123
+#: rhodecode/controllers/changeset.py:168
+msgid "Changeset is to big and was cut off, see raw changeset instead"
+msgstr ""
+
+#: rhodecode/controllers/changeset.py:159
+msgid "Diff is to big and was cut off, see raw diff instead"
+msgstr ""
+
+#: rhodecode/controllers/error.py:69
 msgid "Home page"
 msgstr ""
 
-#: rhodecode/controllers/error.py:55
+#: rhodecode/controllers/error.py:98
 msgid "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: rhodecode/controllers/error.py:57
-msgid "Unathorized access to resource"
-msgstr ""
-
-#: rhodecode/controllers/error.py:59
+#: rhodecode/controllers/error.py:101
+msgid "Unauthorized access to resource"
+msgstr ""
+
+#: rhodecode/controllers/error.py:103
 msgid "You don't have permission to view this page"
 msgstr ""
 
-#: rhodecode/controllers/error.py:61
+#: rhodecode/controllers/error.py:105
 msgid "The resource could not be found"
 msgstr ""
 
-#: rhodecode/controllers/error.py:63
+#: rhodecode/controllers/error.py:107
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
 msgstr ""
 
-#: rhodecode/model/forms.py:29
+#: rhodecode/controllers/feed.py:48
+#, python-format
+msgid "Changes on %s repository"
+msgstr ""
+
+#: rhodecode/controllers/feed.py:49
+#, python-format
+msgid "%s %s feed"
+msgstr ""
+
+#: rhodecode/controllers/files.py:72
+msgid "There are no files yet"
+msgstr ""
+
+#: rhodecode/controllers/files.py:262
+#, python-format
+msgid "Edited %s via RhodeCode"
+msgstr ""
+
+#: rhodecode/controllers/files.py:267
+#: rhodecode/templates/files/file_diff.html:40
+msgid "No changes"
+msgstr ""
+
+#: rhodecode/controllers/files.py:278
+#, python-format
+msgid "Successfully committed to %s"
+msgstr ""
+
+#: rhodecode/controllers/files.py:283
+msgid "Error occurred during commit"
+msgstr ""
+
+#: rhodecode/controllers/files.py:308
+msgid "downloads disabled"
+msgstr ""
+
+#: rhodecode/controllers/files.py:313
+#, python-format
+msgid "Unknown revision %s"
+msgstr ""
+
+#: rhodecode/controllers/files.py:315
+msgid "Empty repository"
+msgstr ""
+
+#: rhodecode/controllers/files.py:317
+msgid "Unknown archive type"
+msgstr ""
+
+#: rhodecode/controllers/files.py:385 rhodecode/controllers/files.py:398
+msgid "Binary file"
+msgstr ""
+
+#: rhodecode/controllers/files.py:417
+#: rhodecode/templates/changeset/changeset_range.html:4
+#: rhodecode/templates/changeset/changeset_range.html:12
+#: rhodecode/templates/changeset/changeset_range.html:29
+msgid "Changesets"
+msgstr ""
+
+#: rhodecode/controllers/files.py:418 rhodecode/controllers/summary.py:175
+#: rhodecode/templates/branches/branches.html:5
+#: rhodecode/templates/summary/summary.html:690
+msgid "Branches"
+msgstr ""
+
+#: rhodecode/controllers/files.py:419 rhodecode/controllers/summary.py:176
+#: rhodecode/templates/summary/summary.html:679
+#: rhodecode/templates/tags/tags.html:5
+msgid "Tags"
+msgstr ""
+
+#: rhodecode/controllers/journal.py:50
+#, python-format
+msgid "%s public journal %s feed"
+msgstr ""
+
+#: rhodecode/controllers/journal.py:178 rhodecode/controllers/journal.py:212
+#: rhodecode/templates/admin/repos/repo_edit.html:171
+#: rhodecode/templates/base/base.html:50
+msgid "Public journal"
+msgstr ""
+
+#: rhodecode/controllers/login.py:111
+msgid "You have successfully registered into rhodecode"
+msgstr ""
+
+#: rhodecode/controllers/login.py:133
+msgid "Your password reset link was sent"
+msgstr ""
+
+#: rhodecode/controllers/login.py:155
+msgid ""
+"Your password reset was successful, new password has been sent to your "
+"email"
+msgstr ""
+
+#: rhodecode/controllers/search.py:109
+msgid "Invalid search query. Try quoting it."
+msgstr ""
+
+#: rhodecode/controllers/search.py:114
+msgid "There is no index to search in. Please run whoosh indexer"
+msgstr ""
+
+#: rhodecode/controllers/search.py:118
+msgid "An error occurred during this search operation"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:61 rhodecode/controllers/settings.py:171
+#, python-format
+msgid ""
+"%s repository is not mapped to db perhaps it was created or renamed from "
+"the file system please run the application again in order to rescan "
+"repositories"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:109
+#: rhodecode/controllers/admin/repos.py:239
+#, python-format
+msgid "Repository %s updated successfully"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:126
+#: rhodecode/controllers/admin/repos.py:257
+#, python-format
+msgid "error occurred during update of repository %s"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:144
+#: rhodecode/controllers/admin/repos.py:275
+#, python-format
+msgid ""
+"%s repository is not mapped to db perhaps it was moved or renamed  from "
+"the filesystem please run the application again in order to rescan "
+"repositories"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:156
+#: rhodecode/controllers/admin/repos.py:287
+#, python-format
+msgid "deleted repository %s"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:159
+#: rhodecode/controllers/admin/repos.py:297
+#: rhodecode/controllers/admin/repos.py:303
+#, python-format
+msgid "An error occurred during deletion of %s"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:193
+#, python-format
+msgid "forked %s repository as %s"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:211
+#, python-format
+msgid "An error occurred during repository forking %s"
+msgstr ""
+
+#: rhodecode/controllers/summary.py:123
+msgid "No data loaded yet"
+msgstr ""
+
+#: rhodecode/controllers/summary.py:126
+msgid "Statistics are disabled for this repository"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:49
+msgid "BASE"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:50
+msgid "ONELEVEL"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:51
+msgid "SUBTREE"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:55
+msgid "NEVER"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:56
+msgid "ALLOW"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:57
+msgid "TRY"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:58
+msgid "DEMAND"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:59
+msgid "HARD"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:63
+msgid "No encryption"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:64
+msgid "LDAPS connection"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:65
+msgid "START_TLS on LDAP connection"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:115
+msgid "Ldap settings updated successfully"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:120
+msgid "Unable to activate ldap. The \"python-ldap\" library is missing."
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:134
+msgid "error occurred during update of ldap settings"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:56
+msgid "None"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:57
+msgid "Read"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:58
+msgid "Write"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:59
+#: rhodecode/templates/admin/ldap/ldap.html:9
+#: rhodecode/templates/admin/permissions/permissions.html:9
+#: rhodecode/templates/admin/repos/repo_add.html:9
+#: rhodecode/templates/admin/repos/repo_edit.html:9
+#: rhodecode/templates/admin/repos/repos.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:8
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:8
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
+#: rhodecode/templates/admin/settings/hooks.html:9
+#: rhodecode/templates/admin/settings/settings.html:9
+#: rhodecode/templates/admin/users/user_add.html:8
+#: rhodecode/templates/admin/users/user_edit.html:9
+#: rhodecode/templates/admin/users/user_edit.html:110
+#: rhodecode/templates/admin/users/users.html:9
+#: rhodecode/templates/admin/users_groups/users_group_add.html:8
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:9
+#: rhodecode/templates/admin/users_groups/users_groups.html:9
+#: rhodecode/templates/base/base.html:279
+#: rhodecode/templates/base/base.html:366
+#: rhodecode/templates/base/base.html:368
+#: rhodecode/templates/base/base.html:370
+msgid "Admin"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:62
+msgid "disabled"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:64
+msgid "allowed with manual account activation"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:66
+msgid "allowed with automatic account activation"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:68
+msgid "Disabled"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:69
+msgid "Enabled"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:102
+msgid "Default permissions updated successfully"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:119
+msgid "error occurred during update of permissions"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:96
+#, python-format
+msgid ""
+"%s repository is not mapped to db perhaps it was created or renamed from "
+"the filesystem please run the application again in order to rescan "
+"repositories"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:172
+#, python-format
+msgid "created repository %s from %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:176
+#, python-format
+msgid "created repository %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:205
+#, python-format
+msgid "error occurred during creation of repository %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:292
+#, python-format
+msgid "Cannot delete %s it still contains attached forks"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:320
+msgid "An error occurred during deletion of repository user"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:335
+msgid "An error occurred during deletion of repository users groups"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:352
+msgid "An error occurred during deletion of repository stats"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:367
+msgid "An error occurred during cache invalidation"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:387
+msgid "Updated repository visibility in public journal"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:390
+msgid "An error occurred during setting this repository in public journal"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:395 rhodecode/model/forms.py:53
 msgid "Token mismatch"
 msgstr ""
 
-#: rhodecode/model/forms.py:52
-msgid "Account number is invalid, it must be 26 digits"
-msgstr ""
-
+#: rhodecode/controllers/admin/repos.py:408
+msgid "Pulled from remote location"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:410
+msgid "An error occurred during pull from remote location"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:83
+#, python-format
+msgid "created repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:96
+#, python-format
+msgid "error occurred during creation of repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:130
+#, python-format
+msgid "updated repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:143
+#, python-format
+msgid "error occurred during update of repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:164
+#, python-format
+msgid "This group contains %s repositores and cannot be deleted"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:171
+#, python-format
+msgid "removed repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:175
+#, python-format
+msgid "error occurred during deletion of repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:109
+#, python-format
+msgid "Repositories successfully rescanned added: %s,removed: %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:118
+msgid "Whoosh reindex task scheduled"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:143
+msgid "Updated application settings"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:148
+#: rhodecode/controllers/admin/settings.py:215
+msgid "error occurred during updating application settings"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:210
+msgid "Updated mercurial settings"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:236
+msgid "Added new hook"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:247
+msgid "Updated hooks"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:251
+msgid "error occurred during hook creation"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:310
+msgid "You can't edit this user since it's crucial for entire application"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:339
+msgid "Your account was updated successfully"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:359
+#: rhodecode/controllers/admin/users.py:130
+#, python-format
+msgid "error occurred during update of user %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:78
+#, python-format
+msgid "created user %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:90
+#, python-format
+msgid "error occurred during creation of user %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:116
+msgid "User updated successfully"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:146
+msgid "successfully deleted user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:150
+msgid "An error occurred during deletion of user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:166
+msgid "You can't edit this user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:195
+#: rhodecode/controllers/admin/users_groups.py:202
+msgid "Granted 'repository create' permission to user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:204
+#: rhodecode/controllers/admin/users_groups.py:211
+msgid "Revoked 'repository create' permission to user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:74
+#, python-format
+msgid "created users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:86
+#, python-format
+msgid "error occurred during creation of users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:119
+#, python-format
+msgid "updated users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:138
+#, python-format
+msgid "error occurred during update of users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:154
+msgid "successfully deleted users group"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:158
+msgid "An error occurred during deletion of users group"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:279
+msgid "year"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:280
+msgid "month"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:281
+msgid "day"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:282
+msgid "hour"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:283
+msgid "minute"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:284
+msgid "second"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:293
+msgid "ago"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:296
+msgid "just now"
+msgstr ""
+
+#: rhodecode/lib/auth.py:377
+msgid "You need to be a registered user to perform this action"
+msgstr ""
+
+#: rhodecode/lib/auth.py:421
+msgid "You need to be a signed in to view this page"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:307
+msgid "True"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:311
+msgid "False"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:352
+#, python-format
+msgid "Show all combined changesets %s->%s"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:356
+msgid "compare view"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:365
+msgid "and"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:365
+#, python-format
+msgid "%s more"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:367 rhodecode/templates/changelog/changelog.html:14
+#: rhodecode/templates/changelog/changelog.html:39
+msgid "revisions"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:385
+msgid "fork name "
+msgstr ""
+
+#: rhodecode/lib/helpers.py:388
+msgid "[deleted] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:389 rhodecode/lib/helpers.py:393
+msgid "[created] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:390 rhodecode/lib/helpers.py:394
+msgid "[forked] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:391 rhodecode/lib/helpers.py:395
+msgid "[updated] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:392
+msgid "[delete] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:396
+msgid "[pushed] into"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:397
+msgid "[committed via RhodeCode] into"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:398
+msgid "[pulled from remote] into"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:399
+msgid "[pulled] from"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:400
+msgid "[started following] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:401
+msgid "[stopped following] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:577
+#, python-format
+msgid " and %s more"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:581
+msgid "No Files"
+msgstr ""
+
+#: rhodecode/model/forms.py:66
+msgid "Invalid username"
+msgstr ""
+
+#: rhodecode/model/forms.py:75
+msgid "This username already exists"
+msgstr ""
+
+#: rhodecode/model/forms.py:79
+msgid ""
+"Username may only contain alphanumeric characters underscores, periods or"
+" dashes and must begin with alphanumeric character"
+msgstr ""
+
+#: rhodecode/model/forms.py:94
+msgid "Invalid group name"
+msgstr ""
+
+#: rhodecode/model/forms.py:104
+msgid "This users group already exists"
+msgstr ""
+
+#: rhodecode/model/forms.py:110
+msgid ""
+"Group name may only contain alphanumeric characters underscores, periods "
+"or dashes and must begin with alphanumeric character"
+msgstr ""
+
+#: rhodecode/model/forms.py:132
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: rhodecode/model/forms.py:148
+msgid "This group already exists"
+msgstr ""
+
+#: rhodecode/model/forms.py:164 rhodecode/model/forms.py:172
+#: rhodecode/model/forms.py:180
+msgid "Invalid characters in password"
+msgstr ""
+
+#: rhodecode/model/forms.py:191
+msgid "Passwords do not match"
+msgstr ""
+
+#: rhodecode/model/forms.py:196
+msgid "invalid password"
+msgstr ""
+
+#: rhodecode/model/forms.py:197
+msgid "invalid user name"
+msgstr ""
+
+#: rhodecode/model/forms.py:198
+msgid "Your account is disabled"
+msgstr ""
+
+#: rhodecode/model/forms.py:233
+msgid "This username is not valid"
+msgstr ""
+
+#: rhodecode/model/forms.py:245
+msgid "This repository name is disallowed"
+msgstr ""
+
+#: rhodecode/model/forms.py:266
+#, python-format
+msgid "This repository already exists in group \"%s\""
+msgstr ""
+
+#: rhodecode/model/forms.py:274
+msgid "This repository already exists"
+msgstr ""
+
+#: rhodecode/model/forms.py:312 rhodecode/model/forms.py:319
+msgid "invalid clone url"
+msgstr ""
+
+#: rhodecode/model/forms.py:322
+msgid "Invalid clone url, provide a valid clone http\\s url"
+msgstr ""
+
+#: rhodecode/model/forms.py:334
+msgid "Fork have to be the same type as original"
+msgstr ""
+
+#: rhodecode/model/forms.py:341
+msgid "This username or users group name is not valid"
+msgstr ""
+
+#: rhodecode/model/forms.py:403
+msgid "This is not a valid path"
+msgstr ""
+
+#: rhodecode/model/forms.py:416
+msgid "This e-mail address is already taken"
+msgstr ""
+
+#: rhodecode/model/forms.py:427
+msgid "This e-mail address doesn't exist."
+msgstr ""
+
+#: rhodecode/model/forms.py:447
+msgid ""
+"The LDAP Login attribute of the CN must be specified - this is the name "
+"of the attribute that is equivalent to 'username'"
+msgstr ""
+
+#: rhodecode/model/forms.py:466
+msgid "Please enter a login"
+msgstr ""
+
+#: rhodecode/model/forms.py:467
+#, python-format
+msgid "Enter a value %(min)i characters long or more"
+msgstr ""
+
+#: rhodecode/model/forms.py:475
+msgid "Please enter a password"
+msgstr ""
+
+#: rhodecode/model/forms.py:476
+#, python-format
+msgid "Enter %(min)i characters or more"
+msgstr ""
+
+#: rhodecode/model/user.py:145
+msgid "[RhodeCode] New User registration"
+msgstr ""
+
+#: rhodecode/model/user.py:157 rhodecode/model/user.py:179
+msgid "You can't Edit this user since it's crucial for entire application"
+msgstr ""
+
+#: rhodecode/model/user.py:201
+msgid "You can't remove this user since it's crucial for entire application"
+msgstr ""
+
+#: rhodecode/model/user.py:204
+#, python-format
+msgid ""
+"This user still owns %s repositories and cannot be removed. Switch owners"
+" or remove those repositories"
+msgstr ""
+
+#: rhodecode/templates/index.html:4
+msgid "Dashboard"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:22
+#: rhodecode/templates/admin/users/user_edit_my_account.html:102
+msgid "quick filter..."
+msgstr ""
+
+#: rhodecode/templates/index_base.html:23
+#: rhodecode/templates/base/base.html:300
+msgid "repositories"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:29
+#: rhodecode/templates/admin/repos/repos.html:22
+msgid "ADD NEW REPOSITORY"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:32
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:32
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:33
+#: rhodecode/templates/admin/users_groups/users_group_add.html:32
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:33
+msgid "Group name"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:42
+#: rhodecode/templates/index_base.html:73
+#: rhodecode/templates/admin/repos/repo_add_base.html:44
+#: rhodecode/templates/admin/repos/repo_edit.html:64
+#: rhodecode/templates/admin/repos/repos.html:31
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:34
+#: rhodecode/templates/settings/repo_fork.html:40
+#: rhodecode/templates/settings/repo_settings.html:40
+#: rhodecode/templates/summary/summary.html:92
+msgid "Description"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:53
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46
+msgid "Repositories group"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:72
+#: rhodecode/templates/admin/repos/repo_add_base.html:9
+#: rhodecode/templates/admin/repos/repo_edit.html:32
+#: rhodecode/templates/admin/repos/repos.html:30
+#: rhodecode/templates/admin/users/user_edit_my_account.html:117
+#: rhodecode/templates/files/files_browser.html:157
+#: rhodecode/templates/settings/repo_settings.html:31
+#: rhodecode/templates/summary/summary.html:31
+#: rhodecode/templates/summary/summary.html:107
+msgid "Name"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:74
+#: rhodecode/templates/admin/repos/repos.html:32
+#: rhodecode/templates/summary/summary.html:114
+msgid "Last change"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:75
+#: rhodecode/templates/admin/repos/repos.html:33
+msgid "Tip"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:76
+#: rhodecode/templates/admin/repos/repo_edit.html:97
+msgid "Owner"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:77
+#: rhodecode/templates/journal/public_journal.html:20
+#: rhodecode/templates/summary/summary.html:180
+#: rhodecode/templates/summary/summary.html:183
+msgid "RSS"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:78
+#: rhodecode/templates/journal/public_journal.html:23
+#: rhodecode/templates/summary/summary.html:181
+#: rhodecode/templates/summary/summary.html:184
+msgid "Atom"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:87
+#: rhodecode/templates/index_base.html:89
+#: rhodecode/templates/index_base.html:91
+#: rhodecode/templates/base/base.html:209
+#: rhodecode/templates/base/base.html:211
+#: rhodecode/templates/base/base.html:213
+#: rhodecode/templates/summary/summary.html:4
+msgid "Summary"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:95
+#: rhodecode/templates/index_base.html:97
+#: rhodecode/templates/index_base.html:99
+#: rhodecode/templates/base/base.html:225
+#: rhodecode/templates/base/base.html:227
+#: rhodecode/templates/base/base.html:229
+#: rhodecode/templates/changelog/changelog.html:6
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "Changelog"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:103
+#: rhodecode/templates/index_base.html:105
+#: rhodecode/templates/index_base.html:107
+#: rhodecode/templates/base/base.html:268
+#: rhodecode/templates/base/base.html:270
+#: rhodecode/templates/base/base.html:272
+#: rhodecode/templates/files/files.html:4
+msgid "Files"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:116
+#: rhodecode/templates/admin/repos/repos.html:42
+#: rhodecode/templates/admin/users/user_edit_my_account.html:127
+#: rhodecode/templates/summary/summary.html:48
+msgid "Mercurial repository"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:118
+#: rhodecode/templates/admin/repos/repos.html:44
+#: rhodecode/templates/admin/users/user_edit_my_account.html:129
+#: rhodecode/templates/summary/summary.html:51
+msgid "Git repository"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:123
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:16
+#: rhodecode/templates/journal/journal.html:53
+#: rhodecode/templates/summary/summary.html:56
+msgid "private repository"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:125
+#: rhodecode/templates/journal/journal.html:55
+#: rhodecode/templates/summary/summary.html:58
+msgid "public repository"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:133
+#: rhodecode/templates/base/base.html:291
+#: rhodecode/templates/settings/repo_fork.html:13
+msgid "fork"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:134
+#: rhodecode/templates/admin/repos/repos.html:60
+#: rhodecode/templates/admin/users/user_edit_my_account.html:143
+#: rhodecode/templates/summary/summary.html:69
+#: rhodecode/templates/summary/summary.html:71
+msgid "Fork of"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:155
+#: rhodecode/templates/admin/repos/repos.html:73
+msgid "No changesets yet"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:161
+#: rhodecode/templates/index_base.html:163
+#, python-format
+msgid "Subscribe to %s rss feed"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:168
+#: rhodecode/templates/index_base.html:170
+#, python-format
+msgid "Subscribe to %s atom feed"
+msgstr ""
+
+#: rhodecode/templates/login.html:5 rhodecode/templates/login.html:54
+#: rhodecode/templates/base/base.html:38
+msgid "Sign In"
+msgstr ""
+
+#: rhodecode/templates/login.html:21
+msgid "Sign In to"
+msgstr ""
+
+#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20
+#: rhodecode/templates/admin/admin_log.html:5
+#: rhodecode/templates/admin/users/user_add.html:32
+#: rhodecode/templates/admin/users/user_edit.html:47
+#: rhodecode/templates/admin/users/user_edit_my_account.html:45
+#: rhodecode/templates/base/base.html:15
+#: rhodecode/templates/summary/summary.html:106
+msgid "Username"
+msgstr ""
+
+#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29
+#: rhodecode/templates/admin/ldap/ldap.html:46
+#: rhodecode/templates/admin/users/user_add.html:41
+#: rhodecode/templates/base/base.html:24
+msgid "Password"
+msgstr ""
+
+#: rhodecode/templates/login.html:60
+msgid "Forgot your password ?"
+msgstr ""
+
+#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:35
+msgid "Don't have an account ?"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:5
+msgid "Reset your password"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:11
+msgid "Reset your password to"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:21
+msgid "Email address"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:30
+msgid "Reset my password"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:31
+msgid "Password reset link will be send to matching email address"
+msgstr ""
+
+#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74
+msgid "Sign Up"
+msgstr ""
+
+#: rhodecode/templates/register.html:11
+msgid "Sign Up to"
+msgstr ""
+
+#: rhodecode/templates/register.html:38
+msgid "Re-enter password"
+msgstr ""
+
+#: rhodecode/templates/register.html:47
+#: rhodecode/templates/admin/users/user_add.html:50
+#: rhodecode/templates/admin/users/user_edit.html:74
+#: rhodecode/templates/admin/users/user_edit_my_account.html:63
+msgid "First Name"
+msgstr ""
+
+#: rhodecode/templates/register.html:56
+#: rhodecode/templates/admin/users/user_add.html:59
+#: rhodecode/templates/admin/users/user_edit.html:83
+#: rhodecode/templates/admin/users/user_edit_my_account.html:72
+msgid "Last Name"
+msgstr ""
+
+#: rhodecode/templates/register.html:65
+#: rhodecode/templates/admin/users/user_add.html:68
+#: rhodecode/templates/admin/users/user_edit.html:92
+#: rhodecode/templates/admin/users/user_edit_my_account.html:81
+#: rhodecode/templates/summary/summary.html:108
+msgid "Email"
+msgstr ""
+
+#: rhodecode/templates/register.html:76
+msgid "Your account will be activated right after registration"
+msgstr ""
+
+#: rhodecode/templates/register.html:78
+msgid "Your account must wait for activation by administrator"
+msgstr ""
+
+#: rhodecode/templates/repo_switcher_list.html:14
+msgid "Private repository"
+msgstr ""
+
+#: rhodecode/templates/repo_switcher_list.html:19
+msgid "Public repository"
+msgstr ""
+
+#: rhodecode/templates/admin/admin.html:5
+#: rhodecode/templates/admin/admin.html:9
+msgid "Admin journal"
+msgstr ""
+
+#: rhodecode/templates/admin/admin_log.html:6
+msgid "Action"
+msgstr ""
+
+#: rhodecode/templates/admin/admin_log.html:7
+msgid "Repository"
+msgstr ""
+
+#: rhodecode/templates/admin/admin_log.html:8
+msgid "Date"
+msgstr ""
+
+#: rhodecode/templates/admin/admin_log.html:9
+msgid "From IP"
+msgstr ""
+
+#: rhodecode/templates/admin/admin_log.html:52
+msgid "No actions yet"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:5
+msgid "LDAP administration"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:11
+msgid "Ldap"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:28
+msgid "Connection settings"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:30
+msgid "Enable LDAP"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:34
+msgid "Host"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:38
+msgid "Port"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:42
+msgid "Account"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:50
+msgid "Connection security"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:54
+msgid "Certificate Checks"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:57
+msgid "Search settings"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:59
+msgid "Base DN"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:63
+msgid "LDAP Filter"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:67
+msgid "LDAP Search Scope"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:70
+msgid "Attribute mappings"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:72
+msgid "Login Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:76
+msgid "First Name Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:80
+msgid "Last Name Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:84
+msgid "E-mail Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:89
+#: rhodecode/templates/admin/settings/hooks.html:73
+#: rhodecode/templates/admin/users/user_edit.html:117
+#: rhodecode/templates/admin/users/user_edit.html:142
+#: rhodecode/templates/admin/users/user_edit_my_account.html:89
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:263
+msgid "Save"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:5
+msgid "Permissions administration"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:11
+#: rhodecode/templates/admin/repos/repo_edit.html:109
+#: rhodecode/templates/admin/users/user_edit.html:127
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:248
+#: rhodecode/templates/settings/repo_settings.html:58
+msgid "Permissions"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:24
+msgid "Default permissions"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:31
+msgid "Anonymous access"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:41
+msgid "Repository permission"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:49
+msgid ""
+"All default permissions on each repository will be reset to choosen "
+"permission, note that all custom default permission on repositories will "
+"be lost"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:50
+msgid "overwrite existing settings"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:55
+msgid "Registration"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:63
+msgid "Repository creation"
+msgstr ""
+
+#: rhodecode/templates/admin/permissions/permissions.html:71
+msgid "set"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add.html:5
+#: rhodecode/templates/admin/repos/repo_add_create_repository.html:5
+msgid "Add repository"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add.html:11
+#: rhodecode/templates/admin/repos/repo_edit.html:11
+#: rhodecode/templates/admin/repos/repos.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
+msgid "Repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add.html:13
+msgid "add new"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:20
+#: rhodecode/templates/summary/summary.html:80
+#: rhodecode/templates/summary/summary.html:82
+msgid "Clone from"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:28
+#: rhodecode/templates/admin/repos/repo_edit.html:48
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:4
+msgid "Repository group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:36
+#: rhodecode/templates/admin/repos/repo_edit.html:56
+msgid "Type"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:52
+#: rhodecode/templates/admin/repos/repo_edit.html:73
+#: rhodecode/templates/settings/repo_fork.html:48
+#: rhodecode/templates/settings/repo_settings.html:49
+msgid "Private"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:59
+msgid "add"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_create_repository.html:9
+msgid "add new repository"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:5
+msgid "Edit repository"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:13
+#: rhodecode/templates/admin/users/user_edit.html:13
+#: rhodecode/templates/admin/users/user_edit_my_account.html:148
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:13
+#: rhodecode/templates/files/files_annotate.html:49
+#: rhodecode/templates/files/files_source.html:20
+msgid "edit"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:40
+msgid "Clone uri"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:81
+msgid "Enable statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:89
+msgid "Enable downloads"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:127
+msgid "Administration"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:130
+msgid "Statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:134
+msgid "Reset current statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:134
+msgid "Confirm to remove current statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:137
+msgid "Fetched to rev"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:138
+msgid "Percentage of stats gathered"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:147
+msgid "Remote"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:151
+msgid "Pull changes from remote location"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:151
+msgid "Confirm to pull changes from remote side"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:162
+msgid "Cache"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:166
+msgid "Invalidate repository cache"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:166
+msgid "Confirm to invalidate repository cache"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:177
+msgid "Remove from public journal"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:179
+msgid "Add to public journal"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:185
+msgid "Delete"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:189
+msgid "Remove this repository"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:189
+#: rhodecode/templates/admin/repos/repos.html:79
+msgid "Confirm to delete this repository"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:3
+msgid "none"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:4
+msgid "read"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:5
+msgid "write"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:6
+#: rhodecode/templates/admin/users/users.html:38
+#: rhodecode/templates/base/base.html:296
+msgid "admin"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:7
+msgid "member"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:33
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:53
+msgid "revoke"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:75
+msgid "Add another member"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:89
+msgid "Failed to remove user"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:104
+msgid "Failed to remove users group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:205
+msgid "Group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:206
+#: rhodecode/templates/admin/users_groups/users_groups.html:33
+msgid "members"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repos.html:5
+msgid "Repositories administration"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repos.html:34
+#: rhodecode/templates/summary/summary.html:100
+msgid "Contact"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repos.html:35
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:36
+#: rhodecode/templates/admin/users/user_edit_my_account.html:119
+#: rhodecode/templates/admin/users/users.html:40
+#: rhodecode/templates/admin/users_groups/users_groups.html:35
+msgid "action"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repos.html:51
+#: rhodecode/templates/admin/users/user_edit_my_account.html:134
+#: rhodecode/templates/admin/users/user_edit_my_account.html:148
+msgid "private"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repos.html:53
+#: rhodecode/templates/admin/repos/repos.html:59
+#: rhodecode/templates/admin/users/user_edit_my_account.html:136
+#: rhodecode/templates/admin/users/user_edit_my_account.html:142
+#: rhodecode/templates/summary/summary.html:68
+msgid "public"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repos.html:79
+#: rhodecode/templates/admin/users/users.html:55
+msgid "delete"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:8
+msgid "Groups"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:13
+msgid "with"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5
+msgid "Add repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:10
+msgid "Repos groups"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:12
+msgid "add new repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:50
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:50
+msgid "Group parent"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:58
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:58
+#: rhodecode/templates/admin/users/user_add.html:85
+#: rhodecode/templates/admin/users_groups/users_group_add.html:49
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:90
+msgid "save"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5
+msgid "Edit repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:12
+msgid "edit repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5
+msgid "Repositories groups administration"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:22
+msgid "ADD NEW GROUP"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:35
+msgid "Number of repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:54
+msgid "Confirm to delete this group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:62
+msgid "There are no repositories groups yet"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:5
+#: rhodecode/templates/admin/settings/settings.html:5
+msgid "Settings administration"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:9
+#: rhodecode/templates/admin/settings/settings.html:9
+#: rhodecode/templates/settings/repo_settings.html:5
+#: rhodecode/templates/settings/repo_settings.html:13
+msgid "Settings"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:24
+msgid "Built in hooks - read only"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:40
+msgid "Custom hooks"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:56
+msgid "remove"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:88
+msgid "Failed to remove hook"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:24
+msgid "Remap and rescan repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:32
+msgid "rescan option"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:38
+msgid ""
+"In case a repository was deleted from filesystem and there are leftovers "
+"in the database check this option to scan obsolete data in database and "
+"remove it."
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:39
+msgid "destroy old data"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:45
+msgid "Rescan repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:51
+msgid "Whoosh indexing"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:59
+msgid "index build option"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:64
+msgid "build from scratch"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:70
+msgid "Reindex"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:76
+msgid "Global application settings"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:85
+msgid "Application name"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:94
+msgid "Realm text"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:103
+msgid "GA code"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:111
+#: rhodecode/templates/admin/settings/settings.html:177
+msgid "Save settings"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:112
+#: rhodecode/templates/admin/settings/settings.html:178
+#: rhodecode/templates/admin/users/user_edit.html:118
+#: rhodecode/templates/admin/users/user_edit.html:143
+#: rhodecode/templates/admin/users/user_edit_my_account.html:90
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:264
+#: rhodecode/templates/files/files_edit.html:50
+msgid "Reset"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:118
+msgid "Mercurial settings"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:127
+msgid "Web"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:132
+msgid "require ssl for pushing"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:139
+msgid "Hooks"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:142
+msgid "advanced setup"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:147
+msgid "Update repository after push (hg update)"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:151
+msgid "Show repository size after push"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:155
+msgid "Log user push commands"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:159
+msgid "Log user pull commands"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:166
+msgid "Repositories location"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:171
+msgid ""
+"This a crucial application setting. If you are really sure you need to "
+"change this, you must restart application in order to make this setting "
+"take effect. Click this label to unlock."
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:172
+msgid "unlock"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_add.html:5
+msgid "Add user"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_add.html:10
+#: rhodecode/templates/admin/users/user_edit.html:11
+#: rhodecode/templates/admin/users/users.html:9
+msgid "Users"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_add.html:12
+msgid "add new user"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_add.html:77
+#: rhodecode/templates/admin/users/user_edit.html:101
+#: rhodecode/templates/admin/users_groups/users_group_add.html:41
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:42
+msgid "Active"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:5
+msgid "Edit user"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:33
+#: rhodecode/templates/admin/users/user_edit_my_account.html:32
+msgid "Change your avatar at"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:34
+#: rhodecode/templates/admin/users/user_edit_my_account.html:33
+msgid "Using"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:40
+#: rhodecode/templates/admin/users/user_edit_my_account.html:39
+msgid "API key"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:56
+msgid "LDAP DN"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:65
+#: rhodecode/templates/admin/users/user_edit_my_account.html:54
+msgid "New password"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:135
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:256
+msgid "Create repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:5
+msgid "My account"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:9
+msgid "My Account"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:101
+msgid "My repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:107
+msgid "ADD REPOSITORY"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:118
+#: rhodecode/templates/branches/branches_data.html:7
+#: rhodecode/templates/shortlog/shortlog_data.html:8
+#: rhodecode/templates/tags/tags_data.html:7
+msgid "revision"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:157
+msgid "No repositories yet"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:159
+msgid "create one now"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:5
+msgid "Users administration"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:23
+msgid "ADD NEW USER"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:33
+msgid "username"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:34
+#: rhodecode/templates/branches/branches_data.html:5
+#: rhodecode/templates/tags/tags_data.html:5
+msgid "name"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:35
+msgid "lastname"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:36
+msgid "last login"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:37
+#: rhodecode/templates/admin/users_groups/users_groups.html:34
+msgid "active"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:39
+#: rhodecode/templates/base/base.html:305
+msgid "ldap"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:56
+msgid "Confirm to delete this user"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:5
+msgid "Add users group"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:10
+#: rhodecode/templates/admin/users_groups/users_groups.html:9
+msgid "Users groups"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:12
+msgid "add new users group"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:5
+msgid "Edit users group"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:11
+msgid "UsersGroups"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:50
+msgid "Members"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:58
+msgid "Choosen group members"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:61
+msgid "Remove all elements"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:75
+msgid "Available members"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:79
+msgid "Add all elements"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:5
+msgid "Users groups administration"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:23
+msgid "ADD NEW USER GROUP"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:32
+msgid "group name"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:32
+msgid "Forgot password ?"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:57 rhodecode/templates/base/base.html:338
+#: rhodecode/templates/base/base.html:340
+#: rhodecode/templates/base/base.html:342
+msgid "Home"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:61 rhodecode/templates/base/base.html:347
+#: rhodecode/templates/base/base.html:349
+#: rhodecode/templates/base/base.html:351
+#: rhodecode/templates/journal/journal.html:4
+#: rhodecode/templates/journal/journal.html:17
+#: rhodecode/templates/journal/public_journal.html:4
+msgid "Journal"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:66
+msgid "Login"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:68
+msgid "Log Out"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:107
+msgid "Submit a bug"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:141
+msgid "Switch repository"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:143
+msgid "Products"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:149
+msgid "loading..."
+msgstr ""
+
+#: rhodecode/templates/base/base.html:234
+#: rhodecode/templates/base/base.html:236
+#: rhodecode/templates/base/base.html:238
+msgid "Switch to"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:242
+#: rhodecode/templates/branches/branches.html:13
+msgid "branches"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:249
+#: rhodecode/templates/branches/branches_data.html:52
+msgid "There are no branches yet"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:254
+#: rhodecode/templates/shortlog/shortlog_data.html:10
+#: rhodecode/templates/tags/tags.html:14
+msgid "tags"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:261
+#: rhodecode/templates/tags/tags_data.html:32
+msgid "There are no tags yet"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:277
+#: rhodecode/templates/base/base.html:281
+#: rhodecode/templates/files/files_annotate.html:40
+#: rhodecode/templates/files/files_source.html:11
+msgid "Options"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:286
+#: rhodecode/templates/base/base.html:288
+#: rhodecode/templates/base/base.html:306
+msgid "settings"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:292
+msgid "search"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:299
+msgid "journal"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:301
+msgid "repositories groups"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:302
+msgid "users"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:303
+msgid "users groups"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:304
+msgid "permissions"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:317
+#: rhodecode/templates/base/base.html:319
+#: rhodecode/templates/followers/followers.html:5
+msgid "Followers"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:325
+#: rhodecode/templates/base/base.html:327
+#: rhodecode/templates/forks/forks.html:5
+msgid "Forks"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:356
+#: rhodecode/templates/base/base.html:358
+#: rhodecode/templates/base/base.html:360
+#: rhodecode/templates/search/search.html:4
+#: rhodecode/templates/search/search.html:24
+#: rhodecode/templates/search/search.html:46
+msgid "Search"
+msgstr ""
+
+#: rhodecode/templates/base/root.html:57
+#: rhodecode/templates/journal/journal.html:48
+#: rhodecode/templates/summary/summary.html:36
+msgid "Stop following this repository"
+msgstr ""
+
+#: rhodecode/templates/base/root.html:66
+#: rhodecode/templates/summary/summary.html:40
+msgid "Start following this repository"
+msgstr ""
+
+#: rhodecode/templates/branches/branches_data.html:4
+#: rhodecode/templates/tags/tags_data.html:4
+msgid "date"
+msgstr ""
+
+#: rhodecode/templates/branches/branches_data.html:6
+#: rhodecode/templates/shortlog/shortlog_data.html:7
+#: rhodecode/templates/tags/tags_data.html:6
+msgid "author"
+msgstr ""
+
+#: rhodecode/templates/branches/branches_data.html:8
+#: rhodecode/templates/shortlog/shortlog_data.html:11
+#: rhodecode/templates/tags/tags_data.html:8
+msgid "links"
+msgstr ""
+
+#: rhodecode/templates/branches/branches_data.html:23
+#: rhodecode/templates/branches/branches_data.html:43
+#: rhodecode/templates/shortlog/shortlog_data.html:39
+#: rhodecode/templates/tags/tags_data.html:24
+msgid "changeset"
+msgstr ""
+
+#: rhodecode/templates/branches/branches_data.html:25
+#: rhodecode/templates/branches/branches_data.html:45
+#: rhodecode/templates/files/files.html:12
+#: rhodecode/templates/shortlog/shortlog_data.html:41
+#: rhodecode/templates/summary/summary.html:233
+#: rhodecode/templates/tags/tags_data.html:26
+msgid "files"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "showing "
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "out of"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:37
+msgid "Show"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:50
+#: rhodecode/templates/changeset/changeset.html:42
+#: rhodecode/templates/summary/summary.html:609
+msgid "commit"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:63
+msgid "Affected number of files, click to show more details"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:67
+#: rhodecode/templates/changeset/changeset.html:66
+msgid "merge"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:72
+#: rhodecode/templates/changeset/changeset.html:72
+msgid "Parent"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:77
+#: rhodecode/templates/changeset/changeset.html:77
+msgid "No parents"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:82
+#: rhodecode/templates/changeset/changeset.html:80
+#: rhodecode/templates/files/files.html:29
+#: rhodecode/templates/files/files_annotate.html:25
+#: rhodecode/templates/files/files_edit.html:33
+#: rhodecode/templates/shortlog/shortlog_data.html:9
+msgid "branch"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:86
+#: rhodecode/templates/changeset/changeset.html:83
+msgid "tag"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:122
+msgid "Show selected changes __S -> __E"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:172
+#: rhodecode/templates/shortlog/shortlog_data.html:61
+msgid "There are no changes yet"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:2
+#: rhodecode/templates/changeset/changeset.html:55
+msgid "removed"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:3
+#: rhodecode/templates/changeset/changeset.html:56
+msgid "changed"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:4
+#: rhodecode/templates/changeset/changeset.html:57
+msgid "added"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:6
+#: rhodecode/templates/changelog/changelog_details.html:7
+#: rhodecode/templates/changelog/changelog_details.html:8
+#: rhodecode/templates/changeset/changeset.html:59
+#: rhodecode/templates/changeset/changeset.html:60
+#: rhodecode/templates/changeset/changeset.html:61
+#, python-format
+msgid "affected %s files"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:6
+#: rhodecode/templates/changeset/changeset.html:14
+#: rhodecode/templates/changeset/changeset.html:31
+msgid "Changeset"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:32
+#: rhodecode/templates/changeset/changeset.html:121
+#: rhodecode/templates/changeset/changeset_range.html:78
+#: rhodecode/templates/files/file_diff.html:32
+#: rhodecode/templates/files/file_diff.html:42
+msgid "raw diff"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:34
+#: rhodecode/templates/changeset/changeset.html:123
+#: rhodecode/templates/changeset/changeset_range.html:80
+#: rhodecode/templates/files/file_diff.html:34
+msgid "download diff"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:90
+#, python-format
+msgid "%s files affected with %s additions and %s deletions."
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:101
+msgid "Changeset was too big and was cut off..."
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:119
+#: rhodecode/templates/changeset/changeset_range.html:76
+#: rhodecode/templates/files/file_diff.html:30
+msgid "diff"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:132
+#: rhodecode/templates/changeset/changeset_range.html:89
+msgid "No changes in this file"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset_range.html:30
+msgid "Compare View"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset_range.html:52
+msgid "Files affected"
+msgstr ""
+
+#: rhodecode/templates/errors/error_document.html:44
+#, python-format
+msgid "You will be redirected to %s in %s seconds"
+msgstr ""
+
+#: rhodecode/templates/files/file_diff.html:4
+#: rhodecode/templates/files/file_diff.html:12
+msgid "File diff"
+msgstr ""
+
+#: rhodecode/templates/files/file_diff.html:42
+msgid "Diff is to big to display"
+msgstr ""
+
+#: rhodecode/templates/files/files.html:37
+#: rhodecode/templates/files/files_annotate.html:31
+#: rhodecode/templates/files/files_edit.html:39
+msgid "Location"
+msgstr ""
+
+#: rhodecode/templates/files/files.html:46
+msgid "Go back"
+msgstr ""
+
+#: rhodecode/templates/files/files.html:47
+msgid "No files at given path"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:4
+msgid "File annotate"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:12
+msgid "annotate"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:33
+#: rhodecode/templates/files/files_browser.html:160
+#: rhodecode/templates/files/files_source.html:2
+msgid "Revision"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:36
+#: rhodecode/templates/files/files_browser.html:158
+#: rhodecode/templates/files/files_source.html:7
+msgid "Size"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:38
+#: rhodecode/templates/files/files_browser.html:159
+#: rhodecode/templates/files/files_source.html:9
+msgid "Mimetype"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:41
+msgid "show source"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:43
+#: rhodecode/templates/files/files_annotate.html:78
+#: rhodecode/templates/files/files_source.html:14
+#: rhodecode/templates/files/files_source.html:51
+msgid "show as raw"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:45
+#: rhodecode/templates/files/files_source.html:16
+msgid "download as raw"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:54
+#: rhodecode/templates/files/files_source.html:25
+msgid "History"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:73
+#: rhodecode/templates/files/files_source.html:46
+#, python-format
+msgid "Binary file (%s)"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:78
+#: rhodecode/templates/files/files_source.html:51
+msgid "File is too big to display"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:13
+msgid "view"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:14
+msgid "previous revision"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:16
+msgid "next revision"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:23
+msgid "follow current branch"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:27
+msgid "search file list"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:32
+msgid "Loading file list..."
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:111
+msgid "search truncated"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:122
+msgid "no matching files"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:161
+msgid "Last modified"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:162
+msgid "Last commiter"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:4
+msgid "Edit file"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:19
+msgid "edit file"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:45
+#: rhodecode/templates/shortlog/shortlog_data.html:5
+msgid "commit message"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:51
+msgid "Commit changes"
+msgstr ""
+
+#: rhodecode/templates/files/files_source.html:12
+msgid "show annotation"
+msgstr ""
+
+#: rhodecode/templates/files/files_source.html:153
+msgid "Selection link"
+msgstr ""
+
+#: rhodecode/templates/followers/followers.html:13
+msgid "followers"
+msgstr ""
+
+#: rhodecode/templates/followers/followers_data.html:12
+msgid "Started following"
+msgstr ""
+
+#: rhodecode/templates/forks/forks.html:13
+msgid "forks"
+msgstr ""
+
+#: rhodecode/templates/forks/forks_data.html:17
+msgid "forked"
+msgstr ""
+
+#: rhodecode/templates/forks/forks_data.html:34
+msgid "There are no forks yet"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:34
+msgid "Following"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:41
+msgid "following user"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:41
+msgid "user"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:65
+msgid "You are not following any users or repositories"
+msgstr ""
+
+#: rhodecode/templates/journal/journal_data.html:46
+msgid "No entries yet"
+msgstr ""
+
+#: rhodecode/templates/journal/public_journal.html:17
+msgid "Public Journal"
+msgstr ""
+
+#: rhodecode/templates/search/search.html:7
+#: rhodecode/templates/search/search.html:26
+msgid "in repository: "
+msgstr ""
+
+#: rhodecode/templates/search/search.html:9
+#: rhodecode/templates/search/search.html:28
+msgid "in all repositories"
+msgstr ""
+
+#: rhodecode/templates/search/search.html:42
+msgid "Search term"
+msgstr ""
+
+#: rhodecode/templates/search/search.html:54
+msgid "Search in"
+msgstr ""
+
+#: rhodecode/templates/search/search.html:57
+msgid "File contents"
+msgstr ""
+
+#: rhodecode/templates/search/search.html:59
+msgid "File names"
+msgstr ""
+
+#: rhodecode/templates/search/search_content.html:20
+#: rhodecode/templates/search/search_path.html:15
+msgid "Permission denied"
+msgstr ""
+
+#: rhodecode/templates/settings/repo_fork.html:5
+msgid "Fork"
+msgstr ""
+
+#: rhodecode/templates/settings/repo_fork.html:31
+msgid "Fork name"
+msgstr ""
+
+#: rhodecode/templates/settings/repo_fork.html:55
+msgid "fork this repository"
+msgstr ""
+
+#: rhodecode/templates/shortlog/shortlog.html:5
+#: rhodecode/templates/summary/summary.html:666
+msgid "Shortlog"
+msgstr ""
+
+#: rhodecode/templates/shortlog/shortlog.html:14
+msgid "shortlog"
+msgstr ""
+
+#: rhodecode/templates/shortlog/shortlog_data.html:6
+msgid "age"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:12
+msgid "summary"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:79
+msgid "remote clone"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:121
+msgid "by"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:128
+msgid "Clone url"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:137
+msgid "Trending source files"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:146
+msgid "Download"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:150
+msgid "There are no downloads yet"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:152
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:154
+#: rhodecode/templates/summary/summary.html:320
+msgid "enable"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:162
+#: rhodecode/templates/summary/summary.html:297
+#, python-format
+msgid "Download %s as %s"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:168
+msgid "Check this to download archive with subrepos"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:168
+msgid "with subrepos"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:176
+msgid "Feeds"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:257
+#: rhodecode/templates/summary/summary.html:684
+#: rhodecode/templates/summary/summary.html:695
+msgid "show more"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:312
+msgid "Commit activity by day / author"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:324
+msgid "Loaded in"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:603
+msgid "commits"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:604
+msgid "files added"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:605
+msgid "files changed"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:606
+msgid "files removed"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:610
+msgid "file added"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:611
+msgid "file changed"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:612
+msgid "file removed"
+msgstr ""
+
--- a/rhodecode/i18n/how_to	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/i18n/how_to	Fri Oct 07 01:08:50 2011 +0200
@@ -1,15 +1,28 @@
-#goto pylons folder app (the on holding .ini files)
+##########################
+# to create new language #
+##########################
 
-# to create new 
+#this needs to be done on source codes, preferable default/stable branches
+ 
 python setup.py extract_messages -> get messages from project
-python setup.py init_catalog -l pl -> create a language directory
-edit the new po file with poedit
+python setup.py init_catalog -l pl -> create a language directory for <pl> lang
+edit the new po file with poedit or any other editor
 python setup.py compile_catalog -> create translation files
-#done 
- 
- # to update
+
+############# 
+# to update #
+#############
+
 python setup.py extract_messages -> get messages from project
 python setup.py update_catalog -> to update the translations
 edit the new updated po file with poedit
 python setup.py compile_catalog -> create translation files
-#done
\ No newline at end of file
+
+
+###################
+# change language #
+###################
+
+`lang=en`
+
+in the .ini file
\ No newline at end of file
Binary file rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.mo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/i18n/pt_BR/LC_MESSAGES/rhodecode.po	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,2530 @@
+# Portuguese (Brazil) translations for RhodeCode.
+# Copyright (C) 2011 Augusto Herrmann
+# This file is distributed under the same license as the RhodeCode project.
+# Augusto Herrmann <augusto.herrmann@gmail.com>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: RhodeCode 1.2.0\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-09-14 15:50-0300\n"
+"PO-Revision-Date: 2011-09-14 15:53-0300\n"
+"Last-Translator: Augusto Herrmann <augusto.herrmann@gmail.com>\n"
+"Language-Team: pt_BR <LL@li.org>\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+#: rhodecode/controllers/changeset.py:108
+#: rhodecode/controllers/changeset.py:149
+#: rhodecode/controllers/changeset.py:216
+#: rhodecode/controllers/changeset.py:229
+msgid "binary file"
+msgstr "arquivo binário"
+
+#: rhodecode/controllers/changeset.py:123
+#: rhodecode/controllers/changeset.py:168
+msgid "Changeset is to big and was cut off, see raw changeset instead"
+msgstr "Conjunto de mudanças é grande demais e foi cortado, em vez disso veja o conjunto de mudanças bruto"
+
+#: rhodecode/controllers/changeset.py:159
+msgid "Diff is to big and was cut off, see raw diff instead"
+msgstr "Diff é grande demais e foi cortado, em vez disso veja diff bruto"
+
+#: rhodecode/controllers/error.py:69
+msgid "Home page"
+msgstr "Página inicial"
+
+#: rhodecode/controllers/error.py:98
+msgid "The request could not be understood by the server due to malformed syntax."
+msgstr "A requisição não pôde ser compreendida pelo servidor devido à sintaxe mal formada"
+
+#: rhodecode/controllers/error.py:101
+msgid "Unauthorized access to resource"
+msgstr "Acesso não autorizado ao recurso"
+
+#: rhodecode/controllers/error.py:103
+msgid "You don't have permission to view this page"
+msgstr "Você não tem permissão para ver esta página"
+
+#: rhodecode/controllers/error.py:105
+msgid "The resource could not be found"
+msgstr "O recurso não pôde ser encontrado"
+
+#: rhodecode/controllers/error.py:107
+msgid "The server encountered an unexpected condition which prevented it from fulfilling the request."
+msgstr "O servidor encontrou uma condição inesperada que o impediu de satisfazer a requisição"
+
+#: rhodecode/controllers/feed.py:48
+#, python-format
+msgid "Changes on %s repository"
+msgstr "Alterações no repositório %s"
+
+#: rhodecode/controllers/feed.py:49
+#, python-format
+msgid "%s %s feed"
+msgstr "%s - feed %s"
+
+#: rhodecode/controllers/files.py:72
+msgid "There are no files yet"
+msgstr "Ainda não há arquivos"
+
+#: rhodecode/controllers/files.py:262
+#, python-format
+msgid "Edited %s via RhodeCode"
+msgstr "Editado %s via RhodeCode"
+
+#: rhodecode/controllers/files.py:267
+#: rhodecode/templates/files/file_diff.html:40
+msgid "No changes"
+msgstr "Sem alterações"
+
+#: rhodecode/controllers/files.py:278
+#, python-format
+msgid "Successfully committed to %s"
+msgstr "Commit realizado com sucesso para %s"
+
+#: rhodecode/controllers/files.py:283
+msgid "Error occurred during commit"
+msgstr "Ocorreu um erro ao realizar commit"
+
+#: rhodecode/controllers/files.py:308
+msgid "downloads disabled"
+msgstr "downloads desabilitados"
+
+#: rhodecode/controllers/files.py:313
+#, python-format
+msgid "Unknown revision %s"
+msgstr "Revisão desconhecida %s"
+
+#: rhodecode/controllers/files.py:315
+msgid "Empty repository"
+msgstr "Repositório vazio"
+
+#: rhodecode/controllers/files.py:317
+msgid "Unknown archive type"
+msgstr "Arquivo de tipo desconhecido"
+
+#: rhodecode/controllers/files.py:385
+#: rhodecode/controllers/files.py:398
+msgid "Binary file"
+msgstr "Arquivo binário"
+
+#: rhodecode/controllers/files.py:417
+#: rhodecode/templates/changeset/changeset_range.html:4
+#: rhodecode/templates/changeset/changeset_range.html:12
+#: rhodecode/templates/changeset/changeset_range.html:29
+msgid "Changesets"
+msgstr "Conjuntos de mudanças"
+
+#: rhodecode/controllers/files.py:418
+#: rhodecode/controllers/summary.py:175
+#: rhodecode/templates/branches/branches.html:5
+#: rhodecode/templates/summary/summary.html:690
+msgid "Branches"
+msgstr "Ramos"
+
+#: rhodecode/controllers/files.py:419
+#: rhodecode/controllers/summary.py:176
+#: rhodecode/templates/summary/summary.html:679
+#: rhodecode/templates/tags/tags.html:5
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: rhodecode/controllers/journal.py:50
+#, python-format
+msgid "%s public journal %s feed"
+msgstr "diário público de %s - feed %s"
+
+#: rhodecode/controllers/journal.py:178
+#: rhodecode/controllers/journal.py:212
+#: rhodecode/templates/admin/repos/repo_edit.html:171
+#: rhodecode/templates/base/base.html:50
+msgid "Public journal"
+msgstr "Diário público"
+
+#: rhodecode/controllers/login.py:111
+msgid "You have successfully registered into rhodecode"
+msgstr "Você se registrou com sucesso no rhodecode"
+
+#: rhodecode/controllers/login.py:133
+msgid "Your password reset link was sent"
+msgstr "Seu link de reinicialização de senha foi enviado"
+
+#: rhodecode/controllers/login.py:155
+msgid "Your password reset was successful, new password has been sent to your email"
+msgstr "Sua reinicialização de senha foi bem sucedida, sua senha foi enviada ao seu e-mail"
+
+#: rhodecode/controllers/search.py:109
+msgid "Invalid search query. Try quoting it."
+msgstr "Consulta de busca inválida. Tente usar aspas."
+
+#: rhodecode/controllers/search.py:114
+msgid "There is no index to search in. Please run whoosh indexer"
+msgstr "Não há índice onde pesquisa. Por favor execute o indexador whoosh"
+
+#: rhodecode/controllers/search.py:118
+msgid "An error occurred during this search operation"
+msgstr "Ocorreu um erro durante essa operação de busca"
+
+#: rhodecode/controllers/settings.py:61
+#: rhodecode/controllers/settings.py:171
+#, python-format
+msgid "%s repository is not mapped to db perhaps it was created or renamed from the file system please run the application again in order to rescan repositories"
+msgstr "repositório %s não está mapeado ao bd. Talvez ele tenha sido criado ou renomeado a partir do sistema de arquivos. Por favor execute a aplicação outra vez para varrer novamente por repositórios"
+
+#: rhodecode/controllers/settings.py:109
+#: rhodecode/controllers/admin/repos.py:239
+#, python-format
+msgid "Repository %s updated successfully"
+msgstr "Repositório %s atualizado com sucesso"
+
+#: rhodecode/controllers/settings.py:126
+#: rhodecode/controllers/admin/repos.py:257
+#, python-format
+msgid "error occurred during update of repository %s"
+msgstr "ocorreu um erro ao atualizar o repositório %s"
+
+#: rhodecode/controllers/settings.py:144
+#: rhodecode/controllers/admin/repos.py:275
+#, python-format
+msgid "%s repository is not mapped to db perhaps it was moved or renamed  from the filesystem please run the application again in order to rescan repositories"
+msgstr "repositório %s não está mapeado ao bd. Talvez ele tenha sido movido ou renomeado a partir do sistema de arquivos. Por favor execute a aplicação outra vez para varrer novamente por repositórios"
+
+#: rhodecode/controllers/settings.py:156
+#: rhodecode/controllers/admin/repos.py:287
+#, python-format
+msgid "deleted repository %s"
+msgstr "excluído o repositório %s"
+
+#: rhodecode/controllers/settings.py:159
+#: rhodecode/controllers/admin/repos.py:297
+#: rhodecode/controllers/admin/repos.py:303
+#, python-format
+msgid "An error occurred during deletion of %s"
+msgstr "Ocorreu um erro durante a exclusão de %s"
+
+#: rhodecode/controllers/settings.py:193
+#, python-format
+msgid "forked %s repository as %s"
+msgstr "bifurcado repositório %s como %s"
+
+#: rhodecode/controllers/settings.py:211
+#, python-format
+msgid "An error occurred during repository forking %s"
+msgstr "Ocorreu um erro ao bifurcar o repositório %s"
+
+#: rhodecode/controllers/summary.py:123
+msgid "No data loaded yet"
+msgstr "Ainda não há dados carregados"
+
+#: rhodecode/controllers/summary.py:126
+msgid "Statistics are disabled for this repository"
+msgstr "As estatísticas estão desabillitadas para este repositório"
+
+#: rhodecode/controllers/admin/ldap_settings.py:49
+msgid "BASE"
+msgstr "BASE"
+
+#: rhodecode/controllers/admin/ldap_settings.py:50
+msgid "ONELEVEL"
+msgstr "UMNÍVEL"
+
+#: rhodecode/controllers/admin/ldap_settings.py:51
+msgid "SUBTREE"
+msgstr "SUBÁRVORE"
+
+#: rhodecode/controllers/admin/ldap_settings.py:55
+msgid "NEVER"
+msgstr "NUNCA"
+
+#: rhodecode/controllers/admin/ldap_settings.py:56
+msgid "ALLOW"
+msgstr "PERMITIR"
+
+#: rhodecode/controllers/admin/ldap_settings.py:57
+msgid "TRY"
+msgstr "TENTAR"
+
+#: rhodecode/controllers/admin/ldap_settings.py:58
+msgid "DEMAND"
+msgstr "EXIGIR"
+
+#: rhodecode/controllers/admin/ldap_settings.py:59
+msgid "HARD"
+msgstr "DIFÍCIL"
+
+#: rhodecode/controllers/admin/ldap_settings.py:63
+msgid "No encryption"
+msgstr "Sem criptografia"
+
+#: rhodecode/controllers/admin/ldap_settings.py:64
+msgid "LDAPS connection"
+msgstr "Conexão LDAPS"
+
+#: rhodecode/controllers/admin/ldap_settings.py:65
+msgid "START_TLS on LDAP connection"
+msgstr "START_TLS na conexão LDAP"
+
+#: rhodecode/controllers/admin/ldap_settings.py:115
+msgid "Ldap settings updated successfully"
+msgstr "Configurações de LDAP atualizadas com sucesso"
+
+#: rhodecode/controllers/admin/ldap_settings.py:120
+msgid "Unable to activate ldap. The \"python-ldap\" library is missing."
+msgstr "Não foi possível ativar LDAP. A biblioteca \"python-ldap\" está faltando."
+
+#: rhodecode/controllers/admin/ldap_settings.py:134
+msgid "error occurred during update of ldap settings"
+msgstr "ocorreu um erro ao atualizar as configurações de LDAP"
+
+#: rhodecode/controllers/admin/permissions.py:56
+msgid "None"
+msgstr "Nenhum"
+
+#: rhodecode/controllers/admin/permissions.py:57
+msgid "Read"
+msgstr "Ler"
+
+#: rhodecode/controllers/admin/permissions.py:58
+msgid "Write"
+msgstr "Gravar"
+
+#: rhodecode/controllers/admin/permissions.py:59
+#: rhodecode/templates/admin/ldap/ldap.html:9
+#: rhodecode/templates/admin/permissions/permissions.html:9
+#: rhodecode/templates/admin/repos/repo_add.html:9
+#: rhodecode/templates/admin/repos/repo_edit.html:9
+#: rhodecode/templates/admin/repos/repos.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:8
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:8
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
+#: rhodecode/templates/admin/settings/hooks.html:9
+#: rhodecode/templates/admin/settings/settings.html:9
+#: rhodecode/templates/admin/users/user_add.html:8
+#: rhodecode/templates/admin/users/user_edit.html:9
+#: rhodecode/templates/admin/users/user_edit.html:110
+#: rhodecode/templates/admin/users/users.html:9
+#: rhodecode/templates/admin/users_groups/users_group_add.html:8
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:9
+#: rhodecode/templates/admin/users_groups/users_groups.html:9
+#: rhodecode/templates/base/base.html:279
+#: rhodecode/templates/base/base.html:366
+#: rhodecode/templates/base/base.html:368
+#: rhodecode/templates/base/base.html:370
+msgid "Admin"
+msgstr "Administrador"
+
+#: rhodecode/controllers/admin/permissions.py:62
+msgid "disabled"
+msgstr "desabilitado"
+
+#: rhodecode/controllers/admin/permissions.py:64
+msgid "allowed with manual account activation"
+msgstr "permitido com ativação manual de conta"
+
+#: rhodecode/controllers/admin/permissions.py:66
+msgid "allowed with automatic account activation"
+msgstr "permitido com ativação automática de conta"
+
+#: rhodecode/controllers/admin/permissions.py:68
+msgid "Disabled"
+msgstr "Desabilitado"
+
+#: rhodecode/controllers/admin/permissions.py:69
+msgid "Enabled"
+msgstr "Habilitado"
+
+#: rhodecode/controllers/admin/permissions.py:102
+msgid "Default permissions updated successfully"
+msgstr "Permissões padrões atualizadas com sucesso"
+
+#: rhodecode/controllers/admin/permissions.py:119
+msgid "error occurred during update of permissions"
+msgstr "ocorreu um erro ao atualizar as permissões"
+
+#: rhodecode/controllers/admin/repos.py:96
+#, python-format
+msgid "%s repository is not mapped to db perhaps it was created or renamed from the filesystem please run the application again in order to rescan repositories"
+msgstr "repositório %s não está mapeado ao bd. Talvez ele tenha sido criado ou renomeado a partir do sistema de arquivos. Por favor execute a aplicação outra vez para varrer novamente por repositórios"
+
+#: rhodecode/controllers/admin/repos.py:172
+#, python-format
+msgid "created repository %s from %s"
+msgstr "repositório %s criado a partir de %s"
+
+#: rhodecode/controllers/admin/repos.py:176
+#, python-format
+msgid "created repository %s"
+msgstr "repositório %s criado"
+
+#: rhodecode/controllers/admin/repos.py:205
+#, python-format
+msgid "error occurred during creation of repository %s"
+msgstr "ocorreu um erro ao criar o repositório %s"
+
+#: rhodecode/controllers/admin/repos.py:292
+#, python-format
+msgid "Cannot delete %s it still contains attached forks"
+msgstr "Nao é possível excluir %s pois ele ainda contém bifurcações vinculadas"
+
+#: rhodecode/controllers/admin/repos.py:320
+msgid "An error occurred during deletion of repository user"
+msgstr "Ocorreu um erro ao excluir usuário de repositório"
+
+#: rhodecode/controllers/admin/repos.py:335
+msgid "An error occurred during deletion of repository users groups"
+msgstr "Ocorreu um erro ao excluir grupo de usuário de repositório"
+
+#: rhodecode/controllers/admin/repos.py:352
+msgid "An error occurred during deletion of repository stats"
+msgstr "Ocorreu um erro ao excluir estatísticas de repositório"
+
+#: rhodecode/controllers/admin/repos.py:367
+msgid "An error occurred during cache invalidation"
+msgstr "Ocorreu um erro ao invalidar o cache"
+
+#: rhodecode/controllers/admin/repos.py:387
+msgid "Updated repository visibility in public journal"
+msgstr "Atualizada a visibilidade do repositório no diário público"
+
+#: rhodecode/controllers/admin/repos.py:390
+msgid "An error occurred during setting this repository in public journal"
+msgstr "Ocorreu um erro ao ajustar esse repositório no diário público"
+
+#: rhodecode/controllers/admin/repos.py:395
+#: rhodecode/model/forms.py:53
+msgid "Token mismatch"
+msgstr "Descompasso de Token"
+
+#: rhodecode/controllers/admin/repos.py:408
+msgid "Pulled from remote location"
+msgstr "Realizado pull de localização remota"
+
+#: rhodecode/controllers/admin/repos.py:410
+msgid "An error occurred during pull from remote location"
+msgstr "Ocorreu um erro ao realizar pull de localização remota"
+
+#: rhodecode/controllers/admin/repos_groups.py:83
+#, python-format
+msgid "created repos group %s"
+msgstr "criado grupo de repositórios %s"
+
+#: rhodecode/controllers/admin/repos_groups.py:96
+#, python-format
+msgid "error occurred during creation of repos group %s"
+msgstr "ccorreu um erro ao criar grupo de repositório %s"
+
+#: rhodecode/controllers/admin/repos_groups.py:130
+#, python-format
+msgid "updated repos group %s"
+msgstr "atualizado grupo de repositórios %s"
+
+#: rhodecode/controllers/admin/repos_groups.py:143
+#, python-format
+msgid "error occurred during update of repos group %s"
+msgstr "ocorreu um erro ao atualizar grupo de repositórios %s"
+
+#: rhodecode/controllers/admin/repos_groups.py:164
+#, python-format
+msgid "This group contains %s repositores and cannot be deleted"
+msgstr "Esse grupo contém %s repositórios e não pode ser excluído"
+
+#: rhodecode/controllers/admin/repos_groups.py:171
+#, python-format
+msgid "removed repos group %s"
+msgstr "removido grupo de repositórios %s"
+
+#: rhodecode/controllers/admin/repos_groups.py:175
+#, python-format
+msgid "error occurred during deletion of repos group %s"
+msgstr "ccorreu um erro ao excluir grupo de repositórios %s"
+
+#: rhodecode/controllers/admin/settings.py:109
+#, python-format
+msgid "Repositories successfully rescanned added: %s,removed: %s"
+msgstr "Repositórios varridos com sucesso adicionados: %s, removidos: %s"
+
+#: rhodecode/controllers/admin/settings.py:118
+msgid "Whoosh reindex task scheduled"
+msgstr "Tarefa de reindexação do whoosh agendada"
+
+#: rhodecode/controllers/admin/settings.py:143
+msgid "Updated application settings"
+msgstr "Configurações da aplicação atualizadas"
+
+#: rhodecode/controllers/admin/settings.py:148
+#: rhodecode/controllers/admin/settings.py:215
+msgid "error occurred during updating application settings"
+msgstr "ocorreu um erro ao atualizar as configurações da aplicação"
+
+#: rhodecode/controllers/admin/settings.py:210
+msgid "Updated mercurial settings"
+msgstr "Atualizadas as configurações do mercurial"
+
+#: rhodecode/controllers/admin/settings.py:236
+msgid "Added new hook"
+msgstr "Adicionado novo gancho"
+
+#: rhodecode/controllers/admin/settings.py:247
+msgid "Updated hooks"
+msgstr "Atualizados os ganchos"
+
+#: rhodecode/controllers/admin/settings.py:251
+msgid "error occurred during hook creation"
+msgstr "ocorreu um erro ao criar gancho"
+
+#: rhodecode/controllers/admin/settings.py:310
+msgid "You can't edit this user since it's crucial for entire application"
+msgstr "Você não pode editar esse usuário pois ele é crucial para toda a aplicação"
+
+#: rhodecode/controllers/admin/settings.py:339
+msgid "Your account was updated successfully"
+msgstr "Sua conta foi atualizada com sucesso"
+
+#: rhodecode/controllers/admin/settings.py:359
+#: rhodecode/controllers/admin/users.py:130
+#, python-format
+msgid "error occurred during update of user %s"
+msgstr "ocorreu um erro ao atualizar o usuário %s"
+
+#: rhodecode/controllers/admin/users.py:78
+#, python-format
+msgid "created user %s"
+msgstr "usuário %s criado"
+
+#: rhodecode/controllers/admin/users.py:90
+#, python-format
+msgid "error occurred during creation of user %s"
+msgstr "ocorreu um erro ao criar o usuário %s"
+
+#: rhodecode/controllers/admin/users.py:116
+msgid "User updated successfully"
+msgstr "Usuário atualizado com sucesso"
+
+#: rhodecode/controllers/admin/users.py:146
+msgid "successfully deleted user"
+msgstr "usuário excluído com sucesso"
+
+#: rhodecode/controllers/admin/users.py:150
+msgid "An error occurred during deletion of user"
+msgstr "Ocorreu um erro ao excluir o usuário"
+
+#: rhodecode/controllers/admin/users.py:166
+msgid "You can't edit this user"
+msgstr "Você não pode editar esse usuário"
+
+#: rhodecode/controllers/admin/users.py:195
+#: rhodecode/controllers/admin/users_groups.py:202
+msgid "Granted 'repository create' permission to user"
+msgstr "Concedida permissão de 'criar repositório' ao usuário"
+
+#: rhodecode/controllers/admin/users.py:204
+#: rhodecode/controllers/admin/users_groups.py:211
+msgid "Revoked 'repository create' permission to user"
+msgstr "Revogada permissão de 'criar repositório' ao usuário"
+
+#: rhodecode/controllers/admin/users_groups.py:74
+#, python-format
+msgid "created users group %s"
+msgstr "criado grupo de usuários %s"
+
+#: rhodecode/controllers/admin/users_groups.py:86
+#, python-format
+msgid "error occurred during creation of users group %s"
+msgstr "ocorreu um erro ao criar o grupo de usuários %s"
+
+#: rhodecode/controllers/admin/users_groups.py:119
+#, python-format
+msgid "updated users group %s"
+msgstr "grupo de usuários %s atualizado"
+
+#: rhodecode/controllers/admin/users_groups.py:138
+#, python-format
+msgid "error occurred during update of users group %s"
+msgstr "ocorreu um erro ao atualizar o grupo de usuários %s"
+
+#: rhodecode/controllers/admin/users_groups.py:154
+msgid "successfully deleted users group"
+msgstr "grupo de usuários excluído com sucesso"
+
+#: rhodecode/controllers/admin/users_groups.py:158
+msgid "An error occurred during deletion of users group"
+msgstr "Ocorreu um erro ao excluir o grupo de usuários"
+
+#: rhodecode/lib/__init__.py:279
+msgid "year"
+msgstr "ano"
+
+#: rhodecode/lib/__init__.py:280
+msgid "month"
+msgstr "mês"
+
+#: rhodecode/lib/__init__.py:281
+msgid "day"
+msgstr "dia"
+
+#: rhodecode/lib/__init__.py:282
+msgid "hour"
+msgstr "hora"
+
+#: rhodecode/lib/__init__.py:283
+msgid "minute"
+msgstr "minuto"
+
+#: rhodecode/lib/__init__.py:284
+msgid "second"
+msgstr "segundo"
+
+#: rhodecode/lib/__init__.py:293
+msgid "ago"
+msgstr "atrás"
+
+#: rhodecode/lib/__init__.py:296
+msgid "just now"
+msgstr "agora há pouco"
+
+#: rhodecode/lib/auth.py:377
+msgid "You need to be a registered user to perform this action"
+msgstr "Você precisa ser um usuário registrado para realizar essa ação"
+
+#: rhodecode/lib/auth.py:421
+msgid "You need to be a signed in to view this page"
+msgstr "Você precisa estar logado para ver essa página"
+
+#: rhodecode/lib/helpers.py:307
+msgid "True"
+msgstr "Verdadeiro"
+
+#: rhodecode/lib/helpers.py:311
+msgid "False"
+msgstr "Falso"
+
+#: rhodecode/lib/helpers.py:352
+#, python-format
+msgid "Show all combined changesets %s->%s"
+msgstr "Ver todos os conjuntos de mudanças combinados %s->%s"
+
+#: rhodecode/lib/helpers.py:356
+msgid "compare view"
+msgstr "comparar exibir"
+
+#: rhodecode/lib/helpers.py:365
+msgid "and"
+msgstr "e"
+
+#: rhodecode/lib/helpers.py:365
+#, python-format
+msgid "%s more"
+msgstr "%s mais"
+
+#: rhodecode/lib/helpers.py:367
+#: rhodecode/templates/changelog/changelog.html:14
+#: rhodecode/templates/changelog/changelog.html:39
+msgid "revisions"
+msgstr "revisões"
+
+#: rhodecode/lib/helpers.py:385
+msgid "fork name "
+msgstr "nome da bifurcação"
+
+#: rhodecode/lib/helpers.py:388
+msgid "[deleted] repository"
+msgstr "repositório [excluído]"
+
+#: rhodecode/lib/helpers.py:389
+#: rhodecode/lib/helpers.py:393
+msgid "[created] repository"
+msgstr "repositório [criado]"
+
+#: rhodecode/lib/helpers.py:390
+#: rhodecode/lib/helpers.py:394
+msgid "[forked] repository"
+msgstr "repositório [bifurcado]"
+
+#: rhodecode/lib/helpers.py:391
+#: rhodecode/lib/helpers.py:395
+msgid "[updated] repository"
+msgstr "repositório [atualizado]"
+
+#: rhodecode/lib/helpers.py:392
+msgid "[delete] repository"
+msgstr "[excluir] repositório"
+
+#: rhodecode/lib/helpers.py:396
+msgid "[pushed] into"
+msgstr "[realizado push] para"
+
+#: rhodecode/lib/helpers.py:397
+msgid "[committed via RhodeCode] into"
+msgstr "[realizado commit via RhodeCode] para"
+
+#: rhodecode/lib/helpers.py:398
+msgid "[pulled from remote] into"
+msgstr "[realizado pull remoto] para"
+
+#: rhodecode/lib/helpers.py:399
+msgid "[pulled] from"
+msgstr "[realizado pull] a partir de"
+
+#: rhodecode/lib/helpers.py:400
+msgid "[started following] repository"
+msgstr "[passou a seguir] o repositório"
+
+#: rhodecode/lib/helpers.py:401
+msgid "[stopped following] repository"
+msgstr "[parou de seguir] o repositório"
+
+#: rhodecode/lib/helpers.py:577
+#, python-format
+msgid " and %s more"
+msgstr " e mais %s"
+
+#: rhodecode/lib/helpers.py:581
+msgid "No Files"
+msgstr "Nenhum Arquivo"
+
+#: rhodecode/model/forms.py:66
+msgid "Invalid username"
+msgstr "Nome de usuário inválido"
+
+#: rhodecode/model/forms.py:75
+msgid "This username already exists"
+msgstr "Esse nome de usuário já existe"
+
+#: rhodecode/model/forms.py:79
+msgid "Username may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character"
+msgstr "Nome de usuário pode conter somente caracteres alfanuméricos, sublinha, pontos e hífens e deve iniciar com caractere alfanumérico"
+
+#: rhodecode/model/forms.py:94
+msgid "Invalid group name"
+msgstr "Nome de grupo inválido"
+
+#: rhodecode/model/forms.py:104
+msgid "This users group already exists"
+msgstr "Esse grupo de usuários já existe"
+
+#: rhodecode/model/forms.py:110
+msgid "Group name may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character"
+msgstr "Nome de grupo pode conter somente caracteres alfanuméricos, sublinha, pontos e hífens e deve iniciar com caractere alfanumérico"
+
+#: rhodecode/model/forms.py:132
+msgid "Cannot assign this group as parent"
+msgstr "Não é possível associar esse grupo como progenitor"
+
+#: rhodecode/model/forms.py:148
+msgid "This group already exists"
+msgstr "Esse grupo já existe"
+
+#: rhodecode/model/forms.py:164
+#: rhodecode/model/forms.py:172
+#: rhodecode/model/forms.py:180
+msgid "Invalid characters in password"
+msgstr "Caracteres inválidos na senha"
+
+#: rhodecode/model/forms.py:191
+msgid "Passwords do not match"
+msgstr "Senhas não conferem"
+
+#: rhodecode/model/forms.py:196
+msgid "invalid password"
+msgstr "senha inválida"
+
+#: rhodecode/model/forms.py:197
+msgid "invalid user name"
+msgstr "nome de usuário inválido"
+
+#: rhodecode/model/forms.py:198
+msgid "Your account is disabled"
+msgstr "Sua conta está desabilitada"
+
+#: rhodecode/model/forms.py:233
+msgid "This username is not valid"
+msgstr "Esse nome de usuário não é válido"
+
+#: rhodecode/model/forms.py:245
+msgid "This repository name is disallowed"
+msgstr "Esse nome de repositório não é permitido"
+
+#: rhodecode/model/forms.py:266
+#, python-format
+msgid "This repository already exists in group \"%s\""
+msgstr "Esse repositório já existe no grupo \"%s\""
+
+#: rhodecode/model/forms.py:274
+msgid "This repository already exists"
+msgstr "Esse repositório já existe"
+
+#: rhodecode/model/forms.py:312
+#: rhodecode/model/forms.py:319
+msgid "invalid clone url"
+msgstr "URL de clonagem inválida"
+
+#: rhodecode/model/forms.py:322
+msgid "Invalid clone url, provide a valid clone http\\s url"
+msgstr "URL de clonagem inválida, forneça uma URL válida de clonagem http\\s"
+
+#: rhodecode/model/forms.py:334
+msgid "Fork have to be the same type as original"
+msgstr "Bifurcação precisa ser do mesmo tipo que o original"
+
+#: rhodecode/model/forms.py:341
+msgid "This username or users group name is not valid"
+msgstr "Esse nome de usuário ou nome de grupo de usuários não é válido"
+
+#: rhodecode/model/forms.py:403
+msgid "This is not a valid path"
+msgstr "Esse não é um caminho válido"
+
+#: rhodecode/model/forms.py:416
+msgid "This e-mail address is already taken"
+msgstr "Esse endereço de e-mail já está tomado"
+
+#: rhodecode/model/forms.py:427
+msgid "This e-mail address doesn't exist."
+msgstr "Esse endereço de e-mail não existe."
+
+#: rhodecode/model/forms.py:447
+msgid "The LDAP Login attribute of the CN must be specified - this is the name of the attribute that is equivalent to 'username'"
+msgstr "O atributo de login LDAP do CN deve ser especificado - isto é o nome do atributo que é equivalente ao 'nome de usuário'"
+
+#: rhodecode/model/forms.py:466
+msgid "Please enter a login"
+msgstr "Por favor entre um login"
+
+#: rhodecode/model/forms.py:467
+#, python-format
+msgid "Enter a value %(min)i characters long or more"
+msgstr "Entre um valor com %(min)i caracteres ou mais"
+
+#: rhodecode/model/forms.py:475
+msgid "Please enter a password"
+msgstr "Por favor entre com uma senha"
+
+#: rhodecode/model/forms.py:476
+#, python-format
+msgid "Enter %(min)i characters or more"
+msgstr "Entre com %(min)i caracteres ou mais"
+
+#: rhodecode/model/user.py:145
+msgid "[RhodeCode] New User registration"
+msgstr "[RhodeCode] Registro de Novo Usuário"
+
+#: rhodecode/model/user.py:157
+#: rhodecode/model/user.py:179
+msgid "You can't Edit this user since it's crucial for entire application"
+msgstr "Você não pode Editar esse usuário, pois ele é crucial para toda a aplicação"
+
+#: rhodecode/model/user.py:201
+msgid "You can't remove this user since it's crucial for entire application"
+msgstr "Você não pode remover esse usuário, pois ele é crucial para toda a aplicação"
+
+#: rhodecode/model/user.py:204
+#, python-format
+msgid "This user still owns %s repositories and cannot be removed. Switch owners or remove those repositories"
+msgstr "Esse usuário ainda é dono de %s repositórios e não pode ser removido. Troque os donos ou remova esses repositórios"
+
+#: rhodecode/templates/index.html:4
+msgid "Dashboard"
+msgstr "Painel de Controle"
+
+#: rhodecode/templates/index_base.html:22
+#: rhodecode/templates/admin/users/user_edit_my_account.html:102
+msgid "quick filter..."
+msgstr "filtro rápido..."
+
+#: rhodecode/templates/index_base.html:23
+#: rhodecode/templates/base/base.html:300
+msgid "repositories"
+msgstr "repositórios"
+
+#: rhodecode/templates/index_base.html:29
+#: rhodecode/templates/admin/repos/repos.html:22
+msgid "ADD NEW REPOSITORY"
+msgstr "ADICIONAR NOVO REPOSITÓRIO"
+
+#: rhodecode/templates/index_base.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:32
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:32
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:33
+#: rhodecode/templates/admin/users_groups/users_group_add.html:32
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:33
+msgid "Group name"
+msgstr "Nome do grupo"
+
+#: rhodecode/templates/index_base.html:42
+#: rhodecode/templates/index_base.html:73
+#: rhodecode/templates/admin/repos/repo_add_base.html:44
+#: rhodecode/templates/admin/repos/repo_edit.html:64
+#: rhodecode/templates/admin/repos/repos.html:31
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:34
+#: rhodecode/templates/settings/repo_fork.html:40
+#: rhodecode/templates/settings/repo_settings.html:40
+#: rhodecode/templates/summary/summary.html:92
+msgid "Description"
+msgstr "Descrição"
+
+#: rhodecode/templates/index_base.html:53
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46
+msgid "Repositories group"
+msgstr "Grupo de repositórios"
+
+#: rhodecode/templates/index_base.html:72
+#: rhodecode/templates/admin/repos/repo_add_base.html:9
+#: rhodecode/templates/admin/repos/repo_edit.html:32
+#: rhodecode/templates/admin/repos/repos.html:30
+#: rhodecode/templates/admin/users/user_edit_my_account.html:117
+#: rhodecode/templates/files/files_browser.html:157
+#: rhodecode/templates/settings/repo_settings.html:31
+#: rhodecode/templates/summary/summary.html:31
+#: rhodecode/templates/summary/summary.html:107
+msgid "Name"
+msgstr "Nome"
+
+#: rhodecode/templates/index_base.html:74
+#: rhodecode/templates/admin/repos/repos.html:32
+#: rhodecode/templates/summary/summary.html:114
+msgid "Last change"
+msgstr "Última alteração"
+
+#: rhodecode/templates/index_base.html:75
+#: rhodecode/templates/admin/repos/repos.html:33
+msgid "Tip"
+msgstr "Ponta"
+
+#: rhodecode/templates/index_base.html:76
+#: rhodecode/templates/admin/repos/repo_edit.html:97
+msgid "Owner"
+msgstr "Dono"
+
+#: rhodecode/templates/index_base.html:77
+#: rhodecode/templates/journal/public_journal.html:20
+#: rhodecode/templates/summary/summary.html:180
+#: rhodecode/templates/summary/summary.html:183
+msgid "RSS"
+msgstr "RSS"
+
+#: rhodecode/templates/index_base.html:78
+#: rhodecode/templates/journal/public_journal.html:23
+#: rhodecode/templates/summary/summary.html:181
+#: rhodecode/templates/summary/summary.html:184
+msgid "Atom"
+msgstr "Atom"
+
+#: rhodecode/templates/index_base.html:87
+#: rhodecode/templates/index_base.html:89
+#: rhodecode/templates/index_base.html:91
+#: rhodecode/templates/base/base.html:209
+#: rhodecode/templates/base/base.html:211
+#: rhodecode/templates/base/base.html:213
+#: rhodecode/templates/summary/summary.html:4
+msgid "Summary"
+msgstr "Sumário"
+
+#: rhodecode/templates/index_base.html:95
+#: rhodecode/templates/index_base.html:97
+#: rhodecode/templates/index_base.html:99
+#: rhodecode/templates/base/base.html:225
+#: rhodecode/templates/base/base.html:227
+#: rhodecode/templates/base/base.html:229
+#: rhodecode/templates/changelog/changelog.html:6
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "Changelog"
+msgstr "Registro de alterações"
+
+#: rhodecode/templates/index_base.html:103
+#: rhodecode/templates/index_base.html:105
+#: rhodecode/templates/index_base.html:107
+#: rhodecode/templates/base/base.html:268
+#: rhodecode/templates/base/base.html:270
+#: rhodecode/templates/base/base.html:272
+#: rhodecode/templates/files/files.html:4
+msgid "Files"
+msgstr "Arquivos"
+
+#: rhodecode/templates/index_base.html:116
+#: rhodecode/templates/admin/repos/repos.html:42
+#: rhodecode/templates/admin/users/user_edit_my_account.html:127
+#: rhodecode/templates/summary/summary.html:48
+msgid "Mercurial repository"
+msgstr "Repositório Mercurial"
+
+#: rhodecode/templates/index_base.html:118
+#: rhodecode/templates/admin/repos/repos.html:44
+#: rhodecode/templates/admin/users/user_edit_my_account.html:129
+#: rhodecode/templates/summary/summary.html:51
+msgid "Git repository"
+msgstr "Repositório Git"
+
+#: rhodecode/templates/index_base.html:123
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:16
+#: rhodecode/templates/journal/journal.html:53
+#: rhodecode/templates/summary/summary.html:56
+msgid "private repository"
+msgstr "repositório privado"
+
+#: rhodecode/templates/index_base.html:125
+#: rhodecode/templates/journal/journal.html:55
+#: rhodecode/templates/summary/summary.html:58
+msgid "public repository"
+msgstr "repositório público"
+
+#: rhodecode/templates/index_base.html:133
+#: rhodecode/templates/base/base.html:291
+#: rhodecode/templates/settings/repo_fork.html:13
+msgid "fork"
+msgstr "bifurcação"
+
+#: rhodecode/templates/index_base.html:134
+#: rhodecode/templates/admin/repos/repos.html:60
+#: rhodecode/templates/admin/users/user_edit_my_account.html:143
+#: rhodecode/templates/summary/summary.html:69
+#: rhodecode/templates/summary/summary.html:71
+msgid "Fork of"
+msgstr "Bifurcação de"
+
+#: rhodecode/templates/index_base.html:155
+#: rhodecode/templates/admin/repos/repos.html:73
+msgid "No changesets yet"
+msgstr "Ainda não há conjuntos de mudanças"
+
+#: rhodecode/templates/index_base.html:161
+#: rhodecode/templates/index_base.html:163
+#, python-format
+msgid "Subscribe to %s rss feed"
+msgstr "Assinar o feed rss de %s"
+
+#: rhodecode/templates/index_base.html:168
+#: rhodecode/templates/index_base.html:170
+#, python-format
+msgid "Subscribe to %s atom feed"
+msgstr "Assinar o feed atom de %s"
+
+#: rhodecode/templates/login.html:5
+#: rhodecode/templates/login.html:54
+#: rhodecode/templates/base/base.html:38
+msgid "Sign In"
+msgstr "Entrar"
+
+#: rhodecode/templates/login.html:21
+msgid "Sign In to"
+msgstr "Entrar em"
+
+#: rhodecode/templates/login.html:31
+#: rhodecode/templates/register.html:20
+#: rhodecode/templates/admin/admin_log.html:5
+#: rhodecode/templates/admin/users/user_add.html:32
+#: rhodecode/templates/admin/users/user_edit.html:47
+#: rhodecode/templates/admin/users/user_edit_my_account.html:45
+#: rhodecode/templates/base/base.html:15
+#: rhodecode/templates/summary/summary.html:106
+msgid "Username"
+msgstr "Nome de usuário"
+
+#: rhodecode/templates/login.html:40
+#: rhodecode/templates/register.html:29
+#: rhodecode/templates/admin/ldap/ldap.html:46
+#: rhodecode/templates/admin/users/user_add.html:41
+#: rhodecode/templates/base/base.html:24
+msgid "Password"
+msgstr "Senha"
+
+#: rhodecode/templates/login.html:60
+msgid "Forgot your password ?"
+msgstr "Esqueceu sua senha ?"
+
+#: rhodecode/templates/login.html:63
+#: rhodecode/templates/base/base.html:35
+msgid "Don't have an account ?"
+msgstr "Não possui uma conta ?"
+
+#: rhodecode/templates/password_reset.html:5
+msgid "Reset your password"
+msgstr "Reinicializar sua senha"
+
+#: rhodecode/templates/password_reset.html:11
+msgid "Reset your password to"
+msgstr "Reinicializar sua senha para"
+
+#: rhodecode/templates/password_reset.html:21
+msgid "Email address"
+msgstr "Endereço de e-mail"
+
+#: rhodecode/templates/password_reset.html:30
+msgid "Reset my password"
+msgstr "Reinicializar minha senha"
+
+#: rhodecode/templates/password_reset.html:31
+msgid "Password reset link will be send to matching email address"
+msgstr "Link de reinicialização de senha será enviado ao endereço de e-mail correspondente"
+
+#: rhodecode/templates/register.html:5
+#: rhodecode/templates/register.html:74
+msgid "Sign Up"
+msgstr "Inscrever-se"
+
+#: rhodecode/templates/register.html:11
+msgid "Sign Up to"
+msgstr "Inscrever-se em"
+
+#: rhodecode/templates/register.html:38
+msgid "Re-enter password"
+msgstr "Repita a senha"
+
+#: rhodecode/templates/register.html:47
+#: rhodecode/templates/admin/users/user_add.html:50
+#: rhodecode/templates/admin/users/user_edit.html:74
+#: rhodecode/templates/admin/users/user_edit_my_account.html:63
+msgid "First Name"
+msgstr "Primeiro Nome"
+
+#: rhodecode/templates/register.html:56
+#: rhodecode/templates/admin/users/user_add.html:59
+#: rhodecode/templates/admin/users/user_edit.html:83
+#: rhodecode/templates/admin/users/user_edit_my_account.html:72
+msgid "Last Name"
+msgstr "Último Nome"
+
+#: rhodecode/templates/register.html:65
+#: rhodecode/templates/admin/users/user_add.html:68
+#: rhodecode/templates/admin/users/user_edit.html:92
+#: rhodecode/templates/admin/users/user_edit_my_account.html:81
+#: rhodecode/templates/summary/summary.html:108
+msgid "Email"
+msgstr "E-mail"
+
+#: rhodecode/templates/register.html:76
+msgid "Your account will be activated right after registration"
+msgstr "Sua conta será ativada logo após o registro ser concluído"
+
+#: rhodecode/templates/register.html:78
+msgid "Your account must wait for activation by administrator"
+msgstr "Sua conta precisa esperar ativação por um administrador"
+
+#: rhodecode/templates/repo_switcher_list.html:14
+msgid "Private repository"
+msgstr "Repositório privado"
+
+#: rhodecode/templates/repo_switcher_list.html:19
+msgid "Public repository"
+msgstr "Repositório público"
+
+#: rhodecode/templates/admin/admin.html:5
+#: rhodecode/templates/admin/admin.html:9
+msgid "Admin journal"
+msgstr "Diário do administrador"
+
+#: rhodecode/templates/admin/admin_log.html:6
+msgid "Action"
+msgstr "Ação"
+
+#: rhodecode/templates/admin/admin_log.html:7
+msgid "Repository"
+msgstr "Repositório"
+
+#: rhodecode/templates/admin/admin_log.html:8
+msgid "Date"
+msgstr "Data"
+
+#: rhodecode/templates/admin/admin_log.html:9
+msgid "From IP"
+msgstr "A partir do IP"
+
+#: rhodecode/templates/admin/admin_log.html:52
+msgid "No actions yet"
+msgstr "Ainda não há ações"
+
+#: rhodecode/templates/admin/ldap/ldap.html:5
+msgid "LDAP administration"
+msgstr "Administração de LDAP"
+
+#: rhodecode/templates/admin/ldap/ldap.html:11
+msgid "Ldap"
+msgstr "LDAP"
+
+#: rhodecode/templates/admin/ldap/ldap.html:28
+msgid "Connection settings"
+msgstr "Configurações de conexão"
+
+#: rhodecode/templates/admin/ldap/ldap.html:30
+msgid "Enable LDAP"
+msgstr "Habilitar LDAP"
+
+#: rhodecode/templates/admin/ldap/ldap.html:34
+msgid "Host"
+msgstr "Host"
+
+#: rhodecode/templates/admin/ldap/ldap.html:38
+msgid "Port"
+msgstr "Porta"
+
+#: rhodecode/templates/admin/ldap/ldap.html:42
+msgid "Account"
+msgstr "Conta"
+
+#: rhodecode/templates/admin/ldap/ldap.html:50
+msgid "Connection security"
+msgstr "Segurança da conexão"
+
+#: rhodecode/templates/admin/ldap/ldap.html:54
+msgid "Certificate Checks"
+msgstr "Verificações de Certificados"
+
+#: rhodecode/templates/admin/ldap/ldap.html:57
+msgid "Search settings"
+msgstr "Configurações de busca"
+
+#: rhodecode/templates/admin/ldap/ldap.html:59
+msgid "Base DN"
+msgstr "DN Base"
+
+#: rhodecode/templates/admin/ldap/ldap.html:63
+msgid "LDAP Filter"
+msgstr "Filtro LDAP"
+
+#: rhodecode/templates/admin/ldap/ldap.html:67
+msgid "LDAP Search Scope"
+msgstr "Escopo de Buscas LDAP"
+
+#: rhodecode/templates/admin/ldap/ldap.html:70
+msgid "Attribute mappings"
+msgstr "Mapeamento de atributos"
+
+#: rhodecode/templates/admin/ldap/ldap.html:72
+msgid "Login Attribute"
+msgstr "Atributo de Login"
+
+#: rhodecode/templates/admin/ldap/ldap.html:76
+msgid "First Name Attribute"
+msgstr "Atributo do Primeiro Nome"
+
+#: rhodecode/templates/admin/ldap/ldap.html:80
+msgid "Last Name Attribute"
+msgstr "Atributo do Último Nome"
+
+#: rhodecode/templates/admin/ldap/ldap.html:84
+msgid "E-mail Attribute"
+msgstr "Atributo de E-mail"
+
+#: rhodecode/templates/admin/ldap/ldap.html:89
+#: rhodecode/templates/admin/settings/hooks.html:73
+#: rhodecode/templates/admin/users/user_edit.html:117
+#: rhodecode/templates/admin/users/user_edit.html:142
+#: rhodecode/templates/admin/users/user_edit_my_account.html:89
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:263
+msgid "Save"
+msgstr "Salvar"
+
+#: rhodecode/templates/admin/permissions/permissions.html:5
+msgid "Permissions administration"
+msgstr "Administração de permissões"
+
+#: rhodecode/templates/admin/permissions/permissions.html:11
+#: rhodecode/templates/admin/repos/repo_edit.html:109
+#: rhodecode/templates/admin/users/user_edit.html:127
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:248
+#: rhodecode/templates/settings/repo_settings.html:58
+msgid "Permissions"
+msgstr "Permissões"
+
+#: rhodecode/templates/admin/permissions/permissions.html:24
+msgid "Default permissions"
+msgstr "Permissões padrão"
+
+#: rhodecode/templates/admin/permissions/permissions.html:31
+msgid "Anonymous access"
+msgstr "Acesso anônimo"
+
+#: rhodecode/templates/admin/permissions/permissions.html:41
+msgid "Repository permission"
+msgstr "Permissão de repositório"
+
+#: rhodecode/templates/admin/permissions/permissions.html:49
+msgid "All default permissions on each repository will be reset to choosen permission, note that all custom default permission on repositories will be lost"
+msgstr "Todas as permissões padrão em cada repositório serão reinicializadas para as permissões escolhidas. Note que todas as permissões padrão customizadas nos repositórios serão perdidas"
+
+#: rhodecode/templates/admin/permissions/permissions.html:50
+msgid "overwrite existing settings"
+msgstr "sobrescrever configurações existentes"
+
+#: rhodecode/templates/admin/permissions/permissions.html:55
+msgid "Registration"
+msgstr "Registro"
+
+#: rhodecode/templates/admin/permissions/permissions.html:63
+msgid "Repository creation"
+msgstr "Criação de repositório"
+
+#: rhodecode/templates/admin/permissions/permissions.html:71
+msgid "set"
+msgstr "ajustar"
+
+#: rhodecode/templates/admin/repos/repo_add.html:5
+#: rhodecode/templates/admin/repos/repo_add_create_repository.html:5
+msgid "Add repository"
+msgstr "Adicionar repositório"
+
+#: rhodecode/templates/admin/repos/repo_add.html:11
+#: rhodecode/templates/admin/repos/repo_edit.html:11
+#: rhodecode/templates/admin/repos/repos.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
+msgid "Repositories"
+msgstr "Repositórios"
+
+#: rhodecode/templates/admin/repos/repo_add.html:13
+msgid "add new"
+msgstr "adicionar novo"
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:20
+#: rhodecode/templates/summary/summary.html:80
+#: rhodecode/templates/summary/summary.html:82
+msgid "Clone from"
+msgstr "Clonar de"
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:28
+#: rhodecode/templates/admin/repos/repo_edit.html:48
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:4
+msgid "Repository group"
+msgstr "Grupo de repositórios"
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:36
+#: rhodecode/templates/admin/repos/repo_edit.html:56
+msgid "Type"
+msgstr "Tipo"
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:52
+#: rhodecode/templates/admin/repos/repo_edit.html:73
+#: rhodecode/templates/settings/repo_fork.html:48
+#: rhodecode/templates/settings/repo_settings.html:49
+msgid "Private"
+msgstr "Privado"
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:59
+msgid "add"
+msgstr "adicionar"
+
+#: rhodecode/templates/admin/repos/repo_add_create_repository.html:9
+msgid "add new repository"
+msgstr "adicionar novo repositório"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:5
+msgid "Edit repository"
+msgstr "Editar repositório"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:13
+#: rhodecode/templates/admin/users/user_edit.html:13
+#: rhodecode/templates/admin/users/user_edit_my_account.html:148
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:13
+#: rhodecode/templates/files/files_annotate.html:49
+#: rhodecode/templates/files/files_source.html:20
+msgid "edit"
+msgstr "editar"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:40
+msgid "Clone uri"
+msgstr "URI de clonagem"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:81
+msgid "Enable statistics"
+msgstr "Habilitar estatísticas"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:89
+msgid "Enable downloads"
+msgstr "Habilitar downloads"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:127
+msgid "Administration"
+msgstr "Administração"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:130
+msgid "Statistics"
+msgstr "Estatísticas"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:134
+msgid "Reset current statistics"
+msgstr "Reinicializar estatísticas atuais"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:134
+msgid "Confirm to remove current statistics"
+msgstr "Confirma remover atuais estatísticas"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:137
+msgid "Fetched to rev"
+msgstr "Trazida à rev"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:138
+msgid "Percentage of stats gathered"
+msgstr "Porcentagem das estatísticas totalizadas"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:147
+msgid "Remote"
+msgstr "Remoto"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:151
+msgid "Pull changes from remote location"
+msgstr "Realizar pull de alterações a partir de localização remota"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:151
+msgid "Confirm to pull changes from remote side"
+msgstr "Confirma realizar pull de alterações a partir de lado remoto"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:162
+msgid "Cache"
+msgstr "Cache"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:166
+msgid "Invalidate repository cache"
+msgstr "Invalidar cache do repositório"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:166
+msgid "Confirm to invalidate repository cache"
+msgstr "Confirma invalidar cache do repositório"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:177
+msgid "Remove from public journal"
+msgstr "Remover do diário público"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:179
+msgid "Add to public journal"
+msgstr "Adicionar ao diário público"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:185
+msgid "Delete"
+msgstr "Excluir"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:189
+msgid "Remove this repository"
+msgstr "Remover deste repositório"
+
+#: rhodecode/templates/admin/repos/repo_edit.html:189
+#: rhodecode/templates/admin/repos/repos.html:79
+msgid "Confirm to delete this repository"
+msgstr "Confirma excluir este repositório"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:3
+msgid "none"
+msgstr "nenhum"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:4
+msgid "read"
+msgstr "ler"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:5
+msgid "write"
+msgstr "escrever"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:6
+#: rhodecode/templates/admin/users/users.html:38
+#: rhodecode/templates/base/base.html:296
+msgid "admin"
+msgstr "administrador"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:7
+msgid "member"
+msgstr "membro"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:33
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:53
+msgid "revoke"
+msgstr "revogar"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:75
+msgid "Add another member"
+msgstr "Adicionar outro membro"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:89
+msgid "Failed to remove user"
+msgstr "Falha ao reomver usuário"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:104
+msgid "Failed to remove users group"
+msgstr "Falha ao remover grupo de usuários"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:205
+msgid "Group"
+msgstr "Grupo"
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:206
+#: rhodecode/templates/admin/users_groups/users_groups.html:33
+msgid "members"
+msgstr "membros"
+
+#: rhodecode/templates/admin/repos/repos.html:5
+msgid "Repositories administration"
+msgstr "Administração de repositórios"
+
+#: rhodecode/templates/admin/repos/repos.html:34
+#: rhodecode/templates/summary/summary.html:100
+msgid "Contact"
+msgstr "Contato"
+
+#: rhodecode/templates/admin/repos/repos.html:35
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:36
+#: rhodecode/templates/admin/users/user_edit_my_account.html:119
+#: rhodecode/templates/admin/users/users.html:40
+#: rhodecode/templates/admin/users_groups/users_groups.html:35
+msgid "action"
+msgstr "ação"
+
+#: rhodecode/templates/admin/repos/repos.html:51
+#: rhodecode/templates/admin/users/user_edit_my_account.html:134
+#: rhodecode/templates/admin/users/user_edit_my_account.html:148
+msgid "private"
+msgstr "privado"
+
+#: rhodecode/templates/admin/repos/repos.html:53
+#: rhodecode/templates/admin/repos/repos.html:59
+#: rhodecode/templates/admin/users/user_edit_my_account.html:136
+#: rhodecode/templates/admin/users/user_edit_my_account.html:142
+#: rhodecode/templates/summary/summary.html:68
+msgid "public"
+msgstr "público"
+
+#: rhodecode/templates/admin/repos/repos.html:79
+#: rhodecode/templates/admin/users/users.html:55
+msgid "delete"
+msgstr "excluir"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:8
+msgid "Groups"
+msgstr "Grupos"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:13
+msgid "with"
+msgstr "com"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5
+msgid "Add repos group"
+msgstr "Adicionar grupo de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:10
+msgid "Repos groups"
+msgstr "Grupo de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:12
+msgid "add new repos group"
+msgstr "adicionar novo grupo de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:50
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:50
+msgid "Group parent"
+msgstr "Progenitor do grupo"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:58
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:58
+#: rhodecode/templates/admin/users/user_add.html:85
+#: rhodecode/templates/admin/users_groups/users_group_add.html:49
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:90
+msgid "save"
+msgstr "salvar"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5
+msgid "Edit repos group"
+msgstr "Editar grupo de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:12
+msgid "edit repos group"
+msgstr "editar grupo de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5
+msgid "Repositories groups administration"
+msgstr "Administração de grupos de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:22
+msgid "ADD NEW GROUP"
+msgstr "ADICIONAR NOVO GRUPO"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:35
+msgid "Number of repositories"
+msgstr "Número de repositórios"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:54
+msgid "Confirm to delete this group"
+msgstr "Confirme para excluir este grupo"
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:62
+msgid "There are no repositories groups yet"
+msgstr "Ainda não há grupos de repositórios"
+
+#: rhodecode/templates/admin/settings/hooks.html:5
+#: rhodecode/templates/admin/settings/settings.html:5
+msgid "Settings administration"
+msgstr "Administração de configurações"
+
+#: rhodecode/templates/admin/settings/hooks.html:9
+#: rhodecode/templates/admin/settings/settings.html:9
+#: rhodecode/templates/settings/repo_settings.html:5
+#: rhodecode/templates/settings/repo_settings.html:13
+msgid "Settings"
+msgstr "Configurações"
+
+#: rhodecode/templates/admin/settings/hooks.html:24
+msgid "Built in hooks - read only"
+msgstr "Ganchos pré-definidos - somente leitura"
+
+#: rhodecode/templates/admin/settings/hooks.html:40
+msgid "Custom hooks"
+msgstr "Ganchos customizados"
+
+#: rhodecode/templates/admin/settings/hooks.html:56
+msgid "remove"
+msgstr "remover"
+
+#: rhodecode/templates/admin/settings/hooks.html:88
+msgid "Failed to remove hook"
+msgstr "Falha ao remover gancho"
+
+#: rhodecode/templates/admin/settings/settings.html:24
+msgid "Remap and rescan repositories"
+msgstr "Remapear e varrer novamente repositórios"
+
+#: rhodecode/templates/admin/settings/settings.html:32
+msgid "rescan option"
+msgstr "opção de varredura"
+
+#: rhodecode/templates/admin/settings/settings.html:38
+msgid "In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it."
+msgstr "Caso um repositório tenha sido excluído do sistema de arquivos e haja restos no banco de dados, marque esta opção para varrer dados obsoletos no banco e removê-los."
+
+#: rhodecode/templates/admin/settings/settings.html:39
+msgid "destroy old data"
+msgstr "destruir dados antigos"
+
+#: rhodecode/templates/admin/settings/settings.html:45
+msgid "Rescan repositories"
+msgstr "Varrer repositórios"
+
+#: rhodecode/templates/admin/settings/settings.html:51
+msgid "Whoosh indexing"
+msgstr "Indexação do Whoosh"
+
+#: rhodecode/templates/admin/settings/settings.html:59
+msgid "index build option"
+msgstr "opção de construção de índice"
+
+#: rhodecode/templates/admin/settings/settings.html:64
+msgid "build from scratch"
+msgstr "construir do início"
+
+#: rhodecode/templates/admin/settings/settings.html:70
+msgid "Reindex"
+msgstr "Reindexar"
+
+#: rhodecode/templates/admin/settings/settings.html:76
+msgid "Global application settings"
+msgstr "Configurações globais da aplicação"
+
+#: rhodecode/templates/admin/settings/settings.html:85
+msgid "Application name"
+msgstr "Nome da aplicação"
+
+#: rhodecode/templates/admin/settings/settings.html:94
+msgid "Realm text"
+msgstr "Texto de esfera"
+
+#: rhodecode/templates/admin/settings/settings.html:103
+msgid "GA code"
+msgstr "Código GA"
+
+#: rhodecode/templates/admin/settings/settings.html:111
+#: rhodecode/templates/admin/settings/settings.html:177
+msgid "Save settings"
+msgstr "Salvar configurações"
+
+#: rhodecode/templates/admin/settings/settings.html:112
+#: rhodecode/templates/admin/settings/settings.html:178
+#: rhodecode/templates/admin/users/user_edit.html:118
+#: rhodecode/templates/admin/users/user_edit.html:143
+#: rhodecode/templates/admin/users/user_edit_my_account.html:90
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:264
+#: rhodecode/templates/files/files_edit.html:50
+msgid "Reset"
+msgstr "Limpar"
+
+#: rhodecode/templates/admin/settings/settings.html:118
+msgid "Mercurial settings"
+msgstr "Configurações do Mercurial"
+
+#: rhodecode/templates/admin/settings/settings.html:127
+msgid "Web"
+msgstr "Web"
+
+#: rhodecode/templates/admin/settings/settings.html:132
+msgid "require ssl for pushing"
+msgstr "exigir ssl para realizar push"
+
+#: rhodecode/templates/admin/settings/settings.html:139
+msgid "Hooks"
+msgstr "Ganchos"
+
+#: rhodecode/templates/admin/settings/settings.html:142
+msgid "advanced setup"
+msgstr "confirguações avançadas"
+
+#: rhodecode/templates/admin/settings/settings.html:147
+msgid "Update repository after push (hg update)"
+msgstr "Atualizar repositório após realizar push (hg update)"
+
+#: rhodecode/templates/admin/settings/settings.html:151
+msgid "Show repository size after push"
+msgstr "Mostrar tamanho do repositório após o push"
+
+#: rhodecode/templates/admin/settings/settings.html:155
+msgid "Log user push commands"
+msgstr "Armazenar registro de comandos de push dos usuários"
+
+#: rhodecode/templates/admin/settings/settings.html:159
+msgid "Log user pull commands"
+msgstr "Armazenar registro de comandos de pull dos usuários"
+
+#: rhodecode/templates/admin/settings/settings.html:166
+msgid "Repositories location"
+msgstr "Localização dos repositórios"
+
+#: rhodecode/templates/admin/settings/settings.html:171
+msgid "This a crucial application setting. If you are really sure you need to change this, you must restart application in order to make this setting take effect. Click this label to unlock."
+msgstr "Essa é uma configuração crucial da aplicação. Se você realmente tem certeza de que quer mudar isto, você precisa reiniciar a aplicação para que essa configuração tenha efeito. Clique este rótulo para destravar."
+
+#: rhodecode/templates/admin/settings/settings.html:172
+msgid "unlock"
+msgstr "destravar"
+
+#: rhodecode/templates/admin/users/user_add.html:5
+msgid "Add user"
+msgstr "Adicionar usuário"
+
+#: rhodecode/templates/admin/users/user_add.html:10
+#: rhodecode/templates/admin/users/user_edit.html:11
+#: rhodecode/templates/admin/users/users.html:9
+msgid "Users"
+msgstr "Usuários"
+
+#: rhodecode/templates/admin/users/user_add.html:12
+msgid "add new user"
+msgstr "adicionar novo usuário"
+
+#: rhodecode/templates/admin/users/user_add.html:77
+#: rhodecode/templates/admin/users/user_edit.html:101
+#: rhodecode/templates/admin/users_groups/users_group_add.html:41
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:42
+msgid "Active"
+msgstr "Ativo"
+
+#: rhodecode/templates/admin/users/user_edit.html:5
+msgid "Edit user"
+msgstr "Editar usuário"
+
+#: rhodecode/templates/admin/users/user_edit.html:33
+#: rhodecode/templates/admin/users/user_edit_my_account.html:32
+msgid "Change your avatar at"
+msgstr "Altere o seu avatar em"
+
+#: rhodecode/templates/admin/users/user_edit.html:34
+#: rhodecode/templates/admin/users/user_edit_my_account.html:33
+msgid "Using"
+msgstr "Usando"
+
+#: rhodecode/templates/admin/users/user_edit.html:40
+#: rhodecode/templates/admin/users/user_edit_my_account.html:39
+msgid "API key"
+msgstr "Chave de API"
+
+#: rhodecode/templates/admin/users/user_edit.html:56
+msgid "LDAP DN"
+msgstr "DN LDAP"
+
+#: rhodecode/templates/admin/users/user_edit.html:65
+#: rhodecode/templates/admin/users/user_edit_my_account.html:54
+msgid "New password"
+msgstr "Nova senha"
+
+#: rhodecode/templates/admin/users/user_edit.html:135
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:256
+msgid "Create repositories"
+msgstr "Criar repositórios"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:5
+msgid "My account"
+msgstr "Minha conta"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:9
+msgid "My Account"
+msgstr "Minha Conta"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:101
+msgid "My repositories"
+msgstr "Meus repositórios"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:107
+msgid "ADD REPOSITORY"
+msgstr "ADICIONAR REPOSITÓRIO"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:118
+#: rhodecode/templates/branches/branches_data.html:7
+#: rhodecode/templates/shortlog/shortlog_data.html:8
+#: rhodecode/templates/tags/tags_data.html:7
+msgid "revision"
+msgstr "revisão"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:157
+msgid "No repositories yet"
+msgstr "Ainda não há repositórios"
+
+#: rhodecode/templates/admin/users/user_edit_my_account.html:159
+msgid "create one now"
+msgstr "criar um agora"
+
+#: rhodecode/templates/admin/users/users.html:5
+msgid "Users administration"
+msgstr "Administração de usuários"
+
+#: rhodecode/templates/admin/users/users.html:23
+msgid "ADD NEW USER"
+msgstr "ADICIONAR NOVO USUÁRIO"
+
+#: rhodecode/templates/admin/users/users.html:33
+msgid "username"
+msgstr "nome de usuário"
+
+#: rhodecode/templates/admin/users/users.html:34
+#: rhodecode/templates/branches/branches_data.html:5
+#: rhodecode/templates/tags/tags_data.html:5
+msgid "name"
+msgstr "nome"
+
+#: rhodecode/templates/admin/users/users.html:35
+msgid "lastname"
+msgstr "sobrenome"
+
+#: rhodecode/templates/admin/users/users.html:36
+msgid "last login"
+msgstr "último login"
+
+#: rhodecode/templates/admin/users/users.html:37
+#: rhodecode/templates/admin/users_groups/users_groups.html:34
+msgid "active"
+msgstr "ativo"
+
+#: rhodecode/templates/admin/users/users.html:39
+#: rhodecode/templates/base/base.html:305
+msgid "ldap"
+msgstr "ldap"
+
+#: rhodecode/templates/admin/users/users.html:56
+msgid "Confirm to delete this user"
+msgstr "Conforma excluir este usuário"
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:5
+msgid "Add users group"
+msgstr "Adicionar grupo de usuários"
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:10
+#: rhodecode/templates/admin/users_groups/users_groups.html:9
+msgid "Users groups"
+msgstr "Grupos de usuários"
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:12
+msgid "add new users group"
+msgstr "Adicionar novo grupo de usuários"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:5
+msgid "Edit users group"
+msgstr "Editar grupo de usuários"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:11
+msgid "UsersGroups"
+msgstr "Grupos de Usuários"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:50
+msgid "Members"
+msgstr "Membros"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:58
+msgid "Choosen group members"
+msgstr "Membros escolhidos do grupo"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:61
+msgid "Remove all elements"
+msgstr "Remover todos os elementos"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:75
+msgid "Available members"
+msgstr "Membros disponíveis"
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:79
+msgid "Add all elements"
+msgstr "Adicionar todos os elementos"
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:5
+msgid "Users groups administration"
+msgstr "Administração de grupos de usuários"
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:23
+msgid "ADD NEW USER GROUP"
+msgstr "ADICIONAR NOVO GRUPO DE USUÁRIOS"
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:32
+msgid "group name"
+msgstr "nome do grupo"
+
+#: rhodecode/templates/base/base.html:32
+msgid "Forgot password ?"
+msgstr "Esqueceu a senha ?"
+
+#: rhodecode/templates/base/base.html:57
+#: rhodecode/templates/base/base.html:338
+#: rhodecode/templates/base/base.html:340
+#: rhodecode/templates/base/base.html:342
+msgid "Home"
+msgstr "Início"
+
+#: rhodecode/templates/base/base.html:61
+#: rhodecode/templates/base/base.html:347
+#: rhodecode/templates/base/base.html:349
+#: rhodecode/templates/base/base.html:351
+#: rhodecode/templates/journal/journal.html:4
+#: rhodecode/templates/journal/journal.html:17
+#: rhodecode/templates/journal/public_journal.html:4
+msgid "Journal"
+msgstr "Diário"
+
+#: rhodecode/templates/base/base.html:66
+msgid "Login"
+msgstr "Entrar"
+
+#: rhodecode/templates/base/base.html:68
+msgid "Log Out"
+msgstr "Sair"
+
+#: rhodecode/templates/base/base.html:107
+msgid "Submit a bug"
+msgstr "Encaminhe um bug"
+
+#: rhodecode/templates/base/base.html:141
+msgid "Switch repository"
+msgstr "Trocar repositório"
+
+#: rhodecode/templates/base/base.html:143
+msgid "Products"
+msgstr "Produtos"
+
+#: rhodecode/templates/base/base.html:149
+msgid "loading..."
+msgstr "carregando..."
+
+#: rhodecode/templates/base/base.html:234
+#: rhodecode/templates/base/base.html:236
+#: rhodecode/templates/base/base.html:238
+msgid "Switch to"
+msgstr "Trocar para"
+
+#: rhodecode/templates/base/base.html:242
+#: rhodecode/templates/branches/branches.html:13
+msgid "branches"
+msgstr "ramos"
+
+#: rhodecode/templates/base/base.html:249
+#: rhodecode/templates/branches/branches_data.html:52
+msgid "There are no branches yet"
+msgstr "Ainda não há ramos"
+
+#: rhodecode/templates/base/base.html:254
+#: rhodecode/templates/shortlog/shortlog_data.html:10
+#: rhodecode/templates/tags/tags.html:14
+msgid "tags"
+msgstr "etiquetas"
+
+#: rhodecode/templates/base/base.html:261
+#: rhodecode/templates/tags/tags_data.html:32
+msgid "There are no tags yet"
+msgstr "Ainda não há etiquetas"
+
+#: rhodecode/templates/base/base.html:277
+#: rhodecode/templates/base/base.html:281
+#: rhodecode/templates/files/files_annotate.html:40
+#: rhodecode/templates/files/files_source.html:11
+msgid "Options"
+msgstr "Opções"
+
+#: rhodecode/templates/base/base.html:286
+#: rhodecode/templates/base/base.html:288
+#: rhodecode/templates/base/base.html:306
+msgid "settings"
+msgstr "configurações"
+
+#: rhodecode/templates/base/base.html:292
+msgid "search"
+msgstr "pesquisar"
+
+#: rhodecode/templates/base/base.html:299
+msgid "journal"
+msgstr "diário"
+
+#: rhodecode/templates/base/base.html:301
+msgid "repositories groups"
+msgstr "grupos de repositórios"
+
+#: rhodecode/templates/base/base.html:302
+msgid "users"
+msgstr "usuários"
+
+#: rhodecode/templates/base/base.html:303
+msgid "users groups"
+msgstr "grupos de usuários"
+
+#: rhodecode/templates/base/base.html:304
+msgid "permissions"
+msgstr "permissões"
+
+#: rhodecode/templates/base/base.html:317
+#: rhodecode/templates/base/base.html:319
+#: rhodecode/templates/followers/followers.html:5
+msgid "Followers"
+msgstr "Seguidores"
+
+#: rhodecode/templates/base/base.html:325
+#: rhodecode/templates/base/base.html:327
+#: rhodecode/templates/forks/forks.html:5
+msgid "Forks"
+msgstr "Bifurcações"
+
+#: rhodecode/templates/base/base.html:356
+#: rhodecode/templates/base/base.html:358
+#: rhodecode/templates/base/base.html:360
+#: rhodecode/templates/search/search.html:4
+#: rhodecode/templates/search/search.html:24
+#: rhodecode/templates/search/search.html:46
+msgid "Search"
+msgstr "Pesquisar"
+
+#: rhodecode/templates/base/root.html:57
+#: rhodecode/templates/journal/journal.html:48
+#: rhodecode/templates/summary/summary.html:36
+msgid "Stop following this repository"
+msgstr "Parar de seguir este repositório"
+
+#: rhodecode/templates/base/root.html:66
+#: rhodecode/templates/summary/summary.html:40
+msgid "Start following this repository"
+msgstr "Passar a seguir este repositório"
+
+#: rhodecode/templates/branches/branches_data.html:4
+#: rhodecode/templates/tags/tags_data.html:4
+msgid "date"
+msgstr "data"
+
+#: rhodecode/templates/branches/branches_data.html:6
+#: rhodecode/templates/shortlog/shortlog_data.html:7
+#: rhodecode/templates/tags/tags_data.html:6
+msgid "author"
+msgstr "autor"
+
+#: rhodecode/templates/branches/branches_data.html:8
+#: rhodecode/templates/shortlog/shortlog_data.html:11
+#: rhodecode/templates/tags/tags_data.html:8
+msgid "links"
+msgstr "inks"
+
+#: rhodecode/templates/branches/branches_data.html:23
+#: rhodecode/templates/branches/branches_data.html:43
+#: rhodecode/templates/shortlog/shortlog_data.html:39
+#: rhodecode/templates/tags/tags_data.html:24
+msgid "changeset"
+msgstr "conjunto de mudanças"
+
+#: rhodecode/templates/branches/branches_data.html:25
+#: rhodecode/templates/branches/branches_data.html:45
+#: rhodecode/templates/files/files.html:12
+#: rhodecode/templates/shortlog/shortlog_data.html:41
+#: rhodecode/templates/summary/summary.html:233
+#: rhodecode/templates/tags/tags_data.html:26
+msgid "files"
+msgstr "arquivos"
+
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "showing "
+msgstr "mostrando "
+
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "out of"
+msgstr "de"
+
+#: rhodecode/templates/changelog/changelog.html:37
+msgid "Show"
+msgstr "Mostrar"
+
+#: rhodecode/templates/changelog/changelog.html:50
+#: rhodecode/templates/changeset/changeset.html:42
+#: rhodecode/templates/summary/summary.html:609
+msgid "commit"
+msgstr "commit"
+
+#: rhodecode/templates/changelog/changelog.html:63
+msgid "Affected number of files, click to show more details"
+msgstr "Número de arquivos afetados, clique para mostrar mais detalhes"
+
+#: rhodecode/templates/changelog/changelog.html:67
+#: rhodecode/templates/changeset/changeset.html:66
+msgid "merge"
+msgstr "mesclar"
+
+#: rhodecode/templates/changelog/changelog.html:72
+#: rhodecode/templates/changeset/changeset.html:72
+msgid "Parent"
+msgstr "Progenitor"
+
+#: rhodecode/templates/changelog/changelog.html:77
+#: rhodecode/templates/changeset/changeset.html:77
+msgid "No parents"
+msgstr "Sem progenitores"
+
+#: rhodecode/templates/changelog/changelog.html:82
+#: rhodecode/templates/changeset/changeset.html:80
+#: rhodecode/templates/files/files.html:29
+#: rhodecode/templates/files/files_annotate.html:25
+#: rhodecode/templates/files/files_edit.html:33
+#: rhodecode/templates/shortlog/shortlog_data.html:9
+msgid "branch"
+msgstr "ramo"
+
+#: rhodecode/templates/changelog/changelog.html:86
+#: rhodecode/templates/changeset/changeset.html:83
+msgid "tag"
+msgstr "etiqueta"
+
+#: rhodecode/templates/changelog/changelog.html:122
+msgid "Show selected changes __S -> __E"
+msgstr "Mostrar alterações selecionadas __S -> __E"
+
+#: rhodecode/templates/changelog/changelog.html:172
+#: rhodecode/templates/shortlog/shortlog_data.html:61
+msgid "There are no changes yet"
+msgstr "Ainda não há alteações"
+
+#: rhodecode/templates/changelog/changelog_details.html:2
+#: rhodecode/templates/changeset/changeset.html:55
+msgid "removed"
+msgstr "removidos"
+
+#: rhodecode/templates/changelog/changelog_details.html:3
+#: rhodecode/templates/changeset/changeset.html:56
+msgid "changed"
+msgstr "alterados"
+
+#: rhodecode/templates/changelog/changelog_details.html:4
+#: rhodecode/templates/changeset/changeset.html:57
+msgid "added"
+msgstr "adicionados"
+
+#: rhodecode/templates/changelog/changelog_details.html:6
+#: rhodecode/templates/changelog/changelog_details.html:7
+#: rhodecode/templates/changelog/changelog_details.html:8
+#: rhodecode/templates/changeset/changeset.html:59
+#: rhodecode/templates/changeset/changeset.html:60
+#: rhodecode/templates/changeset/changeset.html:61
+#, python-format
+msgid "affected %s files"
+msgstr "%s arquivos afetados"
+
+#: rhodecode/templates/changeset/changeset.html:6
+#: rhodecode/templates/changeset/changeset.html:14
+#: rhodecode/templates/changeset/changeset.html:31
+msgid "Changeset"
+msgstr "Conjunto de Mudanças"
+
+#: rhodecode/templates/changeset/changeset.html:32
+#: rhodecode/templates/changeset/changeset.html:121
+#: rhodecode/templates/changeset/changeset_range.html:78
+#: rhodecode/templates/files/file_diff.html:32
+#: rhodecode/templates/files/file_diff.html:42
+msgid "raw diff"
+msgstr "diff bruto"
+
+#: rhodecode/templates/changeset/changeset.html:34
+#: rhodecode/templates/changeset/changeset.html:123
+#: rhodecode/templates/changeset/changeset_range.html:80
+#: rhodecode/templates/files/file_diff.html:34
+msgid "download diff"
+msgstr "descarregar diff"
+
+#: rhodecode/templates/changeset/changeset.html:90
+#, python-format
+msgid "%s files affected with %s additions and %s deletions."
+msgstr "%s arquivos afetados com %s adições e %s exclusões"
+
+#: rhodecode/templates/changeset/changeset.html:101
+msgid "Changeset was too big and was cut off..."
+msgstr "Conjunto de mudanças era grande demais e foi cortado..."
+
+#: rhodecode/templates/changeset/changeset.html:119
+#: rhodecode/templates/changeset/changeset_range.html:76
+#: rhodecode/templates/files/file_diff.html:30
+msgid "diff"
+msgstr "diff"
+
+#: rhodecode/templates/changeset/changeset.html:132
+#: rhodecode/templates/changeset/changeset_range.html:89
+msgid "No changes in this file"
+msgstr "Nenhuma alteração nesse arquivo"
+
+#: rhodecode/templates/changeset/changeset_range.html:30
+msgid "Compare View"
+msgstr "Exibir Comparação"
+
+#: rhodecode/templates/changeset/changeset_range.html:52
+msgid "Files affected"
+msgstr "Arquivos afetados"
+
+#: rhodecode/templates/errors/error_document.html:44
+#, python-format
+msgid "You will be redirected to %s in %s seconds"
+msgstr "Você será redirecionado para %s em %s segundos"
+
+#: rhodecode/templates/files/file_diff.html:4
+#: rhodecode/templates/files/file_diff.html:12
+msgid "File diff"
+msgstr "Diff do arquivo"
+
+#: rhodecode/templates/files/file_diff.html:42
+msgid "Diff is to big to display"
+msgstr "Diff é grande demais para exibir"
+
+#: rhodecode/templates/files/files.html:37
+#: rhodecode/templates/files/files_annotate.html:31
+#: rhodecode/templates/files/files_edit.html:39
+msgid "Location"
+msgstr "Local"
+
+#: rhodecode/templates/files/files.html:46
+msgid "Go back"
+msgstr "Voltar"
+
+#: rhodecode/templates/files/files.html:47
+msgid "No files at given path"
+msgstr "Nenhum arquivo no caminho especificado"
+
+#: rhodecode/templates/files/files_annotate.html:4
+msgid "File annotate"
+msgstr "Anotar arquivo"
+
+#: rhodecode/templates/files/files_annotate.html:12
+msgid "annotate"
+msgstr "anotar"
+
+#: rhodecode/templates/files/files_annotate.html:33
+#: rhodecode/templates/files/files_browser.html:160
+#: rhodecode/templates/files/files_source.html:2
+msgid "Revision"
+msgstr "Revisão"
+
+#: rhodecode/templates/files/files_annotate.html:36
+#: rhodecode/templates/files/files_browser.html:158
+#: rhodecode/templates/files/files_source.html:7
+msgid "Size"
+msgstr "Tamanho"
+
+#: rhodecode/templates/files/files_annotate.html:38
+#: rhodecode/templates/files/files_browser.html:159
+#: rhodecode/templates/files/files_source.html:9
+msgid "Mimetype"
+msgstr "Mimetype"
+
+#: rhodecode/templates/files/files_annotate.html:41
+msgid "show source"
+msgstr "mostrar fonte"
+
+#: rhodecode/templates/files/files_annotate.html:43
+#: rhodecode/templates/files/files_annotate.html:78
+#: rhodecode/templates/files/files_source.html:14
+#: rhodecode/templates/files/files_source.html:51
+msgid "show as raw"
+msgstr "mostrar como bruto"
+
+#: rhodecode/templates/files/files_annotate.html:45
+#: rhodecode/templates/files/files_source.html:16
+msgid "download as raw"
+msgstr "descarregar como bruto"
+
+#: rhodecode/templates/files/files_annotate.html:54
+#: rhodecode/templates/files/files_source.html:25
+msgid "History"
+msgstr "Histórico"
+
+#: rhodecode/templates/files/files_annotate.html:73
+#: rhodecode/templates/files/files_source.html:46
+#, python-format
+msgid "Binary file (%s)"
+msgstr "Arquivo binário (%s)"
+
+#: rhodecode/templates/files/files_annotate.html:78
+#: rhodecode/templates/files/files_source.html:51
+msgid "File is too big to display"
+msgstr "Arquivo é grande demais para exibir"
+
+#: rhodecode/templates/files/files_browser.html:13
+msgid "view"
+msgstr "ver"
+
+#: rhodecode/templates/files/files_browser.html:14
+msgid "previous revision"
+msgstr "revisão anterior"
+
+#: rhodecode/templates/files/files_browser.html:16
+msgid "next revision"
+msgstr "próxima revisão"
+
+#: rhodecode/templates/files/files_browser.html:23
+msgid "follow current branch"
+msgstr "seguir ramo atual"
+
+#: rhodecode/templates/files/files_browser.html:27
+msgid "search file list"
+msgstr "pesquisar lista de arquivos"
+
+#: rhodecode/templates/files/files_browser.html:32
+msgid "Loading file list..."
+msgstr "Carregando lista de arquivos..."
+
+#: rhodecode/templates/files/files_browser.html:111
+msgid "search truncated"
+msgstr "pesquisa truncada"
+
+#: rhodecode/templates/files/files_browser.html:122
+msgid "no matching files"
+msgstr "nenhum arquivo corresponde"
+
+#: rhodecode/templates/files/files_browser.html:161
+msgid "Last modified"
+msgstr "Última alteração"
+
+#: rhodecode/templates/files/files_browser.html:162
+msgid "Last commiter"
+msgstr "Último commiter"
+
+#: rhodecode/templates/files/files_edit.html:4
+msgid "Edit file"
+msgstr "Editar arquivo"
+
+#: rhodecode/templates/files/files_edit.html:19
+msgid "edit file"
+msgstr "editar arquivo"
+
+#: rhodecode/templates/files/files_edit.html:45
+#: rhodecode/templates/shortlog/shortlog_data.html:5
+msgid "commit message"
+msgstr "mensagem de commit"
+
+#: rhodecode/templates/files/files_edit.html:51
+msgid "Commit changes"
+msgstr "Realizar commit das alterações"
+
+#: rhodecode/templates/files/files_source.html:12
+msgid "show annotation"
+msgstr "mostrar anotação"
+
+#: rhodecode/templates/files/files_source.html:153
+msgid "Selection link"
+msgstr "Link da seleção"
+
+#: rhodecode/templates/followers/followers.html:13
+msgid "followers"
+msgstr "seguidores"
+
+#: rhodecode/templates/followers/followers_data.html:12
+msgid "Started following"
+msgstr "Passou a seguir"
+
+#: rhodecode/templates/forks/forks.html:13
+msgid "forks"
+msgstr "bifurcações"
+
+#: rhodecode/templates/forks/forks_data.html:17
+msgid "forked"
+msgstr "bifurcado"
+
+#: rhodecode/templates/forks/forks_data.html:34
+msgid "There are no forks yet"
+msgstr "Ainda não há bifurcações"
+
+#: rhodecode/templates/journal/journal.html:34
+msgid "Following"
+msgstr "Seguindo"
+
+#: rhodecode/templates/journal/journal.html:41
+msgid "following user"
+msgstr "seguindo usuário"
+
+#: rhodecode/templates/journal/journal.html:41
+msgid "user"
+msgstr "usuário"
+
+#: rhodecode/templates/journal/journal.html:65
+msgid "You are not following any users or repositories"
+msgstr "Você não está seguindo quaisquer usuários ou repositórios"
+
+#: rhodecode/templates/journal/journal_data.html:46
+msgid "No entries yet"
+msgstr "Ainda não há entradas"
+
+#: rhodecode/templates/journal/public_journal.html:17
+msgid "Public Journal"
+msgstr "Diário Público"
+
+#: rhodecode/templates/search/search.html:7
+#: rhodecode/templates/search/search.html:26
+msgid "in repository: "
+msgstr "no repositório"
+
+#: rhodecode/templates/search/search.html:9
+#: rhodecode/templates/search/search.html:28
+msgid "in all repositories"
+msgstr "em todos os repositórios"
+
+#: rhodecode/templates/search/search.html:42
+msgid "Search term"
+msgstr "Termo de pesquisa"
+
+#: rhodecode/templates/search/search.html:54
+msgid "Search in"
+msgstr "Pesquisando em"
+
+#: rhodecode/templates/search/search.html:57
+msgid "File contents"
+msgstr "Conteúdo dos arquivos"
+
+#: rhodecode/templates/search/search.html:59
+msgid "File names"
+msgstr "Nomes dos arquivos"
+
+#: rhodecode/templates/search/search_content.html:20
+#: rhodecode/templates/search/search_path.html:15
+msgid "Permission denied"
+msgstr "Permissão negada"
+
+#: rhodecode/templates/settings/repo_fork.html:5
+msgid "Fork"
+msgstr "Bifurcação"
+
+#: rhodecode/templates/settings/repo_fork.html:31
+msgid "Fork name"
+msgstr "Nome da bifurcação"
+
+#: rhodecode/templates/settings/repo_fork.html:55
+msgid "fork this repository"
+msgstr "bifurcar este repositório"
+
+#: rhodecode/templates/shortlog/shortlog.html:5
+#: rhodecode/templates/summary/summary.html:666
+msgid "Shortlog"
+msgstr "Log resumido"
+
+#: rhodecode/templates/shortlog/shortlog.html:14
+msgid "shortlog"
+msgstr "log resumido"
+
+#: rhodecode/templates/shortlog/shortlog_data.html:6
+msgid "age"
+msgstr "idade"
+
+#: rhodecode/templates/summary/summary.html:12
+msgid "summary"
+msgstr "sumário"
+
+#: rhodecode/templates/summary/summary.html:79
+msgid "remote clone"
+msgstr "clone remoto"
+
+#: rhodecode/templates/summary/summary.html:121
+msgid "by"
+msgstr "por"
+
+#: rhodecode/templates/summary/summary.html:128
+msgid "Clone url"
+msgstr "URL de clonagem"
+
+#: rhodecode/templates/summary/summary.html:137
+msgid "Trending source files"
+msgstr "Tendências nos arquivos fonte"
+
+#: rhodecode/templates/summary/summary.html:146
+msgid "Download"
+msgstr "Download"
+
+#: rhodecode/templates/summary/summary.html:150
+msgid "There are no downloads yet"
+msgstr "Ainda não há downloads"
+
+#: rhodecode/templates/summary/summary.html:152
+msgid "Downloads are disabled for this repository"
+msgstr "Downloads estão desabilitados para este repositório"
+
+#: rhodecode/templates/summary/summary.html:154
+#: rhodecode/templates/summary/summary.html:320
+msgid "enable"
+msgstr "habilitar"
+
+#: rhodecode/templates/summary/summary.html:162
+#: rhodecode/templates/summary/summary.html:297
+#, python-format
+msgid "Download %s as %s"
+msgstr "Descarregar %s como %s"
+
+#: rhodecode/templates/summary/summary.html:168
+msgid "Check this to download archive with subrepos"
+msgstr "Marque isto para descarregar arquivo com subrepositórios"
+
+#: rhodecode/templates/summary/summary.html:168
+msgid "with subrepos"
+msgstr "com subrepositórios"
+
+#: rhodecode/templates/summary/summary.html:176
+msgid "Feeds"
+msgstr "Feeds"
+
+#: rhodecode/templates/summary/summary.html:257
+#: rhodecode/templates/summary/summary.html:684
+#: rhodecode/templates/summary/summary.html:695
+msgid "show more"
+msgstr "mostrar mais"
+
+#: rhodecode/templates/summary/summary.html:312
+msgid "Commit activity by day / author"
+msgstr "Atividade de commit por dia / autor"
+
+#: rhodecode/templates/summary/summary.html:324
+msgid "Loaded in"
+msgstr "Carregado em"
+
+#: rhodecode/templates/summary/summary.html:603
+msgid "commits"
+msgstr "commits"
+
+#: rhodecode/templates/summary/summary.html:604
+msgid "files added"
+msgstr "arquivos adicionados"
+
+#: rhodecode/templates/summary/summary.html:605
+msgid "files changed"
+msgstr "arquivos alterados"
+
+#: rhodecode/templates/summary/summary.html:606
+msgid "files removed"
+msgstr "arquivos removidos"
+
+#: rhodecode/templates/summary/summary.html:610
+msgid "file added"
+msgstr "arquivo adicionado"
+
+#: rhodecode/templates/summary/summary.html:611
+msgid "file changed"
+msgstr "arquivo alterado"
+
+#: rhodecode/templates/summary/summary.html:612
+msgid "file removed"
+msgstr "arquivo removido"
+
--- a/rhodecode/i18n/rhodecode.pot	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/i18n/rhodecode.pot	Fri Oct 07 01:08:50 2011 +0200
@@ -6,273 +6,477 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: RhodeCode 1.1.5\n"
+"Project-Id-Version: RhodeCode 1.2.0\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-03-17 02:38+0100\n"
+"POT-Creation-Date: 2011-09-14 15:50-0300\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.5\n"
-
-#: rhodecode/controllers/changeset.py:87 rhodecode/controllers/changeset.py:113
-#: rhodecode/controllers/changeset.py:159 rhodecode/controllers/changeset.py:171
+"Generated-By: Babel 0.9.6\n"
+
+#: rhodecode/controllers/changeset.py:108 rhodecode/controllers/changeset.py:149
+#: rhodecode/controllers/changeset.py:216 rhodecode/controllers/changeset.py:229
 msgid "binary file"
 msgstr ""
 
-#: rhodecode/controllers/changeset.py:95 rhodecode/controllers/changeset.py:122
+#: rhodecode/controllers/changeset.py:123 rhodecode/controllers/changeset.py:168
 msgid "Changeset is to big and was cut off, see raw changeset instead"
 msgstr ""
 
-#: rhodecode/controllers/error.py:70
+#: rhodecode/controllers/changeset.py:159
+msgid "Diff is to big and was cut off, see raw diff instead"
+msgstr ""
+
+#: rhodecode/controllers/error.py:69
 msgid "Home page"
 msgstr ""
 
-#: rhodecode/controllers/error.py:100
+#: rhodecode/controllers/error.py:98
 msgid "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: rhodecode/controllers/error.py:102
+#: rhodecode/controllers/error.py:101
 msgid "Unauthorized access to resource"
 msgstr ""
 
-#: rhodecode/controllers/error.py:104
+#: rhodecode/controllers/error.py:103
 msgid "You don't have permission to view this page"
 msgstr ""
 
-#: rhodecode/controllers/error.py:106
+#: rhodecode/controllers/error.py:105
 msgid "The resource could not be found"
 msgstr ""
 
-#: rhodecode/controllers/error.py:108
+#: rhodecode/controllers/error.py:107
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
 msgstr ""
 
-#: rhodecode/controllers/files.py:71
+#: rhodecode/controllers/feed.py:48
+#, python-format
+msgid "Changes on %s repository"
+msgstr ""
+
+#: rhodecode/controllers/feed.py:49
+#, python-format
+msgid "%s %s feed"
+msgstr ""
+
+#: rhodecode/controllers/files.py:72
 msgid "There are no files yet"
 msgstr ""
 
-#: rhodecode/controllers/files.py:222 rhodecode/controllers/files.py:228
-msgid "binary file changed"
-msgstr ""
-
-#: rhodecode/controllers/files.py:233 rhodecode/controllers/files.py:241
-msgid "Diff is to big to display"
-msgstr ""
-
-#: rhodecode/controllers/files.py:235 rhodecode/controllers/files.py:243
+#: rhodecode/controllers/files.py:262
+#, python-format
+msgid "Edited %s via RhodeCode"
+msgstr ""
+
+#: rhodecode/controllers/files.py:267 rhodecode/templates/files/file_diff.html:40
+msgid "No changes"
+msgstr ""
+
+#: rhodecode/controllers/files.py:278
+#, python-format
+msgid "Successfully committed to %s"
+msgstr ""
+
+#: rhodecode/controllers/files.py:283
+msgid "Error occurred during commit"
+msgstr ""
+
+#: rhodecode/controllers/files.py:308
+msgid "downloads disabled"
+msgstr ""
+
+#: rhodecode/controllers/files.py:313
+#, python-format
+msgid "Unknown revision %s"
+msgstr ""
+
+#: rhodecode/controllers/files.py:315
+msgid "Empty repository"
+msgstr ""
+
+#: rhodecode/controllers/files.py:317
+msgid "Unknown archive type"
+msgstr ""
+
+#: rhodecode/controllers/files.py:385 rhodecode/controllers/files.py:398
 msgid "Binary file"
 msgstr ""
 
-#: rhodecode/controllers/files.py:258
+#: rhodecode/controllers/files.py:417
+#: rhodecode/templates/changeset/changeset_range.html:4
+#: rhodecode/templates/changeset/changeset_range.html:12
+#: rhodecode/templates/changeset/changeset_range.html:29
 msgid "Changesets"
 msgstr ""
 
-#: rhodecode/controllers/files.py:259 rhodecode/templates/branches/branches.html:5
-#: rhodecode/templates/summary/summary.html:633
+#: rhodecode/controllers/files.py:418 rhodecode/controllers/summary.py:175
+#: rhodecode/templates/branches/branches.html:5
+#: rhodecode/templates/summary/summary.html:690
 msgid "Branches"
 msgstr ""
 
-#: rhodecode/controllers/files.py:260 rhodecode/templates/summary/summary.html:622
+#: rhodecode/controllers/files.py:419 rhodecode/controllers/summary.py:176
+#: rhodecode/templates/summary/summary.html:679
 #: rhodecode/templates/tags/tags.html:5
 msgid "Tags"
 msgstr ""
 
-#: rhodecode/controllers/login.py:112
+#: rhodecode/controllers/journal.py:50
+#, python-format
+msgid "%s public journal %s feed"
+msgstr ""
+
+#: rhodecode/controllers/journal.py:178 rhodecode/controllers/journal.py:212
+#: rhodecode/templates/admin/repos/repo_edit.html:171
+#: rhodecode/templates/base/base.html:50
+msgid "Public journal"
+msgstr ""
+
+#: rhodecode/controllers/login.py:111
 msgid "You have successfully registered into rhodecode"
 msgstr ""
 
-#: rhodecode/controllers/login.py:134
-msgid "Your new password was sent"
-msgstr ""
-
-#: rhodecode/controllers/search.py:111
+#: rhodecode/controllers/login.py:133
+msgid "Your password reset link was sent"
+msgstr ""
+
+#: rhodecode/controllers/login.py:155
+msgid "Your password reset was successful, new password has been sent to your email"
+msgstr ""
+
+#: rhodecode/controllers/search.py:109
 msgid "Invalid search query. Try quoting it."
 msgstr ""
 
-#: rhodecode/controllers/search.py:116
+#: rhodecode/controllers/search.py:114
 msgid "There is no index to search in. Please run whoosh indexer"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:59 rhodecode/controllers/settings.py:152
+#: rhodecode/controllers/search.py:118
+msgid "An error occurred during this search operation"
+msgstr ""
+
+#: rhodecode/controllers/settings.py:61 rhodecode/controllers/settings.py:171
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from the "
 "file system please run the application again in order to rescan repositories"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:90 rhodecode/controllers/admin/repos.py:142
+#: rhodecode/controllers/settings.py:109 rhodecode/controllers/admin/repos.py:239
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:107 rhodecode/controllers/admin/repos.py:175
+#: rhodecode/controllers/settings.py:126 rhodecode/controllers/admin/repos.py:257
 #, python-format
 msgid "error occurred during update of repository %s"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:126 rhodecode/controllers/admin/repos.py:193
+#: rhodecode/controllers/settings.py:144 rhodecode/controllers/admin/repos.py:275
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was moved or renamed  from the "
 "filesystem please run the application again in order to rescan repositories"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:138 rhodecode/controllers/admin/repos.py:205
+#: rhodecode/controllers/settings.py:156 rhodecode/controllers/admin/repos.py:287
 #, python-format
 msgid "deleted repository %s"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:140 rhodecode/controllers/admin/repos.py:209
+#: rhodecode/controllers/settings.py:159 rhodecode/controllers/admin/repos.py:297
+#: rhodecode/controllers/admin/repos.py:303
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: rhodecode/controllers/settings.py:174
+#: rhodecode/controllers/settings.py:193
 #, python-format
 msgid "forked %s repository as %s"
 msgstr ""
 
-#: rhodecode/controllers/summary.py:114
+#: rhodecode/controllers/settings.py:211
+#, python-format
+msgid "An error occurred during repository forking %s"
+msgstr ""
+
+#: rhodecode/controllers/summary.py:123
 msgid "No data loaded yet"
 msgstr ""
 
-#: rhodecode/controllers/summary.py:117
-msgid "Statistics update are disabled for this repository"
-msgstr ""
-
-#: rhodecode/controllers/admin/ldap_settings.py:84
+#: rhodecode/controllers/summary.py:126
+msgid "Statistics are disabled for this repository"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:49
+msgid "BASE"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:50
+msgid "ONELEVEL"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:51
+msgid "SUBTREE"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:55
+msgid "NEVER"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:56
+msgid "ALLOW"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:57
+msgid "TRY"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:58
+msgid "DEMAND"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:59
+msgid "HARD"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:63
+msgid "No encryption"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:64
+msgid "LDAPS connection"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:65
+msgid "START_TLS on LDAP connection"
+msgstr ""
+
+#: rhodecode/controllers/admin/ldap_settings.py:115
 msgid "Ldap settings updated successfully"
 msgstr ""
 
-#: rhodecode/controllers/admin/ldap_settings.py:89
+#: rhodecode/controllers/admin/ldap_settings.py:120
 msgid "Unable to activate ldap. The \"python-ldap\" library is missing."
 msgstr ""
 
-#: rhodecode/controllers/admin/ldap_settings.py:102
+#: rhodecode/controllers/admin/ldap_settings.py:134
 msgid "error occurred during update of ldap settings"
 msgstr ""
 
+#: rhodecode/controllers/admin/permissions.py:56
+msgid "None"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:57
+msgid "Read"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:58
+msgid "Write"
+msgstr ""
+
 #: rhodecode/controllers/admin/permissions.py:59
-msgid "None"
-msgstr ""
-
-#: rhodecode/controllers/admin/permissions.py:60
-msgid "Read"
-msgstr ""
-
-#: rhodecode/controllers/admin/permissions.py:61
-msgid "Write"
-msgstr ""
-
-#: rhodecode/controllers/admin/permissions.py:62
 #: rhodecode/templates/admin/ldap/ldap.html:9
 #: rhodecode/templates/admin/permissions/permissions.html:9
 #: rhodecode/templates/admin/repos/repo_add.html:9
 #: rhodecode/templates/admin/repos/repo_edit.html:9
 #: rhodecode/templates/admin/repos/repos.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:8
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:8
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
+#: rhodecode/templates/admin/settings/hooks.html:9
 #: rhodecode/templates/admin/settings/settings.html:9
 #: rhodecode/templates/admin/users/user_add.html:8
 #: rhodecode/templates/admin/users/user_edit.html:9
-#: rhodecode/templates/admin/users/user_edit.html:97
+#: rhodecode/templates/admin/users/user_edit.html:110
 #: rhodecode/templates/admin/users/users.html:9
-#: rhodecode/templates/base/base.html:209 rhodecode/templates/base/base.html:297
-#: rhodecode/templates/base/base.html:299 rhodecode/templates/base/base.html:301
+#: rhodecode/templates/admin/users_groups/users_group_add.html:8
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:9
+#: rhodecode/templates/admin/users_groups/users_groups.html:9
+#: rhodecode/templates/base/base.html:279 rhodecode/templates/base/base.html:366
+#: rhodecode/templates/base/base.html:368 rhodecode/templates/base/base.html:370
 msgid "Admin"
 msgstr ""
 
-#: rhodecode/controllers/admin/permissions.py:65
+#: rhodecode/controllers/admin/permissions.py:62
 msgid "disabled"
 msgstr ""
 
-#: rhodecode/controllers/admin/permissions.py:67
+#: rhodecode/controllers/admin/permissions.py:64
 msgid "allowed with manual account activation"
 msgstr ""
 
+#: rhodecode/controllers/admin/permissions.py:66
+msgid "allowed with automatic account activation"
+msgstr ""
+
+#: rhodecode/controllers/admin/permissions.py:68
+msgid "Disabled"
+msgstr ""
+
 #: rhodecode/controllers/admin/permissions.py:69
-msgid "allowed with automatic account activation"
-msgstr ""
-
-#: rhodecode/controllers/admin/permissions.py:71
-msgid "Disabled"
-msgstr ""
-
-#: rhodecode/controllers/admin/permissions.py:72
 msgid "Enabled"
 msgstr ""
 
-#: rhodecode/controllers/admin/permissions.py:106
+#: rhodecode/controllers/admin/permissions.py:102
 msgid "Default permissions updated successfully"
 msgstr ""
 
-#: rhodecode/controllers/admin/permissions.py:123
+#: rhodecode/controllers/admin/permissions.py:119
 msgid "error occurred during update of permissions"
 msgstr ""
 
-#: rhodecode/controllers/admin/repos.py:83
-#, python-format
-msgid "created repository %s"
-msgstr ""
-
-#: rhodecode/controllers/admin/repos.py:110
-#, python-format
-msgid "error occurred during creation of repository %s"
-msgstr ""
-
-#: rhodecode/controllers/admin/repos.py:225
-msgid "An error occurred during deletion of repository user"
-msgstr ""
-
-#: rhodecode/controllers/admin/repos.py:240
-msgid "An error occurred during deletion of repository stats"
-msgstr ""
-
-#: rhodecode/controllers/admin/repos.py:254
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: rhodecode/controllers/admin/repos.py:272
+#: rhodecode/controllers/admin/repos.py:96
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from the "
 "filesystem please run the application again in order to rescan repositories"
 msgstr ""
 
-#: rhodecode/controllers/admin/settings.py:112
-msgid "Repositories successfully rescanned"
-msgstr ""
-
-#: rhodecode/controllers/admin/settings.py:119
+#: rhodecode/controllers/admin/repos.py:172
+#, python-format
+msgid "created repository %s from %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:176
+#, python-format
+msgid "created repository %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:205
+#, python-format
+msgid "error occurred during creation of repository %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:292
+#, python-format
+msgid "Cannot delete %s it still contains attached forks"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:320
+msgid "An error occurred during deletion of repository user"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:335
+msgid "An error occurred during deletion of repository users groups"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:352
+msgid "An error occurred during deletion of repository stats"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:367
+msgid "An error occurred during cache invalidation"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:387
+msgid "Updated repository visibility in public journal"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:390
+msgid "An error occurred during setting this repository in public journal"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:395 rhodecode/model/forms.py:53
+msgid "Token mismatch"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:408
+msgid "Pulled from remote location"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos.py:410
+msgid "An error occurred during pull from remote location"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:83
+#, python-format
+msgid "created repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:96
+#, python-format
+msgid "error occurred during creation of repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:130
+#, python-format
+msgid "updated repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:143
+#, python-format
+msgid "error occurred during update of repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:164
+#, python-format
+msgid "This group contains %s repositores and cannot be deleted"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:171
+#, python-format
+msgid "removed repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/repos_groups.py:175
+#, python-format
+msgid "error occurred during deletion of repos group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:109
+#, python-format
+msgid "Repositories successfully rescanned added: %s,removed: %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:118
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: rhodecode/controllers/admin/settings.py:138
-msgid "Updated application settings"
-msgstr ""
-
 #: rhodecode/controllers/admin/settings.py:143
-#: rhodecode/controllers/admin/settings.py:204
+msgid "Updated application settings"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:148
+#: rhodecode/controllers/admin/settings.py:215
 msgid "error occurred during updating application settings"
 msgstr ""
 
-#: rhodecode/controllers/admin/settings.py:199
+#: rhodecode/controllers/admin/settings.py:210
 msgid "Updated mercurial settings"
 msgstr ""
 
-#: rhodecode/controllers/admin/settings.py:258
+#: rhodecode/controllers/admin/settings.py:236
+msgid "Added new hook"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:247
+msgid "Updated hooks"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:251
+msgid "error occurred during hook creation"
+msgstr ""
+
+#: rhodecode/controllers/admin/settings.py:310
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: rhodecode/controllers/admin/settings.py:286
+#: rhodecode/controllers/admin/settings.py:339
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: rhodecode/controllers/admin/settings.py:306
-#: rhodecode/controllers/admin/users.py:127
+#: rhodecode/controllers/admin/settings.py:359
+#: rhodecode/controllers/admin/users.py:130
 #, python-format
 msgid "error occurred during update of user %s"
 msgstr ""
@@ -288,442 +492,600 @@
 msgstr ""
 
 #: rhodecode/controllers/admin/users.py:116
-msgid "User updated succesfully"
-msgstr ""
-
-#: rhodecode/controllers/admin/users.py:143
-msgid "sucessfully deleted user"
-msgstr ""
-
-#: rhodecode/controllers/admin/users.py:147
+msgid "User updated successfully"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:146
+msgid "successfully deleted user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:150
 msgid "An error occurred during deletion of user"
 msgstr ""
 
-#: rhodecode/controllers/admin/users.py:163
+#: rhodecode/controllers/admin/users.py:166
 msgid "You can't edit this user"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:383
+#: rhodecode/controllers/admin/users.py:195
+#: rhodecode/controllers/admin/users_groups.py:202
+msgid "Granted 'repository create' permission to user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users.py:204
+#: rhodecode/controllers/admin/users_groups.py:211
+msgid "Revoked 'repository create' permission to user"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:74
+#, python-format
+msgid "created users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:86
+#, python-format
+msgid "error occurred during creation of users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:119
+#, python-format
+msgid "updated users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:138
+#, python-format
+msgid "error occurred during update of users group %s"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:154
+msgid "successfully deleted users group"
+msgstr ""
+
+#: rhodecode/controllers/admin/users_groups.py:158
+msgid "An error occurred during deletion of users group"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:279
+msgid "year"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:280
+msgid "month"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:281
+msgid "day"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:282
+msgid "hour"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:283
+msgid "minute"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:284
+msgid "second"
+msgstr ""
+
+#: rhodecode/lib/__init__.py:293
 msgid "ago"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:386
+#: rhodecode/lib/__init__.py:296
 msgid "just now"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:404
+#: rhodecode/lib/auth.py:377
+msgid "You need to be a registered user to perform this action"
+msgstr ""
+
+#: rhodecode/lib/auth.py:421
+msgid "You need to be a signed in to view this page"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:307
 msgid "True"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:407
+#: rhodecode/lib/helpers.py:311
 msgid "False"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:439
+#: rhodecode/lib/helpers.py:352
+#, python-format
+msgid "Show all combined changesets %s->%s"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:356
+msgid "compare view"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:365
 msgid "and"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:439
+#: rhodecode/lib/helpers.py:365
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:441 rhodecode/templates/changelog/changelog.html:14
-#: rhodecode/templates/changelog/changelog.html:40
+#: rhodecode/lib/helpers.py:367 rhodecode/templates/changelog/changelog.html:14
+#: rhodecode/templates/changelog/changelog.html:39
 msgid "revisions"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:456
+#: rhodecode/lib/helpers.py:385
+msgid "fork name "
+msgstr ""
+
+#: rhodecode/lib/helpers.py:388
 msgid "[deleted] repository"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:457 rhodecode/lib/helpers.py:461
+#: rhodecode/lib/helpers.py:389 rhodecode/lib/helpers.py:393
 msgid "[created] repository"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:458
-msgid "[forked] repository as"
-msgstr ""
-
-#: rhodecode/lib/helpers.py:459 rhodecode/lib/helpers.py:463
+#: rhodecode/lib/helpers.py:390 rhodecode/lib/helpers.py:394
+msgid "[forked] repository"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:391 rhodecode/lib/helpers.py:395
 msgid "[updated] repository"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:460
+#: rhodecode/lib/helpers.py:392
 msgid "[delete] repository"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:462
-msgid "[forked] repository"
-msgstr ""
-
-#: rhodecode/lib/helpers.py:464
-msgid "[pushed] "
-msgstr ""
-
-#: rhodecode/lib/helpers.py:465
-msgid "[pulled] "
-msgstr ""
-
-#: rhodecode/lib/helpers.py:466
+#: rhodecode/lib/helpers.py:396
+msgid "[pushed] into"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:397
+msgid "[committed via RhodeCode] into"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:398
+msgid "[pulled from remote] into"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:399
+msgid "[pulled] from"
+msgstr ""
+
+#: rhodecode/lib/helpers.py:400
 msgid "[started following] repository"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:467
+#: rhodecode/lib/helpers.py:401
 msgid "[stopped following] repository"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:554 rhodecode/templates/changelog/changelog.html:68
+#: rhodecode/lib/helpers.py:577
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: rhodecode/lib/helpers.py:557 rhodecode/templates/changelog/changelog.html:71
+#: rhodecode/lib/helpers.py:581
 msgid "No Files"
 msgstr ""
 
-#: rhodecode/model/forms.py:54
-msgid "Token mismatch"
-msgstr ""
-
-#: rhodecode/model/forms.py:67
+#: rhodecode/model/forms.py:66
 msgid "Invalid username"
 msgstr ""
 
-#: rhodecode/model/forms.py:76
+#: rhodecode/model/forms.py:75
 msgid "This username already exists"
 msgstr ""
 
-#: rhodecode/model/forms.py:81
+#: rhodecode/model/forms.py:79
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: rhodecode/model/forms.py:101 rhodecode/model/forms.py:109
-#: rhodecode/model/forms.py:117
+#: rhodecode/model/forms.py:94
+msgid "Invalid group name"
+msgstr ""
+
+#: rhodecode/model/forms.py:104
+msgid "This users group already exists"
+msgstr ""
+
+#: rhodecode/model/forms.py:110
+msgid ""
+"Group name may only contain alphanumeric characters underscores, periods or "
+"dashes and must begin with alphanumeric character"
+msgstr ""
+
+#: rhodecode/model/forms.py:132
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: rhodecode/model/forms.py:148
+msgid "This group already exists"
+msgstr ""
+
+#: rhodecode/model/forms.py:164 rhodecode/model/forms.py:172
+#: rhodecode/model/forms.py:180
 msgid "Invalid characters in password"
 msgstr ""
 
-#: rhodecode/model/forms.py:128
-msgid "Password do not match"
-msgstr ""
-
-#: rhodecode/model/forms.py:133
+#: rhodecode/model/forms.py:191
+msgid "Passwords do not match"
+msgstr ""
+
+#: rhodecode/model/forms.py:196
 msgid "invalid password"
 msgstr ""
 
-#: rhodecode/model/forms.py:134
+#: rhodecode/model/forms.py:197
 msgid "invalid user name"
 msgstr ""
 
-#: rhodecode/model/forms.py:135
+#: rhodecode/model/forms.py:198
 msgid "Your account is disabled"
 msgstr ""
 
-#: rhodecode/model/forms.py:172 rhodecode/model/forms.py:207
+#: rhodecode/model/forms.py:233
 msgid "This username is not valid"
 msgstr ""
 
-#: rhodecode/model/forms.py:185
+#: rhodecode/model/forms.py:245
 msgid "This repository name is disallowed"
 msgstr ""
 
-#: rhodecode/model/forms.py:189
+#: rhodecode/model/forms.py:266
+#, python-format
+msgid "This repository already exists in group \"%s\""
+msgstr ""
+
+#: rhodecode/model/forms.py:274
 msgid "This repository already exists"
 msgstr ""
 
-#: rhodecode/model/forms.py:201
-msgid "Fork have to be the same type as original"
-msgstr ""
-
-#: rhodecode/model/forms.py:256
-msgid "This is not a valid path"
-msgstr ""
-
-#: rhodecode/model/forms.py:270
-msgid "This e-mail address is already taken"
-msgstr ""
-
-#: rhodecode/model/forms.py:286
-msgid "This e-mail address doesn't exist."
-msgstr ""
-
-#: rhodecode/model/forms.py:311
-#, python-format
-msgid ""
-"You need to specify %(user)s in template for example uid=%(user)s "
-",dc=company..."
-msgstr ""
-
-#: rhodecode/model/forms.py:317
-#, python-format
-msgid "Wrong template used, only %(user)s is an valid entry"
+#: rhodecode/model/forms.py:312 rhodecode/model/forms.py:319
+msgid "invalid clone url"
+msgstr ""
+
+#: rhodecode/model/forms.py:322
+msgid "Invalid clone url, provide a valid clone http\\s url"
 msgstr ""
 
 #: rhodecode/model/forms.py:334
+msgid "Fork have to be the same type as original"
+msgstr ""
+
+#: rhodecode/model/forms.py:341
+msgid "This username or users group name is not valid"
+msgstr ""
+
+#: rhodecode/model/forms.py:403
+msgid "This is not a valid path"
+msgstr ""
+
+#: rhodecode/model/forms.py:416
+msgid "This e-mail address is already taken"
+msgstr ""
+
+#: rhodecode/model/forms.py:427
+msgid "This e-mail address doesn't exist."
+msgstr ""
+
+#: rhodecode/model/forms.py:447
+msgid ""
+"The LDAP Login attribute of the CN must be specified - this is the name of "
+"the attribute that is equivalent to 'username'"
+msgstr ""
+
+#: rhodecode/model/forms.py:466
 msgid "Please enter a login"
 msgstr ""
 
-#: rhodecode/model/forms.py:335
+#: rhodecode/model/forms.py:467
 #, python-format
 msgid "Enter a value %(min)i characters long or more"
 msgstr ""
 
-#: rhodecode/model/forms.py:343
+#: rhodecode/model/forms.py:475
 msgid "Please enter a password"
 msgstr ""
 
-#: rhodecode/model/forms.py:344
+#: rhodecode/model/forms.py:476
 #, python-format
 msgid "Enter %(min)i characters or more"
 msgstr ""
 
-#: rhodecode/model/user.py:126
+#: rhodecode/model/user.py:145
 msgid "[RhodeCode] New User registration"
 msgstr ""
 
-#: rhodecode/model/user.py:138 rhodecode/model/user.py:159
+#: rhodecode/model/user.py:157 rhodecode/model/user.py:179
 msgid "You can't Edit this user since it's crucial for entire application"
 msgstr ""
 
-#: rhodecode/model/user.py:180
+#: rhodecode/model/user.py:201
 msgid "You can't remove this user since it's crucial for entire application"
 msgstr ""
 
-#: rhodecode/model/user.py:183
+#: rhodecode/model/user.py:204
 #, python-format
 msgid ""
 "This user still owns %s repositories and cannot be removed. Switch owners or "
 "remove those repositories"
 msgstr ""
 
-#: rhodecode/templates/index.html:4 rhodecode/templates/index.html:30
+#: rhodecode/templates/index.html:4
 msgid "Dashboard"
 msgstr ""
 
-#: rhodecode/templates/index.html:31
-#: rhodecode/templates/admin/users/user_edit_my_account.html:101
+#: rhodecode/templates/index_base.html:22
+#: rhodecode/templates/admin/users/user_edit_my_account.html:102
 msgid "quick filter..."
 msgstr ""
 
-#: rhodecode/templates/index.html:37
+#: rhodecode/templates/index_base.html:23 rhodecode/templates/base/base.html:300
+msgid "repositories"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:29
+#: rhodecode/templates/admin/repos/repos.html:22
 msgid "ADD NEW REPOSITORY"
 msgstr ""
 
-#: rhodecode/templates/index.html:48
-#: rhodecode/templates/admin/repos/repo_add.html:31
-#: rhodecode/templates/admin/repos/repo_add_create_repository.html:27
+#: rhodecode/templates/index_base.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:32
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:32
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:33
+#: rhodecode/templates/admin/users_groups/users_group_add.html:32
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:33
+msgid "Group name"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:42 rhodecode/templates/index_base.html:73
+#: rhodecode/templates/admin/repos/repo_add_base.html:44
+#: rhodecode/templates/admin/repos/repo_edit.html:64
+#: rhodecode/templates/admin/repos/repos.html:31
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:41
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:34
+#: rhodecode/templates/settings/repo_fork.html:40
+#: rhodecode/templates/settings/repo_settings.html:40
+#: rhodecode/templates/summary/summary.html:92
+msgid "Description"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:53
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46
+msgid "Repositories group"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:72
+#: rhodecode/templates/admin/repos/repo_add_base.html:9
 #: rhodecode/templates/admin/repos/repo_edit.html:32
 #: rhodecode/templates/admin/repos/repos.html:30
-#: rhodecode/templates/admin/users/user_edit_my_account.html:116
-#: rhodecode/templates/files/files_browser.html:27
-#: rhodecode/templates/settings/repo_settings.html:29
+#: rhodecode/templates/admin/users/user_edit_my_account.html:117
+#: rhodecode/templates/files/files_browser.html:157
+#: rhodecode/templates/settings/repo_settings.html:31
 #: rhodecode/templates/summary/summary.html:31
-#: rhodecode/templates/summary/summary.html:92
+#: rhodecode/templates/summary/summary.html:107
 msgid "Name"
 msgstr ""
 
-#: rhodecode/templates/index.html:49
-#: rhodecode/templates/admin/repos/repo_add.html:47
-#: rhodecode/templates/admin/repos/repo_add_create_repository.html:44
-#: rhodecode/templates/admin/repos/repo_edit.html:48
-#: rhodecode/templates/admin/repos/repos.html:31
-#: rhodecode/templates/settings/repo_fork.html:38
-#: rhodecode/templates/settings/repo_settings.html:38
-#: rhodecode/templates/summary/summary.html:75
-msgid "Description"
-msgstr ""
-
-#: rhodecode/templates/index.html:50 rhodecode/templates/admin/repos/repos.html:32
-#: rhodecode/templates/summary/summary.html:99
+#: rhodecode/templates/index_base.html:74
+#: rhodecode/templates/admin/repos/repos.html:32
+#: rhodecode/templates/summary/summary.html:114
 msgid "Last change"
 msgstr ""
 
-#: rhodecode/templates/index.html:51 rhodecode/templates/admin/repos/repos.html:33
+#: rhodecode/templates/index_base.html:75
+#: rhodecode/templates/admin/repos/repos.html:33
 msgid "Tip"
 msgstr ""
 
-#: rhodecode/templates/index.html:52
-#: rhodecode/templates/admin/repos/repo_edit.html:73
+#: rhodecode/templates/index_base.html:76
+#: rhodecode/templates/admin/repos/repo_edit.html:97
 msgid "Owner"
 msgstr ""
 
-#: rhodecode/templates/index.html:53 rhodecode/templates/summary/summary.html:236
+#: rhodecode/templates/index_base.html:77
+#: rhodecode/templates/journal/public_journal.html:20
+#: rhodecode/templates/summary/summary.html:180
+#: rhodecode/templates/summary/summary.html:183
 msgid "RSS"
 msgstr ""
 
-#: rhodecode/templates/index.html:54 rhodecode/templates/summary/summary.html:237
+#: rhodecode/templates/index_base.html:78
+#: rhodecode/templates/journal/public_journal.html:23
+#: rhodecode/templates/summary/summary.html:181
+#: rhodecode/templates/summary/summary.html:184
 msgid "Atom"
 msgstr ""
 
-#: rhodecode/templates/index.html:64 rhodecode/templates/admin/repos/repos.html:42
-#: rhodecode/templates/admin/users/user_edit_my_account.html:126
-#: rhodecode/templates/summary/summary.html:35
+#: rhodecode/templates/index_base.html:87 rhodecode/templates/index_base.html:89
+#: rhodecode/templates/index_base.html:91 rhodecode/templates/base/base.html:209
+#: rhodecode/templates/base/base.html:211 rhodecode/templates/base/base.html:213
+#: rhodecode/templates/summary/summary.html:4
+msgid "Summary"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:95 rhodecode/templates/index_base.html:97
+#: rhodecode/templates/index_base.html:99 rhodecode/templates/base/base.html:225
+#: rhodecode/templates/base/base.html:227 rhodecode/templates/base/base.html:229
+#: rhodecode/templates/changelog/changelog.html:6
+#: rhodecode/templates/changelog/changelog.html:14
+msgid "Changelog"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:103 rhodecode/templates/index_base.html:105
+#: rhodecode/templates/index_base.html:107 rhodecode/templates/base/base.html:268
+#: rhodecode/templates/base/base.html:270 rhodecode/templates/base/base.html:272
+#: rhodecode/templates/files/files.html:4
+msgid "Files"
+msgstr ""
+
+#: rhodecode/templates/index_base.html:116
+#: rhodecode/templates/admin/repos/repos.html:42
+#: rhodecode/templates/admin/users/user_edit_my_account.html:127
+#: rhodecode/templates/summary/summary.html:48
 msgid "Mercurial repository"
 msgstr ""
 
-#: rhodecode/templates/index.html:66 rhodecode/templates/admin/repos/repos.html:44
-#: rhodecode/templates/admin/users/user_edit_my_account.html:128
-#: rhodecode/templates/summary/summary.html:38
+#: rhodecode/templates/index_base.html:118
+#: rhodecode/templates/admin/repos/repos.html:44
+#: rhodecode/templates/admin/users/user_edit_my_account.html:129
+#: rhodecode/templates/summary/summary.html:51
 msgid "Git repository"
 msgstr ""
 
-#: rhodecode/templates/index.html:73 rhodecode/templates/journal.html:67
-#: rhodecode/templates/admin/repos/repo_edit.html:103
-#: rhodecode/templates/settings/repo_settings.html:74
-#: rhodecode/templates/summary/summary.html:42
+#: rhodecode/templates/index_base.html:123
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:16
+#: rhodecode/templates/journal/journal.html:53
+#: rhodecode/templates/summary/summary.html:56
 msgid "private repository"
 msgstr ""
 
-#: rhodecode/templates/index.html:75 rhodecode/templates/journal.html:69
-#: rhodecode/templates/summary/summary.html:44
+#: rhodecode/templates/index_base.html:125
+#: rhodecode/templates/journal/journal.html:55
+#: rhodecode/templates/summary/summary.html:58
 msgid "public repository"
 msgstr ""
 
-#: rhodecode/templates/index.html:83 rhodecode/templates/base/base.html:221
-#: rhodecode/templates/settings/repo_fork.html:11
+#: rhodecode/templates/index_base.html:133 rhodecode/templates/base/base.html:291
+#: rhodecode/templates/settings/repo_fork.html:13
 msgid "fork"
 msgstr ""
 
-#: rhodecode/templates/index.html:84 rhodecode/templates/admin/repos/repos.html:60
-#: rhodecode/templates/admin/users/user_edit_my_account.html:142
-#: rhodecode/templates/summary/summary.html:63
-#: rhodecode/templates/summary/summary.html:65
+#: rhodecode/templates/index_base.html:134
+#: rhodecode/templates/admin/repos/repos.html:60
+#: rhodecode/templates/admin/users/user_edit_my_account.html:143
+#: rhodecode/templates/summary/summary.html:69
+#: rhodecode/templates/summary/summary.html:71
 msgid "Fork of"
 msgstr ""
 
-#: rhodecode/templates/index.html:105 rhodecode/templates/admin/repos/repos.html:73
+#: rhodecode/templates/index_base.html:155
+#: rhodecode/templates/admin/repos/repos.html:73
 msgid "No changesets yet"
 msgstr ""
 
-#: rhodecode/templates/index.html:110
+#: rhodecode/templates/index_base.html:161 rhodecode/templates/index_base.html:163
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: rhodecode/templates/index.html:113
+#: rhodecode/templates/index_base.html:168 rhodecode/templates/index_base.html:170
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: rhodecode/templates/journal.html:4 rhodecode/templates/journal.html:17
-#: rhodecode/templates/base/base.html:41 rhodecode/templates/base/base.html:278
-#: rhodecode/templates/base/base.html:280 rhodecode/templates/base/base.html:282
-msgid "Journal"
-msgstr ""
-
-#: rhodecode/templates/journal.html:45
-msgid "No entries yet"
-msgstr ""
-
-#: rhodecode/templates/journal.html:53
-msgid "Following"
-msgstr ""
-
-#: rhodecode/templates/journal.html:60
-msgid "following user"
-msgstr ""
-
-#: rhodecode/templates/journal.html:60
-#: rhodecode/templates/admin/repos/repo_edit.html:94
-#: rhodecode/templates/settings/repo_settings.html:65
-msgid "user"
-msgstr ""
-
-#: rhodecode/templates/journal.html:79
-msgid "You are not following any users or repositories"
-msgstr ""
-
-#: rhodecode/templates/login.html:5
+#: rhodecode/templates/login.html:5 rhodecode/templates/login.html:54
+#: rhodecode/templates/base/base.html:38
 msgid "Sign In"
 msgstr ""
 
-#: rhodecode/templates/login.html:28
+#: rhodecode/templates/login.html:21
 msgid "Sign In to"
 msgstr ""
 
-#: rhodecode/templates/login.html:38 rhodecode/templates/register.html:27
+#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20
 #: rhodecode/templates/admin/admin_log.html:5
 #: rhodecode/templates/admin/users/user_add.html:32
-#: rhodecode/templates/admin/users/user_edit.html:43
-#: rhodecode/templates/admin/users/user_edit_my_account.html:41
-#: rhodecode/templates/summary/summary.html:91
+#: rhodecode/templates/admin/users/user_edit.html:47
+#: rhodecode/templates/admin/users/user_edit_my_account.html:45
+#: rhodecode/templates/base/base.html:15
+#: rhodecode/templates/summary/summary.html:106
 msgid "Username"
 msgstr ""
 
-#: rhodecode/templates/login.html:47 rhodecode/templates/register.html:36
-#: rhodecode/templates/admin/ldap/ldap.html:50
+#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29
+#: rhodecode/templates/admin/ldap/ldap.html:46
 #: rhodecode/templates/admin/users/user_add.html:41
+#: rhodecode/templates/base/base.html:24
 msgid "Password"
 msgstr ""
 
-#: rhodecode/templates/login.html:67
+#: rhodecode/templates/login.html:60
 msgid "Forgot your password ?"
 msgstr ""
 
-#: rhodecode/templates/login.html:70
+#: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:35
 msgid "Don't have an account ?"
 msgstr ""
 
 #: rhodecode/templates/password_reset.html:5
-msgid "Reset You password"
-msgstr ""
-
-#: rhodecode/templates/password_reset.html:18
-msgid "Reset You password to"
-msgstr ""
-
-#: rhodecode/templates/password_reset.html:28
+msgid "Reset your password"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:11
+msgid "Reset your password to"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:21
 msgid "Email address"
 msgstr ""
 
-#: rhodecode/templates/password_reset.html:38
-msgid "Your new password will be send to matching email address"
-msgstr ""
-
-#: rhodecode/templates/register.html:5
+#: rhodecode/templates/password_reset.html:30
+msgid "Reset my password"
+msgstr ""
+
+#: rhodecode/templates/password_reset.html:31
+msgid "Password reset link will be send to matching email address"
+msgstr ""
+
+#: rhodecode/templates/register.html:5 rhodecode/templates/register.html:74
 msgid "Sign Up"
 msgstr ""
 
-#: rhodecode/templates/register.html:18
+#: rhodecode/templates/register.html:11
 msgid "Sign Up to"
 msgstr ""
 
-#: rhodecode/templates/register.html:45
+#: rhodecode/templates/register.html:38
 msgid "Re-enter password"
 msgstr ""
 
-#: rhodecode/templates/register.html:54
+#: rhodecode/templates/register.html:47
 #: rhodecode/templates/admin/users/user_add.html:50
-#: rhodecode/templates/admin/users/user_edit.html:61
-#: rhodecode/templates/admin/users/user_edit_my_account.html:59
+#: rhodecode/templates/admin/users/user_edit.html:74
+#: rhodecode/templates/admin/users/user_edit_my_account.html:63
 msgid "First Name"
 msgstr ""
 
-#: rhodecode/templates/register.html:63
+#: rhodecode/templates/register.html:56
 #: rhodecode/templates/admin/users/user_add.html:59
-#: rhodecode/templates/admin/users/user_edit.html:70
-#: rhodecode/templates/admin/users/user_edit_my_account.html:68
+#: rhodecode/templates/admin/users/user_edit.html:83
+#: rhodecode/templates/admin/users/user_edit_my_account.html:72
 msgid "Last Name"
 msgstr ""
 
-#: rhodecode/templates/register.html:72
+#: rhodecode/templates/register.html:65
 #: rhodecode/templates/admin/users/user_add.html:68
-#: rhodecode/templates/admin/users/user_edit.html:79
-#: rhodecode/templates/admin/users/user_edit_my_account.html:77
-#: rhodecode/templates/summary/summary.html:93
+#: rhodecode/templates/admin/users/user_edit.html:92
+#: rhodecode/templates/admin/users/user_edit_my_account.html:81
+#: rhodecode/templates/summary/summary.html:108
 msgid "Email"
 msgstr ""
 
-#: rhodecode/templates/register.html:83
+#: rhodecode/templates/register.html:76
 msgid "Your account will be activated right after registration"
 msgstr ""
 
-#: rhodecode/templates/register.html:85
+#: rhodecode/templates/register.html:78
 msgid "Your account must wait for activation by administrator"
 msgstr ""
 
+#: rhodecode/templates/repo_switcher_list.html:14
+msgid "Private repository"
+msgstr ""
+
+#: rhodecode/templates/repo_switcher_list.html:19
+msgid "Public repository"
+msgstr ""
+
 #: rhodecode/templates/admin/admin.html:5 rhodecode/templates/admin/admin.html:9
 msgid "Admin journal"
 msgstr ""
@@ -744,12 +1106,11 @@
 msgid "From IP"
 msgstr ""
 
-#: rhodecode/templates/admin/admin_log.html:62
+#: rhodecode/templates/admin/admin_log.html:52
 msgid "No actions yet"
 msgstr ""
 
 #: rhodecode/templates/admin/ldap/ldap.html:5
-#: rhodecode/templates/admin/ldap/ldap.html:24
 msgid "LDAP administration"
 msgstr ""
 
@@ -757,8 +1118,12 @@
 msgid "Ldap"
 msgstr ""
 
+#: rhodecode/templates/admin/ldap/ldap.html:28
+msgid "Connection settings"
+msgstr ""
+
 #: rhodecode/templates/admin/ldap/ldap.html:30
-msgid "Enable ldap"
+msgid "Enable LDAP"
 msgstr ""
 
 #: rhodecode/templates/admin/ldap/ldap.html:34
@@ -770,24 +1135,71 @@
 msgstr ""
 
 #: rhodecode/templates/admin/ldap/ldap.html:42
-msgid "Enable LDAPS"
-msgstr ""
-
-#: rhodecode/templates/admin/ldap/ldap.html:46
 msgid "Account"
 msgstr ""
 
+#: rhodecode/templates/admin/ldap/ldap.html:50
+msgid "Connection security"
+msgstr ""
+
 #: rhodecode/templates/admin/ldap/ldap.html:54
+msgid "Certificate Checks"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:57
+msgid "Search settings"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:59
 msgid "Base DN"
 msgstr ""
 
+#: rhodecode/templates/admin/ldap/ldap.html:63
+msgid "LDAP Filter"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:67
+msgid "LDAP Search Scope"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:70
+msgid "Attribute mappings"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:72
+msgid "Login Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:76
+msgid "First Name Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:80
+msgid "Last Name Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:84
+msgid "E-mail Attribute"
+msgstr ""
+
+#: rhodecode/templates/admin/ldap/ldap.html:89
+#: rhodecode/templates/admin/settings/hooks.html:73
+#: rhodecode/templates/admin/users/user_edit.html:117
+#: rhodecode/templates/admin/users/user_edit.html:142
+#: rhodecode/templates/admin/users/user_edit_my_account.html:89
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:263
+msgid "Save"
+msgstr ""
+
 #: rhodecode/templates/admin/permissions/permissions.html:5
 msgid "Permissions administration"
 msgstr ""
 
 #: rhodecode/templates/admin/permissions/permissions.html:11
-#: rhodecode/templates/admin/repos/repo_edit.html:85
-#: rhodecode/templates/settings/repo_settings.html:56
+#: rhodecode/templates/admin/repos/repo_edit.html:109
+#: rhodecode/templates/admin/users/user_edit.html:127
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:248
+#: rhodecode/templates/settings/repo_settings.html:58
 msgid "Permissions"
 msgstr ""
 
@@ -822,6 +1234,10 @@
 msgid "Repository creation"
 msgstr ""
 
+#: rhodecode/templates/admin/permissions/permissions.html:71
+msgid "set"
+msgstr ""
+
 #: rhodecode/templates/admin/repos/repo_add.html:5
 #: rhodecode/templates/admin/repos/repo_add_create_repository.html:5
 msgid "Add repository"
@@ -830,6 +1246,7 @@
 #: rhodecode/templates/admin/repos/repo_add.html:11
 #: rhodecode/templates/admin/repos/repo_edit.html:11
 #: rhodecode/templates/admin/repos/repos.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
 msgid "Repositories"
 msgstr ""
 
@@ -837,20 +1254,34 @@
 msgid "add new"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_add.html:39
-#: rhodecode/templates/admin/repos/repo_add_create_repository.html:36
-#: rhodecode/templates/admin/repos/repo_edit.html:40
+#: rhodecode/templates/admin/repos/repo_add_base.html:20
+#: rhodecode/templates/summary/summary.html:80
+#: rhodecode/templates/summary/summary.html:82
+msgid "Clone from"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:28
+#: rhodecode/templates/admin/repos/repo_edit.html:48
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:4
+msgid "Repository group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_add_base.html:36
+#: rhodecode/templates/admin/repos/repo_edit.html:56
 msgid "Type"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_add.html:55
-#: rhodecode/templates/admin/repos/repo_add_create_repository.html:52
-#: rhodecode/templates/admin/repos/repo_edit.html:57
-#: rhodecode/templates/settings/repo_fork.html:46
-#: rhodecode/templates/settings/repo_settings.html:47
+#: rhodecode/templates/admin/repos/repo_add_base.html:52
+#: rhodecode/templates/admin/repos/repo_edit.html:73
+#: rhodecode/templates/settings/repo_fork.html:48
+#: rhodecode/templates/settings/repo_settings.html:49
 msgid "Private"
 msgstr ""
 
+#: rhodecode/templates/admin/repos/repo_add_base.html:59
+msgid "add"
+msgstr ""
+
 #: rhodecode/templates/admin/repos/repo_add_create_repository.html:9
 msgid "add new repository"
 msgstr ""
@@ -861,121 +1292,268 @@
 
 #: rhodecode/templates/admin/repos/repo_edit.html:13
 #: rhodecode/templates/admin/users/user_edit.html:13
-#: rhodecode/templates/admin/users/user_edit_my_account.html:147
+#: rhodecode/templates/admin/users/user_edit_my_account.html:148
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:13
+#: rhodecode/templates/files/files_annotate.html:49
+#: rhodecode/templates/files/files_source.html:20
 msgid "edit"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_edit.html:65
+#: rhodecode/templates/admin/repos/repo_edit.html:40
+msgid "Clone uri"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:81
 msgid "Enable statistics"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_edit.html:90
-#: rhodecode/templates/settings/repo_settings.html:61
-msgid "none"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:91
-#: rhodecode/templates/settings/repo_settings.html:62
-msgid "read"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:92
-#: rhodecode/templates/settings/repo_settings.html:63
-msgid "write"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:93
-#: rhodecode/templates/admin/users/users.html:37
-#: rhodecode/templates/base/base.html:226
-#: rhodecode/templates/settings/repo_settings.html:64
-msgid "admin"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:124
-#: rhodecode/templates/settings/repo_settings.html:95
-msgid "Failed to remove user"
+#: rhodecode/templates/admin/repos/repo_edit.html:89
+msgid "Enable downloads"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:127
+msgid "Administration"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:130
+msgid "Statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:134
+msgid "Reset current statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:134
+msgid "Confirm to remove current statistics"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:137
+msgid "Fetched to rev"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:138
+msgid "Percentage of stats gathered"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:147
+msgid "Remote"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:151
+msgid "Pull changes from remote location"
 msgstr ""
 
 #: rhodecode/templates/admin/repos/repo_edit.html:151
-#: rhodecode/templates/settings/repo_settings.html:123
-msgid "Add another user"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:293
-msgid "Administration"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:296
-msgid "Statistics"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:301
-msgid "Reset current statistics"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:305
-msgid "Fetched to rev"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:306
-msgid "Percentage of stats gathered"
-msgstr ""
-
-#: rhodecode/templates/admin/repos/repo_edit.html:314
+msgid "Confirm to pull changes from remote side"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:162
 msgid "Cache"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_edit.html:318
+#: rhodecode/templates/admin/repos/repo_edit.html:166
 msgid "Invalidate repository cache"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_edit.html:324
+#: rhodecode/templates/admin/repos/repo_edit.html:166
+msgid "Confirm to invalidate repository cache"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:177
+msgid "Remove from public journal"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:179
+msgid "Add to public journal"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit.html:185
 msgid "Delete"
 msgstr ""
 
-#: rhodecode/templates/admin/repos/repo_edit.html:328
+#: rhodecode/templates/admin/repos/repo_edit.html:189
 msgid "Remove this repository"
 msgstr ""
 
+#: rhodecode/templates/admin/repos/repo_edit.html:189
+#: rhodecode/templates/admin/repos/repos.html:79
+msgid "Confirm to delete this repository"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:3
+msgid "none"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:4
+msgid "read"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:5
+msgid "write"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:6
+#: rhodecode/templates/admin/users/users.html:38
+#: rhodecode/templates/base/base.html:296
+msgid "admin"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:7
+msgid "member"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:33
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:53
+msgid "revoke"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:75
+msgid "Add another member"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:89
+msgid "Failed to remove user"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:104
+msgid "Failed to remove users group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:205
+msgid "Group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos/repo_edit_perms.html:206
+#: rhodecode/templates/admin/users_groups/users_groups.html:33
+msgid "members"
+msgstr ""
+
 #: rhodecode/templates/admin/repos/repos.html:5
 msgid "Repositories administration"
 msgstr ""
 
 #: rhodecode/templates/admin/repos/repos.html:34
-#: rhodecode/templates/summary/summary.html:85
+#: rhodecode/templates/summary/summary.html:100
 msgid "Contact"
 msgstr ""
 
 #: rhodecode/templates/admin/repos/repos.html:35
-#: rhodecode/templates/admin/users/user_edit_my_account.html:118
-#: rhodecode/templates/admin/users/users.html:39
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:36
+#: rhodecode/templates/admin/users/user_edit_my_account.html:119
+#: rhodecode/templates/admin/users/users.html:40
+#: rhodecode/templates/admin/users_groups/users_groups.html:35
 msgid "action"
 msgstr ""
 
 #: rhodecode/templates/admin/repos/repos.html:51
-#: rhodecode/templates/admin/users/user_edit_my_account.html:133
-#: rhodecode/templates/admin/users/user_edit_my_account.html:147
+#: rhodecode/templates/admin/users/user_edit_my_account.html:134
+#: rhodecode/templates/admin/users/user_edit_my_account.html:148
 msgid "private"
 msgstr ""
 
 #: rhodecode/templates/admin/repos/repos.html:53
 #: rhodecode/templates/admin/repos/repos.html:59
-#: rhodecode/templates/admin/users/user_edit_my_account.html:135
-#: rhodecode/templates/admin/users/user_edit_my_account.html:141
-#: rhodecode/templates/summary/summary.html:62
+#: rhodecode/templates/admin/users/user_edit_my_account.html:136
+#: rhodecode/templates/admin/users/user_edit_my_account.html:142
+#: rhodecode/templates/summary/summary.html:68
 msgid "public"
 msgstr ""
 
+#: rhodecode/templates/admin/repos/repos.html:79
+#: rhodecode/templates/admin/users/users.html:55
+msgid "delete"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:8
+msgid "Groups"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups.html:13
+msgid "with"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:5
+msgid "Add repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:10
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:10
+msgid "Repos groups"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:12
+msgid "add new repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:50
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:50
+msgid "Group parent"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_add.html:58
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:58
+#: rhodecode/templates/admin/users/user_add.html:85
+#: rhodecode/templates/admin/users_groups/users_group_add.html:49
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:90
+msgid "save"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:5
+msgid "Edit repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:12
+msgid "edit repos group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5
+msgid "Repositories groups administration"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:22
+msgid "ADD NEW GROUP"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:35
+msgid "Number of repositories"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:54
+msgid "Confirm to delete this group"
+msgstr ""
+
+#: rhodecode/templates/admin/repos_groups/repos_groups_show.html:62
+msgid "There are no repositories groups yet"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:5
 #: rhodecode/templates/admin/settings/settings.html:5
 msgid "Settings administration"
 msgstr ""
 
+#: rhodecode/templates/admin/settings/hooks.html:9
 #: rhodecode/templates/admin/settings/settings.html:9
 #: rhodecode/templates/settings/repo_settings.html:5
-#: rhodecode/templates/settings/repo_settings.html:11
+#: rhodecode/templates/settings/repo_settings.html:13
 msgid "Settings"
 msgstr ""
 
+#: rhodecode/templates/admin/settings/hooks.html:24
+msgid "Built in hooks - read only"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:40
+msgid "Custom hooks"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:56
+msgid "remove"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/hooks.html:88
+msgid "Failed to remove hook"
+msgstr ""
+
 #: rhodecode/templates/admin/settings/settings.html:24
 msgid "Remap and rescan repositories"
 msgstr ""
@@ -995,6 +1573,10 @@
 msgid "destroy old data"
 msgstr ""
 
+#: rhodecode/templates/admin/settings/settings.html:45
+msgid "Rescan repositories"
+msgstr ""
+
 #: rhodecode/templates/admin/settings/settings.html:51
 msgid "Whoosh indexing"
 msgstr ""
@@ -1007,6 +1589,10 @@
 msgid "build from scratch"
 msgstr ""
 
+#: rhodecode/templates/admin/settings/settings.html:70
+msgid "Reindex"
+msgstr ""
+
 #: rhodecode/templates/admin/settings/settings.html:76
 msgid "Global application settings"
 msgstr ""
@@ -1019,50 +1605,73 @@
 msgid "Realm text"
 msgstr ""
 
-#: rhodecode/templates/admin/settings/settings.html:109
-msgid "Mercurial settings"
+#: rhodecode/templates/admin/settings/settings.html:103
+msgid "GA code"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:111
+#: rhodecode/templates/admin/settings/settings.html:177
+msgid "Save settings"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:112
+#: rhodecode/templates/admin/settings/settings.html:178
+#: rhodecode/templates/admin/users/user_edit.html:118
+#: rhodecode/templates/admin/users/user_edit.html:143
+#: rhodecode/templates/admin/users/user_edit_my_account.html:90
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:264
+#: rhodecode/templates/files/files_edit.html:50
+msgid "Reset"
 msgstr ""
 
 #: rhodecode/templates/admin/settings/settings.html:118
+msgid "Mercurial settings"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:127
 msgid "Web"
 msgstr ""
 
-#: rhodecode/templates/admin/settings/settings.html:123
+#: rhodecode/templates/admin/settings/settings.html:132
 msgid "require ssl for pushing"
 msgstr ""
 
-#: rhodecode/templates/admin/settings/settings.html:130
-msgid "Hooks"
-msgstr ""
-
-#: rhodecode/templates/admin/settings/settings.html:135
-msgid "Update repository after push (hg update)"
-msgstr ""
-
 #: rhodecode/templates/admin/settings/settings.html:139
-msgid "Show repository size after push"
-msgstr ""
-
-#: rhodecode/templates/admin/settings/settings.html:143
-msgid "Log user push commands"
+msgid "Hooks"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:142
+msgid "advanced setup"
 msgstr ""
 
 #: rhodecode/templates/admin/settings/settings.html:147
-msgid "Log user pull commands"
-msgstr ""
-
-#: rhodecode/templates/admin/settings/settings.html:154
-msgid "Repositories location"
+msgid "Update repository after push (hg update)"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:151
+msgid "Show repository size after push"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:155
+msgid "Log user push commands"
 msgstr ""
 
 #: rhodecode/templates/admin/settings/settings.html:159
+msgid "Log user pull commands"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:166
+msgid "Repositories location"
+msgstr ""
+
+#: rhodecode/templates/admin/settings/settings.html:171
 msgid ""
-"This a crucial application setting. If You really sure you need to change "
-"this, you must restart application in order to make this settings take "
+"This a crucial application setting. If you are really sure you need to change"
+" this, you must restart application in order to make this setting take "
 "effect. Click this label to unlock."
 msgstr ""
 
-#: rhodecode/templates/admin/settings/settings.html:160
+#: rhodecode/templates/admin/settings/settings.html:172
 msgid "unlock"
 msgstr ""
 
@@ -1081,7 +1690,9 @@
 msgstr ""
 
 #: rhodecode/templates/admin/users/user_add.html:77
-#: rhodecode/templates/admin/users/user_edit.html:88
+#: rhodecode/templates/admin/users/user_edit.html:101
+#: rhodecode/templates/admin/users_groups/users_group_add.html:41
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:42
 msgid "Active"
 msgstr ""
 
@@ -1089,16 +1700,35 @@
 msgid "Edit user"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit.html:36
+#: rhodecode/templates/admin/users/user_edit.html:33
+#: rhodecode/templates/admin/users/user_edit_my_account.html:32
+msgid "Change your avatar at"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:34
 #: rhodecode/templates/admin/users/user_edit_my_account.html:33
 msgid "Using"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit.html:52
-#: rhodecode/templates/admin/users/user_edit_my_account.html:50
+#: rhodecode/templates/admin/users/user_edit.html:40
+#: rhodecode/templates/admin/users/user_edit_my_account.html:39
+msgid "API key"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:56
+msgid "LDAP DN"
+msgstr ""
+
+#: rhodecode/templates/admin/users/user_edit.html:65
+#: rhodecode/templates/admin/users/user_edit_my_account.html:54
 msgid "New password"
 msgstr ""
 
+#: rhodecode/templates/admin/users/user_edit.html:135
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:256
+msgid "Create repositories"
+msgstr ""
+
 #: rhodecode/templates/admin/users/user_edit_my_account.html:5
 msgid "My account"
 msgstr ""
@@ -1107,26 +1737,26 @@
 msgid "My Account"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit_my_account.html:100
+#: rhodecode/templates/admin/users/user_edit_my_account.html:101
 msgid "My repositories"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit_my_account.html:106
+#: rhodecode/templates/admin/users/user_edit_my_account.html:107
 msgid "ADD REPOSITORY"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit_my_account.html:117
+#: rhodecode/templates/admin/users/user_edit_my_account.html:118
 #: rhodecode/templates/branches/branches_data.html:7
 #: rhodecode/templates/shortlog/shortlog_data.html:8
 #: rhodecode/templates/tags/tags_data.html:7
 msgid "revision"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit_my_account.html:156
+#: rhodecode/templates/admin/users/user_edit_my_account.html:157
 msgid "No repositories yet"
 msgstr ""
 
-#: rhodecode/templates/admin/users/user_edit_my_account.html:158
+#: rhodecode/templates/admin/users/user_edit_my_account.html:159
 msgid "create one now"
 msgstr ""
 
@@ -1134,6 +1764,10 @@
 msgid "Users administration"
 msgstr ""
 
+#: rhodecode/templates/admin/users/users.html:23
+msgid "ADD NEW USER"
+msgstr ""
+
 #: rhodecode/templates/admin/users/users.html:33
 msgid "username"
 msgstr ""
@@ -1149,140 +1783,203 @@
 msgstr ""
 
 #: rhodecode/templates/admin/users/users.html:36
+msgid "last login"
+msgstr ""
+
+#: rhodecode/templates/admin/users/users.html:37
+#: rhodecode/templates/admin/users_groups/users_groups.html:34
 msgid "active"
 msgstr ""
 
-#: rhodecode/templates/admin/users/users.html:38
-#: rhodecode/templates/base/base.html:233
+#: rhodecode/templates/admin/users/users.html:39
+#: rhodecode/templates/base/base.html:305
 msgid "ldap"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:37 rhodecode/templates/base/base.html:269
-#: rhodecode/templates/base/base.html:271 rhodecode/templates/base/base.html:273
+#: rhodecode/templates/admin/users/users.html:56
+msgid "Confirm to delete this user"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:5
+msgid "Add users group"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:10
+#: rhodecode/templates/admin/users_groups/users_groups.html:9
+msgid "Users groups"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_add.html:12
+msgid "add new users group"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:5
+msgid "Edit users group"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:11
+msgid "UsersGroups"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:50
+msgid "Members"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:58
+msgid "Choosen group members"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:61
+msgid "Remove all elements"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:75
+msgid "Available members"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_group_edit.html:79
+msgid "Add all elements"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:5
+msgid "Users groups administration"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:23
+msgid "ADD NEW USER GROUP"
+msgstr ""
+
+#: rhodecode/templates/admin/users_groups/users_groups.html:32
+msgid "group name"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:32
+msgid "Forgot password ?"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:57 rhodecode/templates/base/base.html:338
+#: rhodecode/templates/base/base.html:340 rhodecode/templates/base/base.html:342
 msgid "Home"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:87
+#: rhodecode/templates/base/base.html:61 rhodecode/templates/base/base.html:347
+#: rhodecode/templates/base/base.html:349 rhodecode/templates/base/base.html:351
+#: rhodecode/templates/journal/journal.html:4
+#: rhodecode/templates/journal/journal.html:17
+#: rhodecode/templates/journal/public_journal.html:4
+msgid "Journal"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:66
+msgid "Login"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:68
+msgid "Log Out"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:107
 msgid "Submit a bug"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:88
-msgid "GPL license"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:120
+#: rhodecode/templates/base/base.html:141
 msgid "Switch repository"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:122
+#: rhodecode/templates/base/base.html:143
 msgid "Products"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:130
-msgid "Private repository"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:132
-msgid "Public repository"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:139 rhodecode/templates/base/base.html:141
-#: rhodecode/templates/base/base.html:143
-#: rhodecode/templates/summary/summary.html:4
-msgid "Summary"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:155 rhodecode/templates/base/base.html:157
-#: rhodecode/templates/base/base.html:159
-#: rhodecode/templates/changelog/changelog.html:6
-#: rhodecode/templates/changelog/changelog.html:14
-msgid "Changelog"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:164 rhodecode/templates/base/base.html:166
-#: rhodecode/templates/base/base.html:168
+#: rhodecode/templates/base/base.html:149
+msgid "loading..."
+msgstr ""
+
+#: rhodecode/templates/base/base.html:234 rhodecode/templates/base/base.html:236
+#: rhodecode/templates/base/base.html:238
 msgid "Switch to"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:172
+#: rhodecode/templates/base/base.html:242
 #: rhodecode/templates/branches/branches.html:13
 msgid "branches"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:179
-#: rhodecode/templates/branches/branches_data.html:32
+#: rhodecode/templates/base/base.html:249
+#: rhodecode/templates/branches/branches_data.html:52
 msgid "There are no branches yet"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:184
+#: rhodecode/templates/base/base.html:254
 #: rhodecode/templates/shortlog/shortlog_data.html:10
 #: rhodecode/templates/tags/tags.html:14
 msgid "tags"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:191
+#: rhodecode/templates/base/base.html:261
 #: rhodecode/templates/tags/tags_data.html:32
 msgid "There are no tags yet"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:198 rhodecode/templates/base/base.html:200
-#: rhodecode/templates/base/base.html:202 rhodecode/templates/files/files.html:4
-msgid "Files"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:207 rhodecode/templates/base/base.html:211
+#: rhodecode/templates/base/base.html:277 rhodecode/templates/base/base.html:281
 #: rhodecode/templates/files/files_annotate.html:40
 #: rhodecode/templates/files/files_source.html:11
 msgid "Options"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:216 rhodecode/templates/base/base.html:218
-#: rhodecode/templates/base/base.html:234
+#: rhodecode/templates/base/base.html:286 rhodecode/templates/base/base.html:288
+#: rhodecode/templates/base/base.html:306
 msgid "settings"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:222
+#: rhodecode/templates/base/base.html:292
 msgid "search"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:229
+#: rhodecode/templates/base/base.html:299
 msgid "journal"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:230
-msgid "repositories"
-msgstr ""
-
-#: rhodecode/templates/base/base.html:231
+#: rhodecode/templates/base/base.html:301
+msgid "repositories groups"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:302
 msgid "users"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:232
+#: rhodecode/templates/base/base.html:303
+msgid "users groups"
+msgstr ""
+
+#: rhodecode/templates/base/base.html:304
 msgid "permissions"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:246 rhodecode/templates/base/base.html:248
+#: rhodecode/templates/base/base.html:317 rhodecode/templates/base/base.html:319
+#: rhodecode/templates/followers/followers.html:5
 msgid "Followers"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:254 rhodecode/templates/base/base.html:256
+#: rhodecode/templates/base/base.html:325 rhodecode/templates/base/base.html:327
+#: rhodecode/templates/forks/forks.html:5
 msgid "Forks"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:287 rhodecode/templates/base/base.html:289
-#: rhodecode/templates/base/base.html:291 rhodecode/templates/search/search.html:4
+#: rhodecode/templates/base/base.html:356 rhodecode/templates/base/base.html:358
+#: rhodecode/templates/base/base.html:360 rhodecode/templates/search/search.html:4
 #: rhodecode/templates/search/search.html:24
 #: rhodecode/templates/search/search.html:46
 msgid "Search"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:339
-#: rhodecode/templates/summary/summary.html:49
+#: rhodecode/templates/base/root.html:57
+#: rhodecode/templates/journal/journal.html:48
+#: rhodecode/templates/summary/summary.html:36
 msgid "Stop following this repository"
 msgstr ""
 
-#: rhodecode/templates/base/base.html:343
-#: rhodecode/templates/summary/summary.html:53
+#: rhodecode/templates/base/root.html:66
+#: rhodecode/templates/summary/summary.html:40
 msgid "Start following this repository"
 msgstr ""
 
@@ -1303,16 +2000,18 @@
 msgid "links"
 msgstr ""
 
-#: rhodecode/templates/branches/branches_data.html:24
+#: rhodecode/templates/branches/branches_data.html:23
+#: rhodecode/templates/branches/branches_data.html:43
 #: rhodecode/templates/shortlog/shortlog_data.html:39
 #: rhodecode/templates/tags/tags_data.html:24
 msgid "changeset"
 msgstr ""
 
-#: rhodecode/templates/branches/branches_data.html:26
+#: rhodecode/templates/branches/branches_data.html:25
+#: rhodecode/templates/branches/branches_data.html:45
 #: rhodecode/templates/files/files.html:12
 #: rhodecode/templates/shortlog/shortlog_data.html:41
-#: rhodecode/templates/summary/summary.html:161
+#: rhodecode/templates/summary/summary.html:233
 #: rhodecode/templates/tags/tags_data.html:26
 msgid "files"
 msgstr ""
@@ -1325,119 +2024,130 @@
 msgid "out of"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:38
+#: rhodecode/templates/changelog/changelog.html:37
 msgid "Show"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:41
-msgid "set"
-msgstr ""
-
-#: rhodecode/templates/changelog/changelog.html:49
-#: rhodecode/templates/changeset/changeset.html:40
-#: rhodecode/templates/summary/summary.html:552
+#: rhodecode/templates/changelog/changelog.html:50
+#: rhodecode/templates/changeset/changeset.html:42
+#: rhodecode/templates/summary/summary.html:609
 msgid "commit"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:74
-#: rhodecode/templates/changeset/changeset.html:52
-msgid "removed"
-msgstr ""
-
-#: rhodecode/templates/changelog/changelog.html:75
-#: rhodecode/templates/changeset/changeset.html:53
-msgid "changed"
-msgstr ""
-
-#: rhodecode/templates/changelog/changelog.html:76
-#: rhodecode/templates/changeset/changeset.html:54
-msgid "added"
-msgstr ""
-
-#: rhodecode/templates/changelog/changelog.html:80
-#: rhodecode/templates/changeset/changeset.html:58
+#: rhodecode/templates/changelog/changelog.html:63
+msgid "Affected number of files, click to show more details"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:67
+#: rhodecode/templates/changeset/changeset.html:66
 msgid "merge"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:85
-#: rhodecode/templates/changeset/changeset.html:64
+#: rhodecode/templates/changelog/changelog.html:72
+#: rhodecode/templates/changeset/changeset.html:72
 msgid "Parent"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:90
-#: rhodecode/templates/changeset/changeset.html:69
+#: rhodecode/templates/changelog/changelog.html:77
+#: rhodecode/templates/changeset/changeset.html:77
 msgid "No parents"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:95
-#: rhodecode/templates/changeset/changeset.html:72
+#: rhodecode/templates/changelog/changelog.html:82
+#: rhodecode/templates/changeset/changeset.html:80
 #: rhodecode/templates/files/files.html:29
 #: rhodecode/templates/files/files_annotate.html:25
+#: rhodecode/templates/files/files_edit.html:33
 #: rhodecode/templates/shortlog/shortlog_data.html:9
 msgid "branch"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:99
-#: rhodecode/templates/changeset/changeset.html:75
+#: rhodecode/templates/changelog/changelog.html:86
+#: rhodecode/templates/changeset/changeset.html:83
 msgid "tag"
 msgstr ""
 
-#: rhodecode/templates/changelog/changelog.html:132
-#: rhodecode/templates/shortlog/shortlog_data.html:64
+#: rhodecode/templates/changelog/changelog.html:122
+msgid "Show selected changes __S -> __E"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog.html:172
+#: rhodecode/templates/shortlog/shortlog_data.html:61
 msgid "There are no changes yet"
 msgstr ""
 
-#: rhodecode/templates/changeset/changeset.html:4
-#: rhodecode/templates/changeset/changeset.html:12
-#: rhodecode/templates/changeset/changeset.html:29
+#: rhodecode/templates/changelog/changelog_details.html:2
+#: rhodecode/templates/changeset/changeset.html:55
+msgid "removed"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:3
+#: rhodecode/templates/changeset/changeset.html:56
+msgid "changed"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:4
+#: rhodecode/templates/changeset/changeset.html:57
+msgid "added"
+msgstr ""
+
+#: rhodecode/templates/changelog/changelog_details.html:6
+#: rhodecode/templates/changelog/changelog_details.html:7
+#: rhodecode/templates/changelog/changelog_details.html:8
+#: rhodecode/templates/changeset/changeset.html:59
+#: rhodecode/templates/changeset/changeset.html:60
+#: rhodecode/templates/changeset/changeset.html:61
+#, python-format
+msgid "affected %s files"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:6
+#: rhodecode/templates/changeset/changeset.html:14
+#: rhodecode/templates/changeset/changeset.html:31
 msgid "Changeset"
 msgstr ""
 
-#: rhodecode/templates/changeset/changeset.html:30
-#: rhodecode/templates/changeset/changeset.html:104
-#: rhodecode/templates/files/file_diff.html:32
-msgid "raw diff"
-msgstr ""
-
 #: rhodecode/templates/changeset/changeset.html:32
-#: rhodecode/templates/changeset/changeset.html:106
+#: rhodecode/templates/changeset/changeset.html:121
+#: rhodecode/templates/changeset/changeset_range.html:78
+#: rhodecode/templates/files/file_diff.html:32
+#: rhodecode/templates/files/file_diff.html:42
+msgid "raw diff"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:34
+#: rhodecode/templates/changeset/changeset.html:123
+#: rhodecode/templates/changeset/changeset_range.html:80
 #: rhodecode/templates/files/file_diff.html:34
 msgid "download diff"
 msgstr ""
 
-#: rhodecode/templates/changeset/changeset.html:81
-msgid "Files affected"
-msgstr ""
-
-#: rhodecode/templates/changeset/changeset.html:102
+#: rhodecode/templates/changeset/changeset.html:90
+#, python-format
+msgid "%s files affected with %s additions and %s deletions."
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:101
+msgid "Changeset was too big and was cut off..."
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset.html:119
+#: rhodecode/templates/changeset/changeset_range.html:76
 #: rhodecode/templates/files/file_diff.html:30
 msgid "diff"
 msgstr ""
 
-#: rhodecode/templates/changeset/changeset.html:115
+#: rhodecode/templates/changeset/changeset.html:132
+#: rhodecode/templates/changeset/changeset_range.html:89
 msgid "No changes in this file"
 msgstr ""
 
-#: rhodecode/templates/errors/error_404.html:5
-msgid "Repository not found"
-msgstr ""
-
-#: rhodecode/templates/errors/error_404.html:22
-msgid "Not Found"
-msgstr ""
-
-#: rhodecode/templates/errors/error_404.html:23
-#, python-format
-msgid "The specified repository \"%s\" is unknown, sorry."
-msgstr ""
-
-#: rhodecode/templates/errors/error_404.html:26
-#, python-format
-msgid "Create \"%s\" repository as %s"
-msgstr ""
-
-#: rhodecode/templates/errors/error_404.html:29
-msgid "Go back to the main repository list page"
+#: rhodecode/templates/changeset/changeset_range.html:30
+msgid "Compare View"
+msgstr ""
+
+#: rhodecode/templates/changeset/changeset_range.html:52
+msgid "Files affected"
 msgstr ""
 
 #: rhodecode/templates/errors/error_document.html:44
@@ -1450,12 +2160,13 @@
 msgid "File diff"
 msgstr ""
 
-#: rhodecode/templates/files/file_diff.html:40
-msgid "No changes"
+#: rhodecode/templates/files/file_diff.html:42
+msgid "Diff is to big to display"
 msgstr ""
 
 #: rhodecode/templates/files/files.html:37
 #: rhodecode/templates/files/files_annotate.html:31
+#: rhodecode/templates/files/files_edit.html:39
 msgid "Location"
 msgstr ""
 
@@ -1476,19 +2187,19 @@
 msgstr ""
 
 #: rhodecode/templates/files/files_annotate.html:33
-#: rhodecode/templates/files/files_browser.html:30
+#: rhodecode/templates/files/files_browser.html:160
 #: rhodecode/templates/files/files_source.html:2
 msgid "Revision"
 msgstr ""
 
 #: rhodecode/templates/files/files_annotate.html:36
-#: rhodecode/templates/files/files_browser.html:28
+#: rhodecode/templates/files/files_browser.html:158
 #: rhodecode/templates/files/files_source.html:7
 msgid "Size"
 msgstr ""
 
 #: rhodecode/templates/files/files_annotate.html:38
-#: rhodecode/templates/files/files_browser.html:29
+#: rhodecode/templates/files/files_browser.html:159
 #: rhodecode/templates/files/files_source.html:9
 msgid "Mimetype"
 msgstr ""
@@ -1498,9 +2209,9 @@
 msgstr ""
 
 #: rhodecode/templates/files/files_annotate.html:43
-#: rhodecode/templates/files/files_annotate.html:69
+#: rhodecode/templates/files/files_annotate.html:78
 #: rhodecode/templates/files/files_source.html:14
-#: rhodecode/templates/files/files_source.html:42
+#: rhodecode/templates/files/files_source.html:51
 msgid "show as raw"
 msgstr ""
 
@@ -1509,40 +2220,131 @@
 msgid "download as raw"
 msgstr ""
 
-#: rhodecode/templates/files/files_annotate.html:48
-#: rhodecode/templates/files/files_source.html:19
+#: rhodecode/templates/files/files_annotate.html:54
+#: rhodecode/templates/files/files_source.html:25
 msgid "History"
 msgstr ""
 
-#: rhodecode/templates/files/files_annotate.html:69
-#: rhodecode/templates/files/files_source.html:42
-msgid "File is to big to display"
-msgstr ""
-
-#: rhodecode/templates/files/files_browser.html:12
-msgid "view"
+#: rhodecode/templates/files/files_annotate.html:73
+#: rhodecode/templates/files/files_source.html:46
+#, python-format
+msgid "Binary file (%s)"
+msgstr ""
+
+#: rhodecode/templates/files/files_annotate.html:78
+#: rhodecode/templates/files/files_source.html:51
+msgid "File is too big to display"
 msgstr ""
 
 #: rhodecode/templates/files/files_browser.html:13
+msgid "view"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:14
 msgid "previous revision"
 msgstr ""
 
-#: rhodecode/templates/files/files_browser.html:15
+#: rhodecode/templates/files/files_browser.html:16
 msgid "next revision"
 msgstr ""
 
-#: rhodecode/templates/files/files_browser.html:31
-msgid "Last modified"
+#: rhodecode/templates/files/files_browser.html:23
+msgid "follow current branch"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:27
+msgid "search file list"
 msgstr ""
 
 #: rhodecode/templates/files/files_browser.html:32
+msgid "Loading file list..."
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:111
+msgid "search truncated"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:122
+msgid "no matching files"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:161
+msgid "Last modified"
+msgstr ""
+
+#: rhodecode/templates/files/files_browser.html:162
 msgid "Last commiter"
 msgstr ""
 
+#: rhodecode/templates/files/files_edit.html:4
+msgid "Edit file"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:19
+msgid "edit file"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:45
+#: rhodecode/templates/shortlog/shortlog_data.html:5
+msgid "commit message"
+msgstr ""
+
+#: rhodecode/templates/files/files_edit.html:51
+msgid "Commit changes"
+msgstr ""
+
 #: rhodecode/templates/files/files_source.html:12
 msgid "show annotation"
 msgstr ""
 
+#: rhodecode/templates/files/files_source.html:153
+msgid "Selection link"
+msgstr ""
+
+#: rhodecode/templates/followers/followers.html:13
+msgid "followers"
+msgstr ""
+
+#: rhodecode/templates/followers/followers_data.html:12
+msgid "Started following"
+msgstr ""
+
+#: rhodecode/templates/forks/forks.html:13
+msgid "forks"
+msgstr ""
+
+#: rhodecode/templates/forks/forks_data.html:17
+msgid "forked"
+msgstr ""
+
+#: rhodecode/templates/forks/forks_data.html:34
+msgid "There are no forks yet"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:34
+msgid "Following"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:41
+msgid "following user"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:41
+msgid "user"
+msgstr ""
+
+#: rhodecode/templates/journal/journal.html:65
+msgid "You are not following any users or repositories"
+msgstr ""
+
+#: rhodecode/templates/journal/journal_data.html:46
+msgid "No entries yet"
+msgstr ""
+
+#: rhodecode/templates/journal/public_journal.html:17
+msgid "Public Journal"
+msgstr ""
+
 #: rhodecode/templates/search/search.html:7
 #: rhodecode/templates/search/search.html:26
 msgid "in repository: "
@@ -1562,7 +2364,7 @@
 msgstr ""
 
 #: rhodecode/templates/search/search.html:57
-msgid "Source codes"
+msgid "File contents"
 msgstr ""
 
 #: rhodecode/templates/search/search.html:59
@@ -1578,12 +2380,16 @@
 msgid "Fork"
 msgstr ""
 
-#: rhodecode/templates/settings/repo_fork.html:29
+#: rhodecode/templates/settings/repo_fork.html:31
 msgid "Fork name"
 msgstr ""
 
+#: rhodecode/templates/settings/repo_fork.html:55
+msgid "fork this repository"
+msgstr ""
+
 #: rhodecode/templates/shortlog/shortlog.html:5
-#: rhodecode/templates/summary/summary.html:609
+#: rhodecode/templates/summary/summary.html:666
 msgid "Shortlog"
 msgstr ""
 
@@ -1591,10 +2397,6 @@
 msgid "shortlog"
 msgstr ""
 
-#: rhodecode/templates/shortlog/shortlog_data.html:5
-msgid "commit message"
-msgstr ""
-
 #: rhodecode/templates/shortlog/shortlog_data.html:6
 msgid "age"
 msgstr ""
@@ -1603,61 +2405,96 @@
 msgid "summary"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:103
+#: rhodecode/templates/summary/summary.html:79
+msgid "remote clone"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:121
 msgid "by"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:110
+#: rhodecode/templates/summary/summary.html:128
 msgid "Clone url"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:119
+#: rhodecode/templates/summary/summary.html:137
 msgid "Trending source files"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:184
-#: rhodecode/templates/summary/summary.html:627
-#: rhodecode/templates/summary/summary.html:638
-msgid "show more"
-msgstr ""
-
-#: rhodecode/templates/summary/summary.html:217
+#: rhodecode/templates/summary/summary.html:146
 msgid "Download"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:233
+#: rhodecode/templates/summary/summary.html:150
+msgid "There are no downloads yet"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:152
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:154
+#: rhodecode/templates/summary/summary.html:320
+msgid "enable"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:162
+#: rhodecode/templates/summary/summary.html:297
+#, python-format
+msgid "Download %s as %s"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:168
+msgid "Check this to download archive with subrepos"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:168
+msgid "with subrepos"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:176
 msgid "Feeds"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:247
+#: rhodecode/templates/summary/summary.html:257
+#: rhodecode/templates/summary/summary.html:684
+#: rhodecode/templates/summary/summary.html:695
+msgid "show more"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:312
 msgid "Commit activity by day / author"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:546
+#: rhodecode/templates/summary/summary.html:324
+msgid "Loaded in"
+msgstr ""
+
+#: rhodecode/templates/summary/summary.html:603
 msgid "commits"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:547
+#: rhodecode/templates/summary/summary.html:604
 msgid "files added"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:548
+#: rhodecode/templates/summary/summary.html:605
 msgid "files changed"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:549
+#: rhodecode/templates/summary/summary.html:606
 msgid "files removed"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:553
+#: rhodecode/templates/summary/summary.html:610
 msgid "file added"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:554
+#: rhodecode/templates/summary/summary.html:611
 msgid "file changed"
 msgstr ""
 
-#: rhodecode/templates/summary/summary.html:555
+#: rhodecode/templates/summary/summary.html:612
 msgid "file removed"
 msgstr ""
 
--- a/rhodecode/lib/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -24,6 +24,55 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+try:
+    import json
+except ImportError:
+    #python 2.5 compatibility
+    import simplejson as json
+
+
+def __get_lem():
+    from pygments import lexers
+    from string import lower
+    from collections import defaultdict
+
+    d = defaultdict(lambda: [])
+
+    def __clean(s):
+        s = s.lstrip('*')
+        s = s.lstrip('.')
+
+        if s.find('[') != -1:
+            exts = []
+            start, stop = s.find('['), s.find(']')
+
+            for suffix in s[start + 1:stop]:
+                exts.append(s[:s.find('[')] + suffix)
+            return map(lower, exts)
+        else:
+            return map(lower, [s])
+
+    for lx, t in sorted(lexers.LEXERS.items()):
+        m = map(__clean, t[-2])
+        if m:
+            m = reduce(lambda x, y: x + y, m)
+            for ext in m:
+                desc = lx.replace('Lexer', '')
+                d[ext].append(desc)
+
+    return dict(d)
+
+# language map is also used by whoosh indexer, which for those specified
+# extensions will index it's content
+LANGUAGES_EXTENSIONS_MAP = __get_lem()
+
+# Additional mappings that are not present in the pygments lexers
+# NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
+ADDITIONAL_MAPPINGS = {'xaml': 'XAML'}
+
+LANGUAGES_EXTENSIONS_MAP.update(ADDITIONAL_MAPPINGS)
+
+
 def str2bool(_str):
     """
     returs True/False value from given string, it tries to translate the
@@ -41,9 +90,57 @@
     return _str in ('t', 'true', 'y', 'yes', 'on', '1')
 
 
+def convert_line_endings(line, mode):
+    """
+    Converts a given line  "line end" accordingly to given mode
+    
+    Available modes are::
+        0 - Unix
+        1 - Mac
+        2 - DOS
+    
+    :param line: given line to convert
+    :param mode: mode to convert to
+    :rtype: str
+    :return: converted line according to mode
+    """
+    from string import replace
+
+    if mode == 0:
+            line = replace(line, '\r\n', '\n')
+            line = replace(line, '\r', '\n')
+    elif mode == 1:
+            line = replace(line, '\r\n', '\r')
+            line = replace(line, '\n', '\r')
+    elif mode == 2:
+            import re
+            line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
+    return line
+
+
+def detect_mode(line, default):
+    """
+    Detects line break for given line, if line break couldn't be found
+    given default value is returned
+
+    :param line: str line
+    :param default: default
+    :rtype: int
+    :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
+    """
+    if line.endswith('\r\n'):
+        return 2
+    elif line.endswith('\n'):
+        return 0
+    elif line.endswith('\r'):
+        return 1
+    else:
+        return default
+
+
 def generate_api_key(username, salt=None):
     """
-    Generates unique API key for given username,if salt is not given
+    Generates unique API key for given username, if salt is not given
     it'll be generated from some random string
 
     :param username: username as string
@@ -60,22 +157,233 @@
     return hashlib.sha1(username + salt).hexdigest()
 
 
-def safe_unicode(_str, from_encoding='utf8'):
+def safe_unicode(str_, from_encoding='utf8'):
     """
-    safe unicode function. In case of UnicodeDecode error we try to return
-    unicode with errors replace
+    safe unicode function. Does few trick to turn str_ into unicode
+     
+    In case of UnicodeDecode error we try to return it with encoding detected
+    by chardet library if it fails fallback to unicode with errors replaced
 
-    :param _str: string to decode
+    :param str_: string to decode
     :rtype: unicode
     :returns: unicode object
     """
+    if isinstance(str_, unicode):
+        return str_
 
-    if isinstance(_str, unicode):
-        return _str
+    try:
+        return unicode(str_)
+    except UnicodeDecodeError:
+        pass
+
+    try:
+        return unicode(str_, from_encoding)
+    except UnicodeDecodeError:
+        pass
+
+    try:
+        import chardet
+        encoding = chardet.detect(str_)['encoding']
+        if encoding is None:
+            raise Exception()
+        return str_.decode(encoding)
+    except (ImportError, UnicodeDecodeError, Exception):
+        return unicode(str_, from_encoding, 'replace')
+
+def safe_str(unicode_, to_encoding='utf8'):
+    """
+    safe str function. Does few trick to turn unicode_ into string
+     
+    In case of UnicodeEncodeError we try to return it with encoding detected
+    by chardet library if it fails fallback to string with errors replaced
+
+    :param unicode_: unicode to encode
+    :rtype: str
+    :returns: str object
+    """
+
+    if isinstance(unicode_, str):
+        return unicode_
 
     try:
-        u_str = unicode(_str, from_encoding)
-    except UnicodeDecodeError:
-        u_str = unicode(_str, from_encoding, 'replace')
+        return unicode_.encode(to_encoding)
+    except UnicodeEncodeError:
+        pass
+    
+    try:
+        import chardet
+        encoding = chardet.detect(unicode_)['encoding']
+        print encoding
+        if encoding is None:
+            raise UnicodeEncodeError()
+        
+        return unicode_.encode(encoding)
+    except (ImportError, UnicodeEncodeError):
+        return unicode_.encode(to_encoding, 'replace')
+
+    return safe_str
+
+
+
+def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
+    """
+    Custom engine_from_config functions that makes sure we use NullPool for
+    file based sqlite databases. This prevents errors on sqlite. This only 
+    applies to sqlalchemy versions < 0.7.0
+
+    """
+    import sqlalchemy
+    from sqlalchemy import engine_from_config as efc
+    import logging
+
+    if int(sqlalchemy.__version__.split('.')[1]) < 7:
+
+        # This solution should work for sqlalchemy < 0.7.0, and should use
+        # proxy=TimerProxy() for execution time profiling
+
+        from sqlalchemy.pool import NullPool
+        url = configuration[prefix + 'url']
+
+        if url.startswith('sqlite'):
+            kwargs.update({'poolclass': NullPool})
+        return efc(configuration, prefix, **kwargs)
+    else:
+        import time
+        from sqlalchemy import event
+        from sqlalchemy.engine import Engine
+
+        log = logging.getLogger('sqlalchemy.engine')
+        BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
+        engine = efc(configuration, prefix, **kwargs)
+
+        def color_sql(sql):
+            COLOR_SEQ = "\033[1;%dm"
+            COLOR_SQL = YELLOW
+            normal = '\x1b[0m'
+            return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
+
+        if configuration['debug']:
+            #attach events only for debug configuration
+
+            def before_cursor_execute(conn, cursor, statement,
+                                    parameters, context, executemany):
+                context._query_start_time = time.time()
+                log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
+
+
+            def after_cursor_execute(conn, cursor, statement,
+                                    parameters, context, executemany):
+                total = time.time() - context._query_start_time
+                log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
+
+            event.listen(engine, "before_cursor_execute",
+                         before_cursor_execute)
+            event.listen(engine, "after_cursor_execute",
+                         after_cursor_execute)
+
+    return engine
+
+
+def age(curdate):
+    """
+    turns a datetime into an age string.
+    
+    :param curdate: datetime object
+    :rtype: unicode
+    :returns: unicode words describing age
+    """
+
+    from datetime import datetime
+    from webhelpers.date import time_ago_in_words
 
-    return u_str
+    _ = lambda s:s
+
+    if not curdate:
+        return ''
+
+    agescales = [(_(u"year"), 3600 * 24 * 365),
+                 (_(u"month"), 3600 * 24 * 30),
+                 (_(u"day"), 3600 * 24),
+                 (_(u"hour"), 3600),
+                 (_(u"minute"), 60),
+                 (_(u"second"), 1), ]
+
+    age = datetime.now() - curdate
+    age_seconds = (age.days * agescales[2][1]) + age.seconds
+    pos = 1
+    for scale in agescales:
+        if scale[1] <= age_seconds:
+            if pos == 6:pos = 5
+            return '%s %s' % (time_ago_in_words(curdate,
+                                                agescales[pos][0]), _('ago'))
+        pos += 1
+
+    return _(u'just now')
+
+
+def uri_filter(uri):
+    """
+    Removes user:password from given url string
+    
+    :param uri:
+    :rtype: unicode
+    :returns: filtered list of strings  
+    """
+    if not uri:
+        return ''
+
+    proto = ''
+
+    for pat in ('https://', 'http://'):
+        if uri.startswith(pat):
+            uri = uri[len(pat):]
+            proto = pat
+            break
+
+    # remove passwords and username
+    uri = uri[uri.find('@') + 1:]
+
+    # get the port
+    cred_pos = uri.find(':')
+    if cred_pos == -1:
+        host, port = uri, None
+    else:
+        host, port = uri[:cred_pos], uri[cred_pos + 1:]
+
+    return filter(None, [proto, host, port])
+
+
+def credentials_filter(uri):
+    """
+    Returns a url with removed credentials
+    
+    :param uri:
+    """
+
+    uri = uri_filter(uri)
+    #check if we have port
+    if len(uri) > 2 and uri[2]:
+        uri[2] = ':' + uri[2]
+
+    return ''.join(uri)
+
+def get_changeset_safe(repo, rev):
+    """
+    Safe version of get_changeset if this changeset doesn't exists for a 
+    repo it returns a Dummy one instead
+    
+    :param repo:
+    :param rev:
+    """
+    from vcs.backends.base import BaseRepository
+    from vcs.exceptions import RepositoryError
+    if not isinstance(repo, BaseRepository):
+        raise Exception('You must pass an Repository '
+                        'object as first argument got %s', type(repo))
+
+    try:
+        cs = repo.get_changeset(rev)
+    except RepositoryError:
+        from rhodecode.lib.utils import EmptyChangeset
+        cs = EmptyChangeset(requested_revision=rev)
+    return cs
\ No newline at end of file
--- a/rhodecode/lib/app_globals.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/app_globals.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,7 +2,7 @@
 
 from beaker.cache import CacheManager
 from beaker.util import parse_cache_config_options
-from vcs.utils.lazy import LazyProperty
+
 
 class Globals(object):
     """Globals acts as a container for objects available throughout the
@@ -18,14 +18,3 @@
         """
         self.cache = CacheManager(**parse_cache_config_options(config))
         self.available_permissions = None   # propagated after init_model
-        self.baseui = None                  # propagated after init_model        
-
-    @LazyProperty
-    def paths(self):
-        if self.baseui:
-            return self.baseui.configitems('paths')
-
-    @LazyProperty
-    def base_path(self):
-        if self.baseui:
-            return self.paths[0][1]
--- a/rhodecode/lib/auth.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/auth.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,9 +2,9 @@
 """
     rhodecode.lib.auth
     ~~~~~~~~~~~~~~~~~~
-    
+
     authentication and permission libraries
-    
+
     :created_on: Apr 4, 2010
     :copyright: (c) 2010 by marcink.
     :license: LICENSE_NAME, see LICENSE_FILE for more details.
@@ -25,7 +25,9 @@
 import random
 import logging
 import traceback
+import hashlib
 
+from tempfile import _RandomNameSequence
 from decorator import decorator
 
 from pylons import config, session, url, request
@@ -39,36 +41,37 @@
 if __platform__ in PLATFORM_OTHERS:
     import bcrypt
 
-from rhodecode.lib import str2bool
+from rhodecode.lib import str2bool, safe_unicode
 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
 from rhodecode.lib.utils import get_repo_slug
 from rhodecode.lib.auth_ldap import AuthLdap
 
 from rhodecode.model import meta
 from rhodecode.model.user import UserModel
-from rhodecode.model.db import Permission, RepoToPerm, Repository, \
-    User, UserToPerm
-
+from rhodecode.model.db import Permission, RhodeCodeSettings
 
 log = logging.getLogger(__name__)
 
+
 class PasswordGenerator(object):
     """This is a simple class for generating password from
         different sets of characters
         usage:
         passwd_gen = PasswordGenerator()
-        #print 8-letter password containing only big and small letters of alphabet
-        print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)        
+        #print 8-letter password containing only big and small letters
+            of alphabet
+        print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
     """
-    ALPHABETS_NUM = r'''1234567890'''#[0]
-    ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
-    ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
-    ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''    #[3]
-    ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
-    ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
+    ALPHABETS_NUM = r'''1234567890'''
+    ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''
+    ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''
+    ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''
+    ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL \
+        + ALPHABETS_NUM + ALPHABETS_SPECIAL
+    ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM
     ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
-    ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
-    ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
+    ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM
+    ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM
 
     def __init__(self, passwd=''):
         self.passwd = passwd
@@ -77,6 +80,7 @@
         self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
         return self.passwd
 
+
 class RhodeCodeCrypto(object):
 
     @classmethod
@@ -84,7 +88,7 @@
         """
         Cryptographic function used for password hashing based on pybcrypt
         or pycrypto in windows
-        
+
         :param password: password to hash
         """
         if __platform__ in PLATFORM_WIN:
@@ -92,14 +96,15 @@
         elif __platform__ in PLATFORM_OTHERS:
             return bcrypt.hashpw(str_, bcrypt.gensalt(10))
         else:
-            raise Exception('Unknown or unsupported platform %s' % __platform__)
+            raise Exception('Unknown or unsupported platform %s' \
+                            % __platform__)
 
     @classmethod
     def hash_check(cls, password, hashed):
         """
         Checks matching password with it's hashed value, runs different
         implementation based on platform it runs on
-        
+
         :param password: password
         :param hashed: password in hashed form
         """
@@ -109,46 +114,55 @@
         elif __platform__ in PLATFORM_OTHERS:
             return bcrypt.hashpw(password, hashed) == hashed
         else:
-            raise Exception('Unknown or unsupported platform %s' % __platform__)
+            raise Exception('Unknown or unsupported platform %s' \
+                            % __platform__)
 
 
 def get_crypt_password(password):
     return RhodeCodeCrypto.hash_string(password)
 
+
 def check_password(password, hashed):
     return RhodeCodeCrypto.hash_check(password, hashed)
 
+
+def generate_api_key(username, salt=None):
+    if salt is None:
+        salt = _RandomNameSequence().next()
+
+    return hashlib.sha1(username + salt).hexdigest()
+
+
 def authfunc(environ, username, password):
-    """
-    Dummy authentication function used in Mercurial/Git/ and access control,
-    
+    """Dummy authentication function used in Mercurial/Git/ and access control,
+
     :param environ: needed only for using in Basic auth
     """
     return authenticate(username, password)
 
 
 def authenticate(username, password):
-    """
-    Authentication function used for access control,
+    """Authentication function used for access control,
     firstly checks for db authentication then if ldap is enabled for ldap
     authentication, also creates ldap user if not in database
-    
+
     :param username: username
     :param password: password
     """
+
     user_model = UserModel()
     user = user_model.get_by_username(username, cache=False)
 
     log.debug('Authenticating user using RhodeCode account')
-    if user is not None and user.is_ldap is False:
+    if user is not None and not user.ldap_dn:
         if user.active:
-
             if user.username == 'default' and user.active:
                 log.info('user %s authenticated correctly as anonymous user',
                          username)
                 return True
 
-            elif user.username == username and check_password(password, user.password):
+            elif user.username == username and check_password(password,
+                                                              user.password):
                 log.info('user %s authenticated correctly', username)
                 return True
         else:
@@ -159,35 +173,48 @@
         user_obj = user_model.get_by_username(username, cache=False,
                                             case_insensitive=True)
 
-        if user_obj is not None and user_obj.is_ldap is False:
+        if user_obj is not None and not user_obj.ldap_dn:
             log.debug('this user already exists as non ldap')
             return False
 
-        from rhodecode.model.settings import SettingsModel
-        ldap_settings = SettingsModel().get_ldap_settings()
-
+        ldap_settings = RhodeCodeSettings.get_ldap_settings()
         #======================================================================
-        # FALLBACK TO LDAP AUTH IN ENABLE                
+        # FALLBACK TO LDAP AUTH IF ENABLE
         #======================================================================
         if str2bool(ldap_settings.get('ldap_active')):
             log.debug("Authenticating user using ldap")
             kwargs = {
-                  'server':ldap_settings.get('ldap_host', ''),
-                  'base_dn':ldap_settings.get('ldap_base_dn', ''),
-                  'port':ldap_settings.get('ldap_port'),
-                  'bind_dn':ldap_settings.get('ldap_dn_user'),
-                  'bind_pass':ldap_settings.get('ldap_dn_pass'),
-                  'use_ldaps':str2bool(ldap_settings.get('ldap_ldaps')),
-                  'ldap_version':3,
+                  'server': ldap_settings.get('ldap_host', ''),
+                  'base_dn': ldap_settings.get('ldap_base_dn', ''),
+                  'port': ldap_settings.get('ldap_port'),
+                  'bind_dn': ldap_settings.get('ldap_dn_user'),
+                  'bind_pass': ldap_settings.get('ldap_dn_pass'),
+                  'tls_kind': ldap_settings.get('ldap_tls_kind'),
+                  'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'),
+                  'ldap_filter': ldap_settings.get('ldap_filter'),
+                  'search_scope': ldap_settings.get('ldap_search_scope'),
+                  'attr_login': ldap_settings.get('ldap_attr_login'),
+                  'ldap_version': 3,
                   }
             log.debug('Checking for ldap authentication')
             try:
                 aldap = AuthLdap(**kwargs)
-                res = aldap.authenticate_ldap(username, password)
-                log.debug('Got ldap response %s', res)
+                (user_dn, ldap_attrs) = aldap.authenticate_ldap(username,
+                                                                password)
+                log.debug('Got ldap DN response %s', user_dn)
+
+                get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\
+                                                           .get(k), [''])[0]
 
-                if user_model.create_ldap(username, password):
-                    log.info('created new ldap user')
+                user_attrs = {
+                 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')),
+                 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')),
+                 'email': get_ldap_attr('ldap_attr_email'),
+                }
+
+                if user_model.create_ldap(username, password, user_dn,
+                                          user_attrs):
+                    log.info('created new ldap user %s', username)
 
                 return True
             except (LdapUsernameError, LdapPasswordError,):
@@ -197,30 +224,82 @@
                 pass
     return False
 
+
 class  AuthUser(object):
     """
-    A simple object that handles a mercurial username for authentication
+    A simple object that handles all attributes of user in RhodeCode
+
+    It does lookup based on API key,given user, or user present in session
+    Then it fills all required information for such user. It also checks if
+    anonymous access is enabled and if so, it returns default user as logged
+    in
     """
-    def __init__(self):
+
+    def __init__(self, user_id=None, api_key=None):
+
+        self.user_id = user_id
+        self.api_key = None
+
         self.username = 'None'
         self.name = ''
         self.lastname = ''
         self.email = ''
-        self.user_id = None
         self.is_authenticated = False
-        self.is_admin = False
+        self.admin = False
         self.permissions = {}
+        self._api_key = api_key
+        self.propagate_data()
+
+    def propagate_data(self):
+        user_model = UserModel()
+        self.anonymous_user = user_model.get_by_username('default', cache=True)
+        if self._api_key and self._api_key != self.anonymous_user.api_key:
+            #try go get user by api key
+            log.debug('Auth User lookup by API KEY %s', self._api_key)
+            user_model.fill_data(self, api_key=self._api_key)
+        else:
+            log.debug('Auth User lookup by USER ID %s', self.user_id)
+            if self.user_id is not None \
+                and self.user_id != self.anonymous_user.user_id:
+                user_model.fill_data(self, user_id=self.user_id)
+            else:
+                if self.anonymous_user.active is True:
+                    user_model.fill_data(self,
+                                         user_id=self.anonymous_user.user_id)
+                    #then we set this user is logged in
+                    self.is_authenticated = True
+                else:
+                    self.is_authenticated = False
+
+        log.debug('Auth User is now %s', self)
+        user_model.fill_perms(self)
+
+    @property
+    def is_admin(self):
+        return self.admin
+
+    @property
+    def full_contact(self):
+        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 
     def __repr__(self):
-        return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
+        return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
+                                              self.is_authenticated)
+
+    def set_authenticated(self, authenticated=True):
+
+        if self.user_id != self.anonymous_user.user_id:
+            self.is_authenticated = authenticated
+
 
 def set_available_permissions(config):
-    """
-    This function will propagate pylons globals with all available defined
-    permission given in db. We don't wannt to check each time from db for new 
+    """This function will propagate pylons globals with all available defined
+    permission given in db. We don't want to check each time from db for new
     permissions since adding a new permission also requires application restart
     ie. to decorate new views with the newly created permission
-    :param config:
+
+    :param config: current pylons config instance
+
     """
     log.info('getting information about all available permissions')
     try:
@@ -233,159 +312,78 @@
 
     config['available_permissions'] = [x.permission_name for x in all_perms]
 
-def set_base_path(config):
-    config['base_path'] = config['pylons.app_globals'].base_path
-
 
-def fill_perms(user):
+#==============================================================================
+# CHECK DECORATORS
+#==============================================================================
+class LoginRequired(object):
     """
-    Fills user permission attribute with permissions taken from database
-    :param user:
+    Must be logged in to execute this function else
+    redirect to login page
+
+    :param api_access: if enabled this checks only for valid auth token
+        and grants access based on valid token
     """
 
-    sa = meta.Session()
-    user.permissions['repositories'] = {}
-    user.permissions['global'] = set()
-
-    #===========================================================================
-    # fetch default permissions
-    #===========================================================================
-    default_user = UserModel().get_by_username('default', cache=True)
-
-    default_perms = sa.query(RepoToPerm, Repository, Permission)\
-        .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
-        .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
-        .filter(RepoToPerm.user == default_user).all()
-
-    if user.is_admin:
-        #=======================================================================
-        # #admin have all default rights set to admin        
-        #=======================================================================
-        user.permissions['global'].add('hg.admin')
-
-        for perm in default_perms:
-            p = 'repository.admin'
-            user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
+    def __init__(self, api_access=False):
+        self.api_access = api_access
 
-    else:
-        #=======================================================================
-        # set default permissions
-        #=======================================================================
-
-        #default global
-        default_global_perms = sa.query(UserToPerm)\
-            .filter(UserToPerm.user == sa.query(User)\
-                   .filter(User.username == 'default').one())
+    def __call__(self, func):
+        return decorator(self.__wrapper, func)
 
-        for perm in default_global_perms:
-            user.permissions['global'].add(perm.permission.permission_name)
-
-        #default repositories
-        for perm in default_perms:
-            if perm.Repository.private and not perm.Repository.user_id == user.user_id:
-                #disable defaults for private repos,
-                p = 'repository.none'
-            elif perm.Repository.user_id == user.user_id:
-                #set admin if owner
-                p = 'repository.admin'
-            else:
-                p = perm.Permission.permission_name
+    def __wrapper(self, func, *fargs, **fkwargs):
+        cls = fargs[0]
+        user = cls.rhodecode_user
 
-            user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
-
-        #=======================================================================
-        # #overwrite default with user permissions if any
-        #=======================================================================
-        user_perms = sa.query(RepoToPerm, Permission, Repository)\
-            .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
-            .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
-            .filter(RepoToPerm.user_id == user.user_id).all()
-
-        for perm in user_perms:
-            if perm.Repository.user_id == user.user_id:#set admin if owner
-                p = 'repository.admin'
+        api_access_ok = False
+        if self.api_access:
+            log.debug('Checking API KEY access for %s', cls)
+            if user.api_key == request.GET.get('api_key'):
+                api_access_ok = True
             else:
-                p = perm.Permission.permission_name
-            user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
-    meta.Session.remove()
-    return user
+                log.debug("API KEY token not valid")
 
-def get_user(session):
-    """
-    Gets user from session, and wraps permissions into user
-    :param session:
-    """
-    user = session.get('rhodecode_user', AuthUser())
-    #if the user is not logged in we check for anonymous access
-    #if user is logged and it's a default user check if we still have anonymous
-    #access enabled
-    if user.user_id is None or user.username == 'default':
-        anonymous_user = UserModel().get_by_username('default', cache=True)
-        if anonymous_user.active is True:
-            #then we set this user is logged in
-            user.is_authenticated = True
-            user.user_id = anonymous_user.user_id
+        log.debug('Checking if %s is authenticated @ %s', user.username, cls)
+        if user.is_authenticated or api_access_ok:
+            log.debug('user %s is authenticated', user.username)
+            return func(*fargs, **fkwargs)
         else:
-            user.is_authenticated = False
-
-    if user.is_authenticated:
-        user = UserModel().fill_data(user)
+            log.warn('user %s NOT authenticated', user.username)
+            p = url.current()
 
-    user = fill_perms(user)
-    session['rhodecode_user'] = user
-    session.save()
-    return user
+            log.debug('redirecting to login page with %s', p)
+            return redirect(url('login_home', came_from=p))
 
-#===============================================================================
-# CHECK DECORATORS
-#===============================================================================
-class LoginRequired(object):
-    """Must be logged in to execute this function else 
+
+class NotAnonymous(object):
+    """Must be logged in to execute this function else
     redirect to login page"""
 
     def __call__(self, func):
         return decorator(self.__wrapper, func)
 
     def __wrapper(self, func, *fargs, **fkwargs):
-        user = session.get('rhodecode_user', AuthUser())
-        log.debug('Checking login required for user:%s', user.username)
-        if user.is_authenticated:
-            log.debug('user %s is authenticated', user.username)
-            return func(*fargs, **fkwargs)
-        else:
-            log.warn('user %s not authenticated', user.username)
+        cls = fargs[0]
+        self.user = cls.rhodecode_user
+
+        log.debug('Checking if user is not anonymous @%s', cls)
+
+        anonymous = self.user.username == 'default'
+
+        if anonymous:
             p = url.current()
 
-            log.debug('redirecting to login page with %s', p)
-            return redirect(url('login_home', came_from=p))
-
-class NotAnonymous(object):
-    """Must be logged in to execute this function else 
-    redirect to login page"""
-
-    def __call__(self, func):
-        return decorator(self.__wrapper, func)
-
-    def __wrapper(self, func, *fargs, **fkwargs):
-        user = session.get('rhodecode_user', AuthUser())
-        log.debug('Checking if user is not anonymous')
-
-        anonymous = user.username == 'default'
-
-        if anonymous:
-            p = ''
-            if request.environ.get('SCRIPT_NAME') != '/':
-                p += request.environ.get('SCRIPT_NAME')
-
-            p += request.environ.get('PATH_INFO')
-            if request.environ.get('QUERY_STRING'):
-                p += '?' + request.environ.get('QUERY_STRING')
+            import rhodecode.lib.helpers as h
+            h.flash(_('You need to be a registered user to '
+                      'perform this action'),
+                    category='warning')
             return redirect(url('login_home', came_from=p))
         else:
             return func(*fargs, **fkwargs)
 
+
 class PermsDecorator(object):
-    """Base class for decorators"""
+    """Base class for controller decorators"""
 
     def __init__(self, *required_perms):
         available_perms = config['available_permissions']
@@ -398,35 +396,44 @@
     def __call__(self, func):
         return decorator(self.__wrapper, func)
 
-
     def __wrapper(self, func, *fargs, **fkwargs):
-#        _wrapper.__name__ = func.__name__
-#        _wrapper.__dict__.update(func.__dict__)
-#        _wrapper.__doc__ = func.__doc__
-        self.user = session.get('rhodecode_user', AuthUser())
+        cls = fargs[0]
+        self.user = cls.rhodecode_user
         self.user_perms = self.user.permissions
         log.debug('checking %s permissions %s for %s %s',
-           self.__class__.__name__, self.required_perms, func.__name__,
+           self.__class__.__name__, self.required_perms, cls,
                self.user)
 
         if self.check_permissions():
-            log.debug('Permission granted for %s %s', func.__name__, self.user)
-
+            log.debug('Permission granted for %s %s', cls, self.user)
             return func(*fargs, **fkwargs)
 
         else:
-            log.warning('Permission denied for %s %s', func.__name__, self.user)
-            #redirect with forbidden ret code
-            return abort(403)
+            log.warning('Permission denied for %s %s', cls, self.user)
 
 
+            anonymous = self.user.username == 'default'
+
+            if anonymous:
+                p = url.current()
+
+                import rhodecode.lib.helpers as h
+                h.flash(_('You need to be a signed in to '
+                          'view this page'),
+                        category='warning')
+                return redirect(url('login_home', came_from=p))
+
+            else:
+                #redirect with forbidden ret code
+                return abort(403)
 
     def check_permissions(self):
         """Dummy function for overriding"""
         raise Exception('You have to write this function in child class')
 
+
 class HasPermissionAllDecorator(PermsDecorator):
-    """Checks for access permission for all given predicates. All of them 
+    """Checks for access permission for all given predicates. All of them
     have to be meet in order to fulfill the request
     """
 
@@ -437,7 +444,7 @@
 
 
 class HasPermissionAnyDecorator(PermsDecorator):
-    """Checks for access permission for any of given predicates. In order to 
+    """Checks for access permission for any of given predicates. In order to
     fulfill the request any of predicates must be meet
     """
 
@@ -446,8 +453,9 @@
             return True
         return False
 
+
 class HasRepoPermissionAllDecorator(PermsDecorator):
-    """Checks for access permission for all given predicates for specific 
+    """Checks for access permission for all given predicates for specific
     repository. All of them have to be meet in order to fulfill the request
     """
 
@@ -463,7 +471,7 @@
 
 
 class HasRepoPermissionAnyDecorator(PermsDecorator):
-    """Checks for access permission for any of given predicates for specific 
+    """Checks for access permission for any of given predicates for specific
     repository. In order to fulfill the request any of predicates must be meet
     """
 
@@ -477,10 +485,11 @@
         if self.required_perms.intersection(user_perms):
             return True
         return False
-#===============================================================================
+
+
+#==============================================================================
 # CHECK FUNCTIONS
-#===============================================================================
-
+#==============================================================================
 class PermsFunction(object):
     """Base function for other check functions"""
 
@@ -500,36 +509,39 @@
         if not user:
             return False
         self.user_perms = user.permissions
-        self.granted_for = user.username
+        self.granted_for = user
         log.debug('checking %s %s %s', self.__class__.__name__,
                   self.required_perms, user)
 
         if self.check_permissions():
-            log.debug('Permission granted for %s @ %s %s', self.granted_for,
-                      check_Location, user)
+            log.debug('Permission granted %s @ %s', self.granted_for,
+                      check_Location or 'unspecified location')
             return True
 
         else:
-            log.warning('Permission denied for %s @ %s %s', self.granted_for,
-                        check_Location, user)
+            log.warning('Permission denied for %s @ %s', self.granted_for,
+                        check_Location or 'unspecified location')
             return False
 
     def check_permissions(self):
         """Dummy function for overriding"""
         raise Exception('You have to write this function in child class')
 
+
 class HasPermissionAll(PermsFunction):
     def check_permissions(self):
         if self.required_perms.issubset(self.user_perms.get('global')):
             return True
         return False
 
+
 class HasPermissionAny(PermsFunction):
     def check_permissions(self):
         if self.required_perms.intersection(self.user_perms.get('global')):
             return True
         return False
 
+
 class HasRepoPermissionAll(PermsFunction):
 
     def __call__(self, repo_name=None, check_Location=''):
@@ -541,8 +553,8 @@
             self.repo_name = get_repo_slug(request)
 
         try:
-            self.user_perms = set([self.user_perms['repositories']\
-                                   [self.repo_name]])
+            self.user_perms = set([self.user_perms['reposit'
+                                                   'ories'][self.repo_name]])
         except KeyError:
             return False
         self.granted_for = self.repo_name
@@ -550,6 +562,7 @@
             return True
         return False
 
+
 class HasRepoPermissionAny(PermsFunction):
 
     def __call__(self, repo_name=None, check_Location=''):
@@ -561,8 +574,8 @@
             self.repo_name = get_repo_slug(request)
 
         try:
-            self.user_perms = set([self.user_perms['repositories']\
-                                   [self.repo_name]])
+            self.user_perms = set([self.user_perms['reposi'
+                                                   'tories'][self.repo_name]])
         except KeyError:
             return False
         self.granted_for = self.repo_name
@@ -570,23 +583,18 @@
             return True
         return False
 
-#===============================================================================
+
+#==============================================================================
 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
-#===============================================================================
-
+#==============================================================================
 class HasPermissionAnyMiddleware(object):
     def __init__(self, *perms):
         self.required_perms = set(perms)
 
     def __call__(self, user, repo_name):
-        usr = AuthUser()
-        usr.user_id = user.user_id
-        usr.username = user.username
-        usr.is_admin = user.admin
-
+        usr = AuthUser(user.user_id)
         try:
-            self.user_perms = set([fill_perms(usr)\
-                                   .permissions['repositories'][repo_name]])
+            self.user_perms = set([usr.permissions['repositories'][repo_name]])
         except:
             self.user_perms = set()
         self.granted_for = ''
@@ -596,7 +604,7 @@
 
     def check_permissions(self):
         log.debug('checking mercurial protocol '
-                  'permissions for user:%s repository:%s',
+                  'permissions %s for user:%s repository:%s', self.user_perms,
                                                 self.username, self.repo_name)
         if self.required_perms.intersection(self.user_perms):
             log.debug('permission granted')
--- a/rhodecode/lib/auth_ldap.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/auth_ldap.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,8 +1,15 @@
-#!/usr/bin/env python
-# encoding: utf-8
-# ldap authentication lib
-# Copyright (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
-#
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.controllers.changelog
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    RhodeCode authentication library for LDAP
+
+    :created_on: Created on Nov 17, 2010
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
@@ -15,30 +22,39 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-Created on Nov 17, 2010
 
-@author: marcink
-"""
-
-from rhodecode.lib.exceptions import *
 import logging
 
+from rhodecode.lib.exceptions import LdapConnectionError, LdapUsernameError, \
+    LdapPasswordError
+
 log = logging.getLogger(__name__)
 
+
 try:
     import ldap
 except ImportError:
+    # means that python-ldap is not installed
     pass
 
+
 class AuthLdap(object):
 
     def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
-                 use_ldaps=False, ldap_version=3):
+                 tls_kind='PLAIN', tls_reqcert='DEMAND', ldap_version=3,
+                 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))',
+                 search_scope='SUBTREE',
+                 attr_login='uid'):
         self.ldap_version = ldap_version
-        if use_ldaps:
+        ldap_server_type = 'ldap'
+
+        self.TLS_KIND = tls_kind
+
+        if self.TLS_KIND == 'LDAPS':
             port = port or 689
-        self.LDAP_USE_LDAPS = use_ldaps
+            ldap_server_type = ldap_server_type + 's'
+
+        self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert]
         self.LDAP_SERVER_ADDRESS = server
         self.LDAP_SERVER_PORT = port
 
@@ -46,20 +62,21 @@
         self.LDAP_BIND_DN = bind_dn
         self.LDAP_BIND_PASS = bind_pass
 
-        ldap_server_type = 'ldap'
-        if self.LDAP_USE_LDAPS:ldap_server_type = ldap_server_type + 's'
         self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
                                                self.LDAP_SERVER_ADDRESS,
                                                self.LDAP_SERVER_PORT)
 
         self.BASE_DN = base_dn
+        self.LDAP_FILTER = ldap_filter
+        self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
+        self.attr_login = attr_login
 
     def authenticate_ldap(self, username, password):
         """Authenticate a user via LDAP and return his/her LDAP properties.
-    
+
         Raises AuthenticationError if the credentials are rejected, or
         EnvironmentError if the LDAP server can't be reached.
-        
+
         :param username: username
         :param password: password
         """
@@ -72,31 +89,59 @@
             raise LdapUsernameError("invalid character in username: ,")
         try:
             ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
+            ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
+            ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
+            ldap.set_option(ldap.OPT_TIMEOUT, 20)
             ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
+            ldap.set_option(ldap.OPT_TIMELIMIT, 15)
+            if self.TLS_KIND != 'PLAIN':
+                ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
             server = ldap.initialize(self.LDAP_SERVER)
             if self.ldap_version == 2:
                 server.protocol = ldap.VERSION2
             else:
                 server.protocol = ldap.VERSION3
 
+            if self.TLS_KIND == 'START_TLS':
+                server.start_tls_s()
+
             if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
                 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
 
-            dn = self.BASE_DN % {'user':uid}
-            log.debug("Authenticating %r at %s", dn, self.LDAP_SERVER)
-            server.simple_bind_s(dn, password)
+            filt = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login,
+                                     username)
+            log.debug("Authenticating %r filt %s at %s", self.BASE_DN,
+                      filt, self.LDAP_SERVER)
+            lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE,
+                                           filt)
+
+            if not lobjects:
+                raise ldap.NO_SUCH_OBJECT()
+
+            for (dn, _attrs) in lobjects:
+                if dn is None:
+                    continue
 
-            properties = server.search_s(dn, ldap.SCOPE_SUBTREE)
-            if not properties:
-                raise ldap.NO_SUCH_OBJECT()
+                try:
+                    server.simple_bind_s(dn, password)
+                    attrs = server.search_ext_s(dn, ldap.SCOPE_BASE,
+                                                '(objectClass=*)')[0][1]
+                    break
+
+                except ldap.INVALID_CREDENTIALS, e:
+                    log.debug("LDAP rejected password for user '%s' (%s): %s",
+                              uid, username, dn)
+
+            else:
+                log.debug("No matching LDAP objects for authentication "
+                          "of '%s' (%s)", uid, username)
+                raise LdapPasswordError()
+
         except ldap.NO_SUCH_OBJECT, e:
             log.debug("LDAP says no such user '%s' (%s)", uid, username)
             raise LdapUsernameError()
-        except ldap.INVALID_CREDENTIALS, e:
-            log.debug("LDAP rejected password for user '%s' (%s)", uid, username)
-            raise LdapPasswordError()
         except ldap.SERVER_DOWN, e:
-            raise LdapConnectionError("LDAP can't access authentication server")
+            raise LdapConnectionError("LDAP can't access "
+                                      "authentication server")
 
-        return properties[0]
-
+        return (dn, attrs)
--- a/rhodecode/lib/backup_manager.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/backup_manager.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,8 +1,15 @@
-#!/usr/bin/env python
-# encoding: utf-8
-# mercurial repository backup manager
-# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
- 
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.lib.backup_manager
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Mercurial repositories backup manager, it allows to backups all 
+    repositories and send it to backup server using RSA key via ssh.
+
+    :created_on: Feb 28, 2010
+    :copyright: (c) 2010 by marcink.
+    :license: LICENSE_NAME, see LICENSE_FILE for more details.
+"""
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
@@ -16,27 +23,23 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-"""
-Created on Feb 28, 2010
-Mercurial repositories backup manager
-@author: marcink
-"""
-
+import os
+import sys
 
 import logging
 import tarfile
-import os
 import datetime
-import sys
 import subprocess
+
 logging.basicConfig(level=logging.DEBUG,
                     format="%(asctime)s %(levelname)-5.5s %(message)s")
 
+
 class BackupManager(object):
     def __init__(self, repos_location, rsa_key, backup_server):
         today = datetime.datetime.now().weekday() + 1
         self.backup_file_name = "mercurial_repos.%s.tar.gz" % today
-        
+
         self.id_rsa_path = self.get_id_rsa(rsa_key)
         self.repos_path = self.get_repos_path(repos_location)
         self.backup_server = backup_server
@@ -46,13 +49,12 @@
         logging.info('starting backup for %s', self.repos_path)
         logging.info('backup target %s', self.backup_file_path)
 
-
     def get_id_rsa(self, rsa_key):
         if not os.path.isfile(rsa_key):
             logging.error('Could not load id_rsa key file in %s', rsa_key)
             sys.exit()
         return rsa_key
-    
+
     def get_repos_path(self, path):
         if not os.path.isdir(path):
             logging.error('Wrong location for repositories in %s', path)
@@ -69,14 +71,12 @@
         tar.close()
         logging.info('finished backup of mercurial repositories')
 
-
-
     def transfer_files(self):
         params = {
                   'id_rsa_key': self.id_rsa_path,
-                  'backup_file':os.path.join(self.backup_file_path,
+                  'backup_file': os.path.join(self.backup_file_path,
                                              self.backup_file_name),
-                  'backup_server':self.backup_server
+                  'backup_server': self.backup_server
                   }
         cmd = ['scp', '-l', '40000', '-i', '%(id_rsa_key)s' % params,
                '%(backup_file)s' % params,
@@ -84,23 +84,18 @@
 
         subprocess.call(cmd)
         logging.info('Transfered file %s to %s', self.backup_file_name, cmd[4])
-        
-    
+
     def rm_file(self):
         logging.info('Removing file %s', self.backup_file_name)
         os.remove(os.path.join(self.backup_file_path, self.backup_file_name))
-    
-
 
 if __name__ == "__main__":
-    
+
     repo_location = '/home/repo_path'
     backup_server = 'root@192.168.1.100:/backups/mercurial'
     rsa_key = '/home/id_rsa'
-    
+
     B_MANAGER = BackupManager(repo_location, rsa_key, backup_server)
     B_MANAGER.backup_repos()
     B_MANAGER.transfer_files()
     B_MANAGER.rm_file()
-
-
--- a/rhodecode/lib/base.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/base.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,42 +2,37 @@
 
 Provides the BaseController class for subclassing.
 """
-from pylons import config, tmpl_context as c, request, session
+import logging
+
+from pylons import config, tmpl_context as c, request, session, url
 from pylons.controllers import WSGIController
+from pylons.controllers.util import redirect
 from pylons.templating import render_mako as render
+
 from rhodecode import __version__
-from rhodecode.lib import auth
+from rhodecode.lib.auth import AuthUser
 from rhodecode.lib.utils import get_repo_slug
 from rhodecode.model import meta
 from rhodecode.model.scm import ScmModel
 from rhodecode import BACKENDS
+from rhodecode.model.db import Repository
+
+log = logging.getLogger(__name__)
 
 class BaseController(WSGIController):
 
     def __before__(self):
         c.rhodecode_version = __version__
-        c.rhodecode_name = config['rhodecode_title']
+        c.rhodecode_name = config.get('rhodecode_title')
+        c.ga_code = config.get('rhodecode_ga_code')
         c.repo_name = get_repo_slug(request)
-        c.cached_repo_list = ScmModel().get_repos()
         c.backends = BACKENDS.keys()
-        self.cut_off_limit = int(config['cut_off_limit'])
-        self.sa = meta.Session()
-        scm_model = ScmModel(self.sa)
-        #c.unread_journal = scm_model.get_unread_journal()
+        self.cut_off_limit = int(config.get('cut_off_limit'))
 
-        if c.repo_name:
-            cached_repo = scm_model.get(c.repo_name)
-            if cached_repo:
-                c.repository_tags = cached_repo.tags
-                c.repository_branches = cached_repo.branches
-                c.repository_followers = scm_model.get_followers(cached_repo.dbrepo.repo_id)
-                c.repository_forks = scm_model.get_forks(cached_repo.dbrepo.repo_id)
-            else:
-                c.repository_tags = {}
-                c.repository_branches = {}
-                c.repository_followers = 0
-                c.repository_forks = 0
+        self.sa = meta.Session()
+        self.scm_model = ScmModel(self.sa)
 
+        #c.unread_journal = scm_model.get_unread_journal()
 
     def __call__(self, environ, start_response):
         """Invoke the Controller"""
@@ -45,8 +40,43 @@
         # the request is routed to. This routing information is
         # available in environ['pylons.routes_dict']
         try:
-            #putting this here makes sure that we update permissions every time
-            self.rhodecode_user = c.rhodecode_user = auth.get_user(session)
+            # putting this here makes sure that we update permissions each time
+            api_key = request.GET.get('api_key')
+            user_id = getattr(session.get('rhodecode_user'), 'user_id', None)
+            self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key)
+            self.rhodecode_user.set_authenticated(
+                                        getattr(session.get('rhodecode_user'),
+                                       'is_authenticated', False))
+            session['rhodecode_user'] = self.rhodecode_user
+            session.save()
             return WSGIController.__call__(self, environ, start_response)
         finally:
             meta.Session.remove()
+
+
+class BaseRepoController(BaseController):
+    """
+    Base class for controllers responsible for loading all needed data
+    for those controllers, loaded items are
+
+    c.rhodecode_repo: instance of scm repository (taken from cache)
+
+    """
+
+    def __before__(self):
+        super(BaseRepoController, self).__before__()
+        if c.repo_name:
+
+            c.rhodecode_db_repo = Repository.by_repo_name(c.repo_name)
+            c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
+
+            if c.rhodecode_repo is None:
+                log.error('%s this repository is present in database but it '
+                          'cannot be created as an scm instance', c.repo_name)
+
+                redirect(url('home'))
+
+            c.repository_followers = \
+                self.scm_model.get_followers(c.repo_name)
+            c.repository_forks = self.scm_model.get_forks(c.repo_name)
+
--- a/rhodecode/lib/celerylib/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/celerylib/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 """
-    package.rhodecode.lib.celerylib.__init__
-    ~~~~~~~~~~~~~~
+    rhodecode.lib.celerylib.__init__
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     celery libs for RhodeCode
-    
+
     :created_on: Nov 27, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -28,25 +28,28 @@
 import socket
 import traceback
 import logging
+from os.path import dirname as dn, join as jn
 
 from hashlib import md5
 from decorator import decorator
+from pylons import  config
+
 from vcs.utils.lazy import LazyProperty
 
+from rhodecode.lib import str2bool
 from rhodecode.lib.pidlock import DaemonLock, LockHeld
 
-from pylons import  config
+from celery.messaging import establish_connection
+
 
 log = logging.getLogger(__name__)
 
-def str2bool(v):
-    return v.lower() in ["yes", "true", "t", "1"] if v else None
-
 try:
     CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
 except KeyError:
     CELERY_ON = False
 
+
 class ResultWrapper(object):
     def __init__(self, task):
         self.task = task
@@ -55,14 +58,16 @@
     def result(self):
         return self.task
 
+
 def run_task(task, *args, **kwargs):
     if CELERY_ON:
         try:
-            t = task.delay(*args, **kwargs)
+            t = task.apply_async(args=args, kwargs=kwargs)
             log.info('running task %s:%s', t.task_id, task)
             return t
+
         except socket.error, e:
-            if  e.errno == 111:
+            if isinstance(e, IOError) and e.errno == 111:
                 log.debug('Unable to connect to celeryd. Sync execution')
             else:
                 log.error(traceback.format_exc())
@@ -75,17 +80,25 @@
     return ResultWrapper(task(*args, **kwargs))
 
 
+def __get_lockkey(func, *fargs, **fkwargs):
+    params = list(fargs)
+    params.extend(['%s-%s' % ar for ar in fkwargs.items()])
+
+    func_name = str(func.__name__) if hasattr(func, '__name__') else str(func)
+
+    lockkey = 'task_%s.lock' % \
+        md5(func_name + '-' + '-'.join(map(str, params))).hexdigest()
+    return lockkey
+
+
 def locked_task(func):
     def __wrapper(func, *fargs, **fkwargs):
-        params = list(fargs)
-        params.extend(['%s-%s' % ar for ar in fkwargs.items()])
+        lockkey = __get_lockkey(func, *fargs, **fkwargs)
+        lockkey_path = dn(dn(dn(os.path.abspath(__file__))))
 
-        lockkey = 'task_%s' % \
-            md5(str(func.__name__) + '-' + \
-                '-'.join(map(str, params))).hexdigest()
         log.info('running task with lockkey %s', lockkey)
         try:
-            l = DaemonLock(lockkey)
+            l = DaemonLock(jn(lockkey_path, lockkey))
             ret = func(*fargs, **fkwargs)
             l.release()
             return ret
@@ -94,11 +107,3 @@
             return 'Task with key %s already running' % lockkey
 
     return decorator(__wrapper, func)
-
-
-
-
-
-
-
-
--- a/rhodecode/lib/celerylib/tasks.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/celerylib/tasks.py	Fri Oct 07 01:08:50 2011 +0200
@@ -5,10 +5,10 @@
 
     RhodeCode task modules, containing all task that suppose to be run
     by celery daemon
-    
+
     :created_on: Oct 6, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -28,20 +28,25 @@
 import os
 import traceback
 import logging
+from os.path import dirname as dn, join as jn
 
 from time import mktime
 from operator import itemgetter
+from string import lower
 
-from pylons import config
+from pylons import config, url
 from pylons.i18n.translation import _
 
-from rhodecode.lib.celerylib import run_task, locked_task, str2bool
+from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, safe_str
+from rhodecode.lib.celerylib import run_task, locked_task, str2bool, \
+    __get_lockkey, LockHeld, DaemonLock
 from rhodecode.lib.helpers import person
 from rhodecode.lib.smtp_mailer import SmtpMailer
-from rhodecode.lib.utils import OrderedDict, add_cache
+from rhodecode.lib.utils import add_cache
+from rhodecode.lib.odict import OrderedDict
 from rhodecode.model import init_model
 from rhodecode.model import meta
-from rhodecode.model.db import RhodeCodeUi
+from rhodecode.model.db import RhodeCodeUi, Statistics, Repository
 
 from vcs.backends import get_repo
 
@@ -60,6 +65,7 @@
 
 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
 
+
 def get_session():
     if CELERY_ON:
         engine = engine_from_config(config, 'sqlalchemy.db1.')
@@ -67,11 +73,13 @@
     sa = meta.Session()
     return sa
 
+
 def get_repos_path():
     sa = get_session()
     q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
     return q.ui_value
 
+
 @task(ignore_result=True)
 @locked_task
 def whoosh_index(repo_location, full_index):
@@ -82,143 +90,202 @@
                          repo_location=repo_location, sa=get_session())\
                          .run(full_index=full_index)
 
+
 @task(ignore_result=True)
-@locked_task
 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
     try:
         log = get_commits_stats.get_logger()
     except:
         log = logging.getLogger(__name__)
 
-    from rhodecode.model.db import Statistics, Repository
+    lockkey = __get_lockkey('get_commits_stats', repo_name, ts_min_y,
+                            ts_max_y)
+    lockkey_path = dn(dn(dn(dn(os.path.abspath(__file__)))))
+    log.info('running task with lockkey %s', lockkey)
+    try:
+        lock = l = DaemonLock(jn(lockkey_path, lockkey))
 
-    #for js data compatibilty
-    author_key_cleaner = lambda k: person(k).replace('"', "")
+        #for js data compatibilty cleans the key for person from '
+        akc = lambda k: person(k).replace('"', "")
 
-    commits_by_day_author_aggregate = {}
-    commits_by_day_aggregate = {}
-    repos_path = get_repos_path()
-    p = os.path.join(repos_path, repo_name)
-    repo = get_repo(p)
+        co_day_auth_aggr = {}
+        commits_by_day_aggregate = {}
+        repos_path = get_repos_path()
+        repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
+        repo_size = len(repo.revisions)
+        #return if repo have no revisions
+        if repo_size < 1:
+            lock.release()
+            return True
 
-    skip_date_limit = True
-    parse_limit = 250 #limit for single task changeset parsing optimal for
-    last_rev = 0
-    last_cs = None
-    timegetter = itemgetter('time')
+        skip_date_limit = True
+        parse_limit = int(config['app_conf'].get('commit_parse_limit'))
+        last_rev = 0
+        last_cs = None
+        timegetter = itemgetter('time')
 
-    sa = get_session()
+        sa = get_session()
 
-    dbrepo = sa.query(Repository)\
-        .filter(Repository.repo_name == repo_name).scalar()
-    cur_stats = sa.query(Statistics)\
-        .filter(Statistics.repository == dbrepo).scalar()
-    if cur_stats:
-        last_rev = cur_stats.stat_on_revision
-    if not repo.revisions:
-        return True
+        dbrepo = sa.query(Repository)\
+            .filter(Repository.repo_name == repo_name).scalar()
+        cur_stats = sa.query(Statistics)\
+            .filter(Statistics.repository == dbrepo).scalar()
 
-    if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
-        #pass silently without any work if we're not on first revision or 
-        #current state of parsing revision(from db marker) is the last revision
-        return True
+        if cur_stats is not None:
+            last_rev = cur_stats.stat_on_revision
+
+        if last_rev == repo.get_changeset().revision and repo_size > 1:
+            #pass silently without any work if we're not on first revision or
+            #current state of parsing revision(from db marker) is the
+            #last revision
+            lock.release()
+            return True
 
-    if cur_stats:
-        commits_by_day_aggregate = OrderedDict(
-                                       json.loads(
+        if cur_stats:
+            commits_by_day_aggregate = OrderedDict(json.loads(
                                         cur_stats.commit_activity_combined))
-        commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
+            co_day_auth_aggr = json.loads(cur_stats.commit_activity)
 
-    log.debug('starting parsing %s', parse_limit)
-    lmktime = mktime
+        log.debug('starting parsing %s', parse_limit)
+        lmktime = mktime
+
+        last_rev = last_rev + 1 if last_rev > 0 else last_rev
 
-    last_rev = last_rev + 1 if last_rev > 0 else last_rev
-    for rev in repo.revisions[last_rev:last_rev + parse_limit]:
-        last_cs = cs = repo.get_changeset(rev)
-        k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
-                      cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
+        for cs in repo[last_rev:last_rev + parse_limit]:
+            last_cs = cs  # remember last parsed changeset
+            k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
+                          cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
 
-        if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
-            try:
-                l = [timegetter(x) for x in commits_by_day_author_aggregate\
-                        [author_key_cleaner(cs.author)]['data']]
-                time_pos = l.index(k)
-            except ValueError:
-                time_pos = False
+            if akc(cs.author) in co_day_auth_aggr:
+                try:
+                    l = [timegetter(x) for x in
+                         co_day_auth_aggr[akc(cs.author)]['data']]
+                    time_pos = l.index(k)
+                except ValueError:
+                    time_pos = False
+
+                if time_pos >= 0 and time_pos is not False:
+
+                    datadict = \
+                        co_day_auth_aggr[akc(cs.author)]['data'][time_pos]
 
-            if time_pos >= 0 and time_pos is not False:
+                    datadict["commits"] += 1
+                    datadict["added"] += len(cs.added)
+                    datadict["changed"] += len(cs.changed)
+                    datadict["removed"] += len(cs.removed)
 
-                datadict = commits_by_day_author_aggregate\
-                    [author_key_cleaner(cs.author)]['data'][time_pos]
+                else:
+                    if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
 
-                datadict["commits"] += 1
-                datadict["added"] += len(cs.added)
-                datadict["changed"] += len(cs.changed)
-                datadict["removed"] += len(cs.removed)
+                        datadict = {"time": k,
+                                    "commits": 1,
+                                    "added": len(cs.added),
+                                    "changed": len(cs.changed),
+                                    "removed": len(cs.removed),
+                                   }
+                        co_day_auth_aggr[akc(cs.author)]['data']\
+                            .append(datadict)
 
             else:
                 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
+                    co_day_auth_aggr[akc(cs.author)] = {
+                                        "label": akc(cs.author),
+                                        "data": [{"time":k,
+                                                 "commits":1,
+                                                 "added":len(cs.added),
+                                                 "changed":len(cs.changed),
+                                                 "removed":len(cs.removed),
+                                                 }],
+                                        "schema": ["commits"],
+                                        }
 
-                    datadict = {"time":k,
-                                "commits":1,
-                                "added":len(cs.added),
-                                "changed":len(cs.changed),
-                                "removed":len(cs.removed),
-                               }
-                    commits_by_day_author_aggregate\
-                        [author_key_cleaner(cs.author)]['data'].append(datadict)
+            #gather all data by day
+            if k in commits_by_day_aggregate:
+                commits_by_day_aggregate[k] += 1
+            else:
+                commits_by_day_aggregate[k] = 1
 
-        else:
-            if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
-                commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
-                                    "label":author_key_cleaner(cs.author),
-                                    "data":[{"time":k,
-                                             "commits":1,
-                                             "added":len(cs.added),
-                                             "changed":len(cs.changed),
-                                             "removed":len(cs.removed),
-                                             }],
-                                    "schema":["commits"],
-                                    }
+        overview_data = sorted(commits_by_day_aggregate.items(),
+                               key=itemgetter(0))
+
+        if not co_day_auth_aggr:
+            co_day_auth_aggr[akc(repo.contact)] = {
+                "label": akc(repo.contact),
+                "data": [0, 1],
+                "schema": ["commits"],
+            }
+
+        stats = cur_stats if cur_stats else Statistics()
+        stats.commit_activity = json.dumps(co_day_auth_aggr)
+        stats.commit_activity_combined = json.dumps(overview_data)
+
+        log.debug('last revison %s', last_rev)
+        leftovers = len(repo.revisions[last_rev:])
+        log.debug('revisions to parse %s', leftovers)
 
-        #gather all data by day
-        if commits_by_day_aggregate.has_key(k):
-            commits_by_day_aggregate[k] += 1
-        else:
-            commits_by_day_aggregate[k] = 1
+        if last_rev == 0 or leftovers < parse_limit:
+            log.debug('getting code trending stats')
+            stats.languages = json.dumps(__get_codes_stats(repo_name))
 
-    overview_data = sorted(commits_by_day_aggregate.items(), key=itemgetter(0))
-    if not commits_by_day_author_aggregate:
-        commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
-            "label":author_key_cleaner(repo.contact),
-            "data":[0, 1],
-            "schema":["commits"],
-        }
+        try:
+            stats.repository = dbrepo
+            stats.stat_on_revision = last_cs.revision if last_cs else 0
+            sa.add(stats)
+            sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            sa.rollback()
+            lock.release()
+            return False
+
+        #final release
+        lock.release()
 
-    stats = cur_stats if cur_stats else Statistics()
-    stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
-    stats.commit_activity_combined = json.dumps(overview_data)
+        #execute another task if celery is enabled
+        if len(repo.revisions) > 1 and CELERY_ON:
+            run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
+        return True
+    except LockHeld:
+        log.info('LockHeld')
+        return 'Task with key %s already running' % lockkey
 
-    log.debug('last revison %s', last_rev)
-    leftovers = len(repo.revisions[last_rev:])
-    log.debug('revisions to parse %s', leftovers)
+@task(ignore_result=True)
+def send_password_link(user_email):
+    try:
+        log = reset_user_password.get_logger()
+    except:
+        log = logging.getLogger(__name__)
 
-    if last_rev == 0 or leftovers < parse_limit:
-        log.debug('getting code trending stats')
-        stats.languages = json.dumps(__get_codes_stats(repo_name))
-
-    stats.repository = dbrepo
-    stats.stat_on_revision = last_cs.revision if last_cs else 0
+    from rhodecode.lib import auth
+    from rhodecode.model.db import User
 
     try:
-        sa.add(stats)
-        sa.commit()
+        sa = get_session()
+        user = sa.query(User).filter(User.email == user_email).scalar()
+
+        if user:
+            link = url('reset_password_confirmation', key=user.api_key,
+                       qualified=True)
+            tmpl = """
+Hello %s
+
+We received a request to create a new password for your account.
+
+You can generate it by clicking following URL:
+
+%s
+
+If you didn't request new password please ignore this email.
+            """
+            run_task(send_email, user_email,
+                     "RhodeCode password reset link",
+                     tmpl % (user.short_contact, link))
+            log.info('send new password mail to %s', user_email)
+
     except:
+        log.error('Failed to update user password')
         log.error(traceback.format_exc())
-        sa.rollback()
         return False
-    if len(repo.revisions) > 1:
-        run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
 
     return True
 
@@ -240,6 +307,7 @@
                              auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
             if user:
                 user.password = auth.get_crypt_password(new_passwd)
+                user.api_key = auth.generate_api_key(user.username)
                 sa.add(user)
                 sa.commit()
                 log.info('change password for %s', user_email)
@@ -251,23 +319,22 @@
             sa.rollback()
 
         run_task(send_email, user_email,
-                 "Your new rhodecode password",
-                 'Your new rhodecode password:%s' % (new_passwd))
+                 "Your new RhodeCode password",
+                 'Your new RhodeCode password:%s' % (new_passwd))
         log.info('send new password mail to %s', user_email)
 
-
     except:
         log.error('Failed to update user password')
         log.error(traceback.format_exc())
 
     return True
 
+
 @task(ignore_result=True)
 def send_email(recipients, subject, body):
     """
     Sends an email with defined parameters from the .ini files.
-    
-    
+
     :param recipients: list of recipients, it this is empty the defined email
         address from field 'email_to' is used instead
     :param subject: subject of the mail
@@ -290,10 +357,11 @@
     mail_port = email_config.get('smtp_port')
     tls = str2bool(email_config.get('smtp_use_tls'))
     ssl = str2bool(email_config.get('smtp_use_ssl'))
+    debug = str2bool(config.get('debug'))
 
     try:
         m = SmtpMailer(mail_from, user, passwd, mail_server,
-                       mail_port, ssl, tls)
+                       mail_port, ssl, tls, debug=debug)
         m.send(recipients, subject, body)
     except:
         log.error('Mail sending failed')
@@ -301,16 +369,17 @@
         return False
     return True
 
+
 @task(ignore_result=True)
 def create_repo_fork(form_data, cur_user):
+    from rhodecode.model.repo import RepoModel
+    from vcs import get_backend
+
     try:
         log = create_repo_fork.get_logger()
     except:
         log = logging.getLogger(__name__)
 
-    from rhodecode.model.repo import RepoModel
-    from vcs import get_backend
-
     repo_model = RepoModel(get_session())
     repo_model.create(form_data, cur_user, just_db=True, fork=True)
     repo_name = form_data['repo_name']
@@ -323,81 +392,22 @@
     backend = get_backend(alias)
     backend(str(repo_fork_path), create=True, src_url=str(repo_path))
 
+
 def __get_codes_stats(repo_name):
-    LANGUAGES_EXTENSIONS_MAP = {'scm': 'Scheme', 'asmx': 'VbNetAspx', 'Rout':
-    'RConsole', 'rest': 'Rst', 'abap': 'ABAP', 'go': 'Go', 'phtml': 'HtmlPhp',
-    'ns2': 'Newspeak', 'xml': 'EvoqueXml', 'sh-session': 'BashSession', 'ads':
-    'Ada', 'clj': 'Clojure', 'll': 'Llvm', 'ebuild': 'Bash', 'adb': 'Ada',
-    'ada': 'Ada', 'c++-objdump': 'CppObjdump', 'aspx':
-    'VbNetAspx', 'ksh': 'Bash', 'coffee': 'CoffeeScript', 'vert': 'GLShader',
-    'Makefile.*': 'Makefile', 'di': 'D', 'dpatch': 'DarcsPatch', 'rake':
-    'Ruby', 'moo': 'MOOCode', 'erl-sh': 'ErlangShell', 'geo': 'GLShader',
-    'pov': 'Povray', 'bas': 'VbNet', 'bat': 'Batch', 'd': 'D', 'lisp':
-    'CommonLisp', 'h': 'C', 'rbx': 'Ruby', 'tcl': 'Tcl', 'c++': 'Cpp', 'md':
-    'MiniD', '.vimrc': 'Vim', 'xsd': 'Xml', 'ml': 'Ocaml', 'el': 'CommonLisp',
-    'befunge': 'Befunge', 'xsl': 'Xslt', 'pyx': 'Cython', 'cfm':
-    'ColdfusionHtml', 'evoque': 'Evoque', 'cfg': 'Ini', 'htm': 'Html',
-    'Makefile': 'Makefile', 'cfc': 'ColdfusionHtml', 'tex': 'Tex', 'cs':
-    'CSharp', 'mxml': 'Mxml', 'patch': 'Diff', 'apache.conf': 'ApacheConf',
-    'scala': 'Scala', 'applescript': 'AppleScript', 'GNUmakefile': 'Makefile',
-    'c-objdump': 'CObjdump', 'lua': 'Lua', 'apache2.conf': 'ApacheConf', 'rb':
-    'Ruby', 'gemspec': 'Ruby', 'rl': 'RagelObjectiveC', 'vala': 'Vala', 'tmpl':
-    'Cheetah', 'bf': 'Brainfuck', 'plt': 'Gnuplot', 'G': 'AntlrRuby', 'xslt':
-    'Xslt', 'flxh': 'Felix', 'asax': 'VbNetAspx', 'Rakefile': 'Ruby', 'S': 'S',
-    'wsdl': 'Xml', 'js': 'Javascript', 'autodelegate': 'Myghty', 'properties':
-    'Ini', 'bash': 'Bash', 'c': 'C', 'g': 'AntlrRuby', 'r3': 'Rebol', 's':
-    'Gas', 'ashx': 'VbNetAspx', 'cxx': 'Cpp', 'boo': 'Boo', 'prolog': 'Prolog',
-    'sqlite3-console': 'SqliteConsole', 'cl': 'CommonLisp', 'cc': 'Cpp', 'pot':
-    'Gettext', 'vim': 'Vim', 'pxi': 'Cython', 'yaml': 'Yaml', 'SConstruct':
-    'Python', 'diff': 'Diff', 'txt': 'Text', 'cw': 'Redcode', 'pxd': 'Cython',
-    'plot': 'Gnuplot', 'java': 'Java', 'hrl': 'Erlang', 'py': 'Python',
-    'makefile': 'Makefile', 'squid.conf': 'SquidConf', 'asm': 'Nasm', 'toc':
-    'Tex', 'kid': 'Genshi', 'rhtml': 'Rhtml', 'po': 'Gettext', 'pl': 'Prolog',
-    'pm': 'Perl', 'hx': 'Haxe', 'ascx': 'VbNetAspx', 'ooc': 'Ooc', 'asy':
-    'Asymptote', 'hs': 'Haskell', 'SConscript': 'Python', 'pytb':
-    'PythonTraceback', 'myt': 'Myghty', 'hh': 'Cpp', 'R': 'S', 'aux': 'Tex',
-    'rst': 'Rst', 'cpp-objdump': 'CppObjdump', 'lgt': 'Logtalk', 'rss': 'Xml',
-    'flx': 'Felix', 'b': 'Brainfuck', 'f': 'Fortran', 'rbw': 'Ruby',
-    '.htaccess': 'ApacheConf', 'cxx-objdump': 'CppObjdump', 'j': 'ObjectiveJ',
-    'mll': 'Ocaml', 'yml': 'Yaml', 'mu': 'MuPAD', 'r': 'Rebol', 'ASM': 'Nasm',
-    'erl': 'Erlang', 'mly': 'Ocaml', 'mo': 'Modelica', 'def': 'Modula2', 'ini':
-    'Ini', 'control': 'DebianControl', 'vb': 'VbNet', 'vapi': 'Vala', 'pro':
-    'Prolog', 'spt': 'Cheetah', 'mli': 'Ocaml', 'as': 'ActionScript3', 'cmd':
-    'Batch', 'cpp': 'Cpp', 'io': 'Io', 'tac': 'Python', 'haml': 'Haml', 'rkt':
-    'Racket', 'st':'Smalltalk', 'inc': 'Povray', 'pas': 'Delphi', 'cmake':
-    'CMake', 'csh':'Tcsh', 'hpp': 'Cpp', 'feature': 'Gherkin', 'html': 'Html',
-    'php':'Php', 'php3':'Php', 'php4':'Php', 'php5':'Php', 'xhtml': 'Html',
-    'hxx': 'Cpp', 'eclass': 'Bash', 'css': 'Css',
-    'frag': 'GLShader', 'd-objdump': 'DObjdump', 'weechatlog': 'IrcLogs',
-    'tcsh': 'Tcsh', 'objdump': 'Objdump', 'pyw': 'Python', 'h++': 'Cpp',
-    'py3tb': 'Python3Traceback', 'jsp': 'Jsp', 'sql': 'Sql', 'mak': 'Makefile',
-    'php': 'Php', 'mao': 'Mako', 'man': 'Groff', 'dylan': 'Dylan', 'sass':
-    'Sass', 'cfml': 'ColdfusionHtml', 'darcspatch': 'DarcsPatch', 'tpl':
-    'Smarty', 'm': 'ObjectiveC', 'f90': 'Fortran', 'mod': 'Modula2', 'sh':
-    'Bash', 'lhs': 'LiterateHaskell', 'sources.list': 'SourcesList', 'axd':
-    'VbNetAspx', 'sc': 'Python'}
-
     repos_path = get_repos_path()
-    p = os.path.join(repos_path, repo_name)
-    repo = get_repo(p)
+    repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
     tip = repo.get_changeset()
     code_stats = {}
 
     def aggregate(cs):
         for f in cs[2]:
-            ext = f.extension
-            key = LANGUAGES_EXTENSIONS_MAP.get(ext, ext)
-            key = key or ext
+            ext = lower(f.extension)
             if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
-                if code_stats.has_key(key):
-                    code_stats[key] += 1
+                if ext in code_stats:
+                    code_stats[ext] += 1
                 else:
-                    code_stats[key] = 1
+                    code_stats[ext] = 1
 
     map(aggregate, tip.walk('/'))
 
     return code_stats or {}
-
-
-
-
--- a/rhodecode/lib/colored_formatter.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/colored_formatter.py	Fri Oct 07 01:08:50 2011 +0200
@@ -5,18 +5,19 @@
 
 # Sequences
 RESET_SEQ = "\033[0m"
-COLOR_SEQ = "\033[1;%dm"
+COLOR_SEQ = "\033[0;%dm"
 BOLD_SEQ = "\033[1m"
 
 COLORS = {
-    'CRITICAL': MAGENTA, # level 50
-    'ERROR': RED, # level 40
-    'WARNING': CYAN, # level 30
-    'INFO': GREEN, # level 20
-    'DEBUG': BLUE, # level 10
-    'SQL' : YELLOW
+    'CRITICAL': MAGENTA,
+    'ERROR': RED,
+    'WARNING': CYAN,
+    'INFO': GREEN,
+    'DEBUG': BLUE,
+    'SQL': YELLOW
 }
 
+
 def one_space_trim(s):
     if s.find("  ") == -1:
         return s
@@ -24,6 +25,7 @@
         s = s.replace('  ', ' ')
         return one_space_trim(s)
 
+
 def format_sql(sql):
     sql = sql.replace('\n', '')
     sql = one_space_trim(sql)
@@ -43,6 +45,7 @@
         .replace('DELETE', '\n\tDELETE')
     return sql
 
+
 class ColorFormatter(logging.Formatter):
 
     def __init__(self, *args, **kwargs):
@@ -59,7 +62,7 @@
         def_record = logging.Formatter.format(self, record)
         end = RESET_SEQ
 
-        colored_record = start + def_record + end
+        colored_record = ''.join([start, def_record, end])
         return colored_record
 
 
@@ -78,5 +81,5 @@
         def_record = format_sql(logging.Formatter.format(self, record))
         end = RESET_SEQ
 
-        colored_record = start + def_record + end
+        colored_record = ''.join([start, def_record, end])
         return colored_record
--- a/rhodecode/lib/db_manage.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/db_manage.py	Fri Oct 07 01:08:50 2011 +0200
@@ -33,7 +33,7 @@
 from rhodecode import __dbversion__
 from rhodecode.model import meta
 
-from rhodecode.lib.auth import get_crypt_password
+from rhodecode.lib.auth import get_crypt_password, generate_api_key
 from rhodecode.lib.utils import ask_ok
 from rhodecode.model import init_model
 from rhodecode.model.db import User, Permission, RhodeCodeUi, \
@@ -115,7 +115,7 @@
             msg = ('Found current database under version'
                  ' control with version %s' % curr_version)
 
-        except (RuntimeError, DatabaseNotControlledError), e:
+        except (RuntimeError, DatabaseNotControlledError):
             curr_version = 1
             msg = ('Current database is not under version control. Setting'
                    ' as version %s' % curr_version)
@@ -157,6 +157,12 @@
                 log.info('Changing ui settings')
                 self.klass.create_ui_settings()
 
+            def step_3(self):
+                print ('Adding additional settings into RhodeCode db')
+                self.klass.fix_settings()
+                print ('Adding ldap defaults')
+                self.klass.create_ldap_options(skip_existing=True)
+                
         upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
 
         #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
@@ -200,6 +206,19 @@
             self.sa.rollback()
             raise
 
+    def fix_settings(self):
+        """Fixes rhodecode settings adds ga_code key for google analytics
+        """
+
+        hgsettings3 = RhodeCodeSettings('ga_code', '')
+
+        try:
+            self.sa.add(hgsettings3)
+            self.sa.commit()
+        except:
+            self.sa.rollback()
+            raise
+
     def admin_prompt(self, second=False):
         if not self.tests:
             import getpass
@@ -244,7 +263,7 @@
 
         """
         #HOOKS
-        hooks1_key = 'changegroup.update'
+        hooks1_key = RhodeCodeUi.HOOK_UPDATE
         hooks1_ = self.sa.query(RhodeCodeUi)\
             .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
 
@@ -254,7 +273,7 @@
         hooks1.ui_value = 'hg update >&2'
         hooks1.ui_active = False
 
-        hooks2_key = 'changegroup.repo_size'
+        hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE
         hooks2_ = self.sa.query(RhodeCodeUi)\
             .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
 
@@ -265,12 +284,12 @@
 
         hooks3 = RhodeCodeUi()
         hooks3.ui_section = 'hooks'
-        hooks3.ui_key = 'pretxnchangegroup.push_logger'
+        hooks3.ui_key = RhodeCodeUi.HOOK_PUSH
         hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
 
         hooks4 = RhodeCodeUi()
         hooks4.ui_section = 'hooks'
-        hooks4.ui_key = 'preoutgoing.pull_logger'
+        hooks4.ui_key = RhodeCodeUi.HOOK_PULL
         hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
 
         #For mercurial 1.7 set backward comapatibility with format
@@ -290,17 +309,21 @@
             self.sa.rollback()
             raise
 
-    def create_ldap_options(self):
+    def create_ldap_options(self,skip_existing=False):
         """Creates ldap settings"""
 
         try:
-            for k, v in [('ldap_active', 'false'),
-                        ('ldap_host', ''),
-                        ('ldap_port', '389'),
-                        ('ldap_ldaps', 'false'),
-                        ('ldap_dn_user', ''), ('ldap_dn_pass', ''),
-                        ('ldap_base_dn', '')]:
+            for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
+                        ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
+                        ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
+                        ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
+                        ('ldap_filter', ''), ('ldap_search_scope', ''),
+                        ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
+                        ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:
 
+                if skip_existing and RhodeCodeSettings.get_by_name(k) != None:
+                    log.debug('Skipping option %s' % k)
+                    continue
                 setting = RhodeCodeSettings(k, v)
                 self.sa.add(setting)
             self.sa.commit()
@@ -322,18 +345,16 @@
         #check proper dir
         if not os.path.isdir(path):
             path_ok = False
-            log.error('Entered path is not a valid directory: %s [%s/3]',
-                      path, retries)
+            log.error('Given path %s is not a valid directory', path)
 
         #check write access
-        if not os.access(path, os.W_OK):
+        if not os.access(path, os.W_OK) and path_ok:
             path_ok = False
+            log.error('No write permission to given path %s', path)
 
-            log.error('No write permission to given path: %s [%s/3]',
-                      path, retries)
 
         if retries == 0:
-            sys.exit()
+            sys.exit('max retries reached')
         if path_ok is False:
             retries -= 1
             return self.config_prompt(test_repo_path, retries)
@@ -372,6 +393,7 @@
 
         hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
         hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
+        hgsettings3 = RhodeCodeSettings('ga_code', '')
 
         try:
             self.sa.add(web1)
@@ -381,6 +403,7 @@
             self.sa.add(paths)
             self.sa.add(hgsettings1)
             self.sa.add(hgsettings2)
+            self.sa.add(hgsettings3)
 
             self.sa.commit()
         except:
@@ -393,40 +416,30 @@
 
     def create_user(self, username, password, email='', admin=False):
         log.info('creating administrator user %s', username)
-        new_user = User()
-        new_user.username = username
-        new_user.password = get_crypt_password(password)
-        new_user.name = 'RhodeCode'
-        new_user.lastname = 'Admin'
-        new_user.email = email
-        new_user.admin = admin
-        new_user.active = True
+        
+        form_data = dict(username=username,
+                         password=password,
+                         active=True,
+                         admin=admin,
+                         name='RhodeCode',
+                         lastname='Admin',
+                         email=email)
+        User.create(form_data)
 
-        try:
-            self.sa.add(new_user)
-            self.sa.commit()
-        except:
-            self.sa.rollback()
-            raise
 
     def create_default_user(self):
         log.info('creating default user')
         #create default user for handling default permissions.
-        def_user = User()
-        def_user.username = 'default'
-        def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
-        def_user.name = 'Anonymous'
-        def_user.lastname = 'User'
-        def_user.email = 'anonymous@rhodecode.org'
-        def_user.admin = False
-        def_user.active = False
-        try:
-            self.sa.add(def_user)
-            self.sa.commit()
-        except:
-            self.sa.rollback()
-            raise
 
+        form_data = dict(username='default',
+                         password=str(uuid.uuid1())[:8],
+                         active=False,
+                         admin=False,
+                         name='Anonymous',
+                         lastname='User',
+                         email='anonymous@rhodecode.org')
+        User.create(form_data)
+        
     def create_permissions(self):
         #module.(access|create|change|delete)_[name]
         #module.(read|write|owner)
@@ -438,12 +451,13 @@
                  ('hg.create.repository', 'Repository create'),
                  ('hg.create.none', 'Repository creation disabled'),
                  ('hg.register.none', 'Register disabled'),
-                 ('hg.register.manual_activate', ('Register new user with '
-                                                  'RhodeCode without '
-                                                  'manual activation')),
-                 ('hg.register.auto_activate', ('Register new user with '
-                                                'RhodeCode without auto '
-                                                'activation')),
+                 ('hg.register.manual_activate', 'Register new user with '
+                                                 'RhodeCode without manual'
+                                                 'activation'),
+
+                 ('hg.register.auto_activate', 'Register new user with '
+                                               'RhodeCode without auto '
+                                               'activation'),
                 ]
 
         for p in perms:
--- a/rhodecode/lib/dbmigrate/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,12 +2,12 @@
 """
     rhodecode.lib.dbmigrate.__init__
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-    
+
     Database migration modules
-    
+
     :created_on: Dec 11, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -32,6 +32,7 @@
 
 log = logging.getLogger(__name__)
 
+
 class UpgradeDb(BasePasterCommand):
     """Command used for paster to upgrade our database to newer version
     """
@@ -57,8 +58,6 @@
 
         dbmanage.upgrade()
 
-
-
     def update_parser(self):
         self.parser.add_option('--sql',
                       action='store_true',
--- a/rhodecode/lib/dbmigrate/migrate/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -7,3 +7,5 @@
 
 from rhodecode.lib.dbmigrate.migrate.versioning import *
 from rhodecode.lib.dbmigrate.migrate.changeset import *
+
+__version__ = '0.7.2.dev'
\ No newline at end of file
--- a/rhodecode/lib/dbmigrate/migrate/changeset/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/changeset/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -12,8 +12,10 @@
 
 warnings.simplefilter('always', DeprecationWarning)
 
-_sa_version = tuple(int(re.match("\d+", x).group(0)) for x in _sa_version.split("."))
+_sa_version = tuple(int(re.match("\d+", x).group(0)) 
+                    for x in _sa_version.split("."))
 SQLA_06 = _sa_version >= (0, 6)
+SQLA_07 = _sa_version >= (0, 7)
 
 del re
 del _sa_version
@@ -21,8 +23,8 @@
 from rhodecode.lib.dbmigrate.migrate.changeset.schema import *
 from rhodecode.lib.dbmigrate.migrate.changeset.constraint import *
 
-sqlalchemy.schema.Table.__bases__ += (ChangesetTable, )
-sqlalchemy.schema.Column.__bases__ += (ChangesetColumn, )
-sqlalchemy.schema.Index.__bases__ += (ChangesetIndex, )
+sqlalchemy.schema.Table.__bases__ += (ChangesetTable,)
+sqlalchemy.schema.Column.__bases__ += (ChangesetColumn,)
+sqlalchemy.schema.Index.__bases__ += (ChangesetIndex,)
 
-sqlalchemy.schema.DefaultClause.__bases__ += (ChangesetDefaultClause, )
+sqlalchemy.schema.DefaultClause.__bases__ += (ChangesetDefaultClause,)
--- a/rhodecode/lib/dbmigrate/migrate/changeset/ansisql.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/changeset/ansisql.py	Fri Oct 07 01:08:50 2011 +0200
@@ -59,7 +59,7 @@
             # adapt to 0.6 which uses a string-returning
             # object
             self.append(" %s" % ret)
-            
+
     def _to_table(self, param):
         """Returns the table object for the given param object."""
         if isinstance(param, (sa.Column, sa.Index, sa.schema.Constraint)):
@@ -297,10 +297,10 @@
 
         def get_constraint_specification(self, cons, **kwargs):
             """Constaint SQL generators.
-        
+
             We cannot use SA visitors because they append comma.
             """
-        
+
             if isinstance(cons, PrimaryKeyConstraint):
                 if cons.name is not None:
                     self.append("CONSTRAINT %s " % self.preparer.format_constraint(cons))
@@ -327,13 +327,13 @@
                 raise exceptions.InvalidConstraintError(cons)
 
         def _visit_constraint(self, constraint):
-        
+
             table = self.start_alter_table(constraint)
             constraint.name = self.get_constraint_name(constraint)
             self.append("ADD ")
             self.get_constraint_specification(constraint)
             self.execute()
-    
+
 
     class ANSIConstraintDropper(ANSIConstraintCommon, SchemaDropper):
 
--- a/rhodecode/lib/dbmigrate/migrate/changeset/constraint.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/changeset/constraint.py	Fri Oct 07 01:08:50 2011 +0200
@@ -28,7 +28,7 @@
     def __do_imports(self, visitor_name, *a, **kw):
         engine = kw.pop('engine', self.table.bind)
         from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor,
-                                                         run_single_visitor)
+                                                                                 run_single_visitor)
         visitorcallable = get_engine_visitor(engine, visitor_name)
         run_single_visitor(engine, visitorcallable, self, *a, **kw)
 
--- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/firebird.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/changeset/databases/firebird.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,7 +2,7 @@
    Firebird database specific implementations of changeset classes.
 """
 from sqlalchemy.databases import firebird as sa_base
-
+from sqlalchemy.schema import PrimaryKeyConstraint
 from rhodecode.lib.dbmigrate.migrate import exceptions
 from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
 
@@ -27,13 +27,32 @@
             if column.table.primary_key.columns.contains_column(column):
                 column.table.primary_key.drop()
                 # TODO: recreate primary key if it references more than this column
-        if column.unique or getattr(column, 'unique_name', None):
-            for cons in column.table.constraints:
-                if cons.contains_column(column):
-                    cons.drop()
-                    # TODO: recreate unique constraint if it refenrences more than this column
+
+        for index in column.table.indexes:
+            # "column in index.columns" causes problems as all
+            # column objects compare equal and return a SQL expression
+            if column.name in [col.name for col in index.columns]:
+                index.drop()
+                # TODO: recreate index if it references more than this column
 
-        table = self.start_alter_table(column)
+        for cons in column.table.constraints:
+            if isinstance(cons,PrimaryKeyConstraint):
+                # will be deleted only when the column its on
+                # is deleted!
+                continue
+
+            if SQLA_06:
+                should_drop = column.name in cons.columns
+            else:
+                should_drop = cons.contains_column(column) and cons.name
+            if should_drop:
+                self.start_alter_table(column)
+                self.append("DROP CONSTRAINT ")
+                self.append(self.preparer.format_constraint(cons))
+                self.execute()
+            # TODO: recreate unique constraint if it refenrences more than this column
+
+        self.start_alter_table(column)
         self.append('DROP %s' % self.preparer.format_column(column))
         self.execute()
 
--- a/rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py	Fri Oct 07 01:08:50 2011 +0200
@@ -44,7 +44,7 @@
         self.execute()
         self.append('DROP TABLE migration_tmp')
         self.execute()
-        
+
     def visit_column(self, delta):
         if isinstance(delta, DictMixin):
             column = delta.result_column
@@ -54,7 +54,7 @@
             table = self._to_table(column.table)
         self.recreate_table(table,column,delta)
 
-class SQLiteColumnGenerator(SQLiteSchemaGenerator, 
+class SQLiteColumnGenerator(SQLiteSchemaGenerator,
                             ansisql.ANSIColumnGenerator,
                             # at the end so we get the normal
                             # visit_column by default
@@ -80,10 +80,17 @@
     """SQLite ColumnDropper"""
 
     def _modify_table(self, table, column, delta):
+
         columns = ' ,'.join(map(self.preparer.format_column, table.columns))
         return 'INSERT INTO %(table_name)s SELECT ' + columns + \
             ' from migration_tmp'
 
+    def visit_column(self,column):
+        # For SQLite, we *have* to remove the column here so the table
+        # is re-created properly.
+        column.remove_from_table(column.table,unset_table=False)
+        super(SQLiteColumnDropper,self).visit_column(column)
+
 
 class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
     """SQLite SchemaChanger"""
--- a/rhodecode/lib/dbmigrate/migrate/changeset/schema.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/changeset/schema.py	Fri Oct 07 01:08:50 2011 +0200
@@ -11,9 +11,9 @@
 from sqlalchemy.schema import UniqueConstraint
 
 from rhodecode.lib.dbmigrate.migrate.exceptions import *
-from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_06
+from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_06, SQLA_07
 from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor,
-                                                 run_single_visitor)
+                                                                         run_single_visitor)
 
 
 __all__ = [
@@ -29,12 +29,9 @@
     'ColumnDelta',
 ]
 
-DEFAULT_ALTER_METADATA = True
-
-
 def create_column(column, table=None, *p, **kw):
     """Create a column, given the table.
-    
+
     API to :meth:`ChangesetColumn.create`.
     """
     if table is not None:
@@ -44,7 +41,7 @@
 
 def drop_column(column, table=None, *p, **kw):
     """Drop a column, given the table.
-    
+
     API to :meth:`ChangesetColumn.drop`.
     """
     if table is not None:
@@ -108,20 +105,12 @@
     :param engine:
       The :class:`~sqlalchemy.engine.base.Engine` to use for table
       reflection and schema alterations.
-    
-    :param alter_metadata:
-      If `True`, which is the default, the
-      :class:`~sqlalchemy.schema.Column` will also modified.
-      If `False`, the :class:`~sqlalchemy.schema.Column` will be left
-      as it was.
-    
+
     :returns: A :class:`ColumnDelta` instance representing the change.
 
-    
+
     """
 
-    k.setdefault('alter_metadata', DEFAULT_ALTER_METADATA)
-
     if 'table' not in k and isinstance(p[0], sqlalchemy.Column):
         k['table'] = p[0].table
     if 'engine' not in k:
@@ -135,6 +124,12 @@
             MigrateDeprecationWarning
             )
     engine = k['engine']
+
+    # enough tests seem to break when metadata is always altered
+    # that this crutch has to be left in until they can be sorted
+    # out
+    k['alter_metadata']=True
+
     delta = ColumnDelta(*p, **k)
 
     visitorcallable = get_engine_visitor(engine, 'schemachanger')
@@ -188,11 +183,10 @@
         :param table: Table at which current Column should be bound to.\
         If table name is given, reflection will be used.
         :type table: string or Table instance
-        :param alter_metadata: If True, it will apply changes to metadata.
-        :type alter_metadata: bool
-        :param metadata: If `alter_metadata` is true, \
-        metadata is used to reflect table names into
-        :type metadata: :class:`MetaData` instance
+
+        :param metadata: A :class:`MetaData` instance to store
+                         reflected table names
+
         :param engine: When reflecting tables, either engine or metadata must \
         be specified to acquire engine object.
         :type engine: :class:`Engine` instance
@@ -213,7 +207,11 @@
     __visit_name__ = 'column'
 
     def __init__(self, *p, **kw):
+        # 'alter_metadata' is not a public api. It exists purely
+        # as a crutch until the tests that fail when 'alter_metadata'
+        # behaviour always happens can be sorted out
         self.alter_metadata = kw.pop("alter_metadata", False)
+
         self.meta = kw.pop("metadata", None)
         self.engine = kw.pop("engine", None)
 
@@ -237,17 +235,19 @@
         self.apply_diffs(diffs)
 
     def __repr__(self):
-        return '<ColumnDelta altermetadata=%r, %s>' % (self.alter_metadata,
-            super(ColumnDelta, self).__repr__())
+        return '<ColumnDelta altermetadata=%r, %s>' % (
+            self.alter_metadata,
+            super(ColumnDelta, self).__repr__()
+            )
 
     def __getitem__(self, key):
         if key not in self.keys():
-            raise KeyError("No such diff key, available: %s" % self.diffs)
+            raise KeyError("No such diff key, available: %s" % self.diffs )
         return getattr(self.result_column, key)
 
     def __setitem__(self, key, value):
         if key not in self.keys():
-            raise KeyError("No such diff key, available: %s" % self.diffs)
+            raise KeyError("No such diff key, available: %s" % self.diffs )
         setattr(self.result_column, key, value)
 
     def __delitem__(self, key):
@@ -278,7 +278,7 @@
         """Compares two Column objects"""
         self.process_column(new_col)
         self.table = k.pop('table', None)
-        # we cannot use bool() on table in SA06 
+        # we cannot use bool() on table in SA06
         if self.table is None:
             self.table = old_col.table
         if self.table is None:
@@ -395,7 +395,6 @@
             self._table = table
             if not self.alter_metadata:
                 self._table.meta = sqlalchemy.MetaData(bind=self._table.bind)
-
     def _get_result_column(self):
         return getattr(self, '_result_column', None)
 
@@ -456,22 +455,18 @@
 
         :param name: New name of the table.
         :type name: string
-        :param alter_metadata: If True, table will be removed from metadata
-        :type alter_metadata: bool
         :param connection: reuse connection istead of creating new one.
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
         """
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         engine = self.bind
         self.new_name = name
         visitorcallable = get_engine_visitor(engine, 'schemachanger')
         run_single_visitor(engine, visitorcallable, self, connection, **kwargs)
 
         # Fix metadata registration
-        if self.alter_metadata:
-            self.name = name
-            self.deregister()
-            self._set_parent(self.metadata)
+        self.name = name
+        self.deregister()
+        self._set_parent(self.metadata)
 
     def _meta_key(self):
         return sqlalchemy.schema._get_table_key(self.name, self.schema)
@@ -489,7 +484,7 @@
 
     def alter(self, *p, **k):
         """Makes a call to :func:`alter_column` for the column this
-        method is called on. 
+        method is called on.
         """
         if 'table' not in k:
             k['table'] = self.table
@@ -510,7 +505,6 @@
 `~migrate.changeset.constraint.UniqueConstraint` on this column.
         :param primary_key_name: Creates :class:\
 `~migrate.changeset.constraint.PrimaryKeyConstraint` on this column.
-        :param alter_metadata: If True, column will be added to table object.
         :param populate_default: If True, created column will be \
 populated with defaults
         :param connection: reuse connection istead of creating new one.
@@ -518,22 +512,19 @@
         :type index_name: string
         :type unique_name: string
         :type primary_key_name: string
-        :type alter_metadata: bool
         :type populate_default: bool
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
 
         :returns: self
         """
         self.populate_default = populate_default
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         self.index_name = index_name
         self.unique_name = unique_name
         self.primary_key_name = primary_key_name
         for cons in ('index_name', 'unique_name', 'primary_key_name'):
             self._check_sanity_constraints(cons)
 
-        if self.alter_metadata:
-            self.add_to_table(table)
+        self.add_to_table(table)
         engine = self.table.bind
         visitorcallable = get_engine_visitor(engine, 'columngenerator')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
@@ -550,28 +541,26 @@
 
         ``ALTER TABLE DROP COLUMN``, for most databases.
 
-        :param alter_metadata: If True, column will be removed from table object.
-        :type alter_metadata: bool
         :param connection: reuse connection istead of creating new one.
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
         """
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         if table is not None:
             self.table = table
         engine = self.table.bind
-        if self.alter_metadata:
-            self.remove_from_table(self.table, unset_table=False)
         visitorcallable = get_engine_visitor(engine, 'columndropper')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
-        if self.alter_metadata:
-            self.table = None
+        self.remove_from_table(self.table, unset_table=False)
+        self.table = None
         return self
 
     def add_to_table(self, table):
         if table is not None  and self.table is None:
-            self._set_parent(table)
+            if SQLA_07:
+                table.append_column(self)
+            else:
+                self._set_parent(table)
 
-    def _col_name_in_constraint(self, cons, name):
+    def _col_name_in_constraint(self,cons,name):
         return False
 
     def remove_from_table(self, table, unset_table=True):
@@ -583,10 +572,10 @@
         for index in table.indexes:
             columns = []
             for col in index.columns:
-                if col.name != self.name:
+                if col.name!=self.name:
                     columns.append(col)
             if columns:
-                index.columns = columns
+                index.columns=columns
             else:
                 to_drop.add(index)
         table.indexes = table.indexes - to_drop
@@ -594,17 +583,20 @@
         to_drop = set()
         for cons in table.constraints:
             # TODO: deal with other types of constraint
-            if isinstance(cons, (ForeignKeyConstraint,
+            if isinstance(cons,(ForeignKeyConstraint,
                                 UniqueConstraint)):
                 for col_name in cons.columns:
-                    if not isinstance(col_name, basestring):
+                    if not isinstance(col_name,basestring):
                         col_name = col_name.name
-                    if self.name == col_name:
+                    if self.name==col_name:
                         to_drop.add(cons)
         table.constraints = table.constraints - to_drop
 
         if table.c.contains_column(self):
-            table.c.remove(self)
+            if SQLA_07:
+                table._columns.remove(self)
+            else:
+                table.c.remove(self)
 
     # TODO: this is fixed in 0.6
     def copy_fixed(self, **kw):
@@ -643,18 +635,14 @@
 
         :param name: New name of the Index.
         :type name: string
-        :param alter_metadata: If True, Index object will be altered.
-        :type alter_metadata: bool
         :param connection: reuse connection istead of creating new one.
         :type connection: :class:`sqlalchemy.engine.base.Connection` instance
         """
-        self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
         engine = self.table.bind
         self.new_name = name
         visitorcallable = get_engine_visitor(engine, 'schemachanger')
         engine._run_visitor(visitorcallable, self, connection, **kwargs)
-        if self.alter_metadata:
-            self.name = name
+        self.name = name
 
 
 class ChangesetDefaultClause(object):
--- a/rhodecode/lib/dbmigrate/migrate/exceptions.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/exceptions.py	Fri Oct 07 01:08:50 2011 +0200
@@ -83,5 +83,6 @@
 class InvalidConstraintError(Error):
     """Invalid constraint error"""
 
+
 class MigrateDeprecationWarning(DeprecationWarning):
     """Warning for deprecated features in Migrate"""
--- a/rhodecode/lib/dbmigrate/migrate/versioning/api.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/api.py	Fri Oct 07 01:08:50 2011 +0200
@@ -110,19 +110,19 @@
 
 
 @catch_known_errors
-def script_sql(database, repository, **opts):
-    """%prog script_sql DATABASE REPOSITORY_PATH
+def script_sql(database, description, repository, **opts):
+    """%prog script_sql DATABASE DESCRIPTION REPOSITORY_PATH
 
     Create empty change SQL scripts for given DATABASE, where DATABASE
-    is either specific ('postgres', 'mysql', 'oracle', 'sqlite', etc.)
+    is either specific ('postgresql', 'mysql', 'oracle', 'sqlite', etc.)
     or generic ('default').
 
-    For instance, manage.py script_sql postgres creates:
-    repository/versions/001_postgres_upgrade.sql and
-    repository/versions/001_postgres_postgres.sql
+    For instance, manage.py script_sql postgresql description creates:
+    repository/versions/001_description_postgresql_upgrade.sql and
+    repository/versions/001_description_postgresql_postgres.sql
     """
     repo = Repository(repository)
-    repo.create_script_sql(database, **opts)
+    repo.create_script_sql(database, description, **opts)
 
 
 def version(repository, **opts):
--- a/rhodecode/lib/dbmigrate/migrate/versioning/genmodel.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/genmodel.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,9 +1,9 @@
 """
-   Code to generate a Python model from a database or differences
-   between a model and database.
+Code to generate a Python model from a database or differences
+between a model and database.
 
-   Some of this is borrowed heavily from the AutoCode project at:
-   http://code.google.com/p/sqlautocode/
+Some of this is borrowed heavily from the AutoCode project at:
+http://code.google.com/p/sqlautocode/
 """
 
 import sys
@@ -14,6 +14,7 @@
 from rhodecode.lib.dbmigrate import migrate
 from rhodecode.lib.dbmigrate.migrate import changeset
 
+
 log = logging.getLogger(__name__)
 HEADER = """
 ## File autogenerated by genmodel.py
@@ -33,6 +34,13 @@
 
 
 class ModelGenerator(object):
+    """Various transformations from an A, B diff.
+
+    In the implementation, A tends to be called the model and B
+    the database (although this is not true of all diffs).
+    The diff is directionless, but transformations apply the diff
+    in a particular direction, described in the method name.
+    """
 
     def __init__(self, diff, engine, declarative=False):
         self.diff = diff
@@ -58,7 +66,7 @@
                 pass
             else:
                 kwarg.append('default')
-        ks = ', '.join('%s=%r' % (k, getattr(col, k)) for k in kwarg)
+        args = ['%s=%r' % (k, getattr(col, k)) for k in kwarg]
 
         # crs: not sure if this is good idea, but it gets rid of extra
         # u''
@@ -72,58 +80,59 @@
                     type_ = cls()
                 break
 
+        type_repr = repr(type_)
+        if type_repr.endswith('()'):
+            type_repr = type_repr[:-2]
+
+        constraints = [repr(cn) for cn in col.constraints]
+
         data = {
             'name': name,
-            'type': type_,
-            'constraints': ', '.join([repr(cn) for cn in col.constraints]),
-            'args': ks and ks or ''}
+            'commonStuff': ', '.join([type_repr] + constraints + args),
+        }
 
-        if data['constraints']:
-            if data['args']:
-                data['args'] = ',' + data['args']
-
-        if data['constraints'] or data['args']:
-            data['maybeComma'] = ','
+        if self.declarative:
+            return """%(name)s = Column(%(commonStuff)s)""" % data
         else:
-            data['maybeComma'] = ''
+            return """Column(%(name)r, %(commonStuff)s)""" % data
 
-        commonStuff = """ %(maybeComma)s %(constraints)s %(args)s)""" % data
-        commonStuff = commonStuff.strip()
-        data['commonStuff'] = commonStuff
-        if self.declarative:
-            return """%(name)s = Column(%(type)r%(commonStuff)s""" % data
-        else:
-            return """Column(%(name)r, %(type)r%(commonStuff)s""" % data
-
-    def getTableDefn(self, table):
+    def _getTableDefn(self, table, metaName='meta'):
         out = []
         tableName = table.name
         if self.declarative:
             out.append("class %(table)s(Base):" % {'table': tableName})
-            out.append("  __tablename__ = '%(table)s'" % {'table': tableName})
+            out.append("    __tablename__ = '%(table)s'\n" %
+                            {'table': tableName})
             for col in table.columns:
-                out.append("  %s" % self.column_repr(col))
+                out.append("    %s" % self.column_repr(col))
+            out.append('\n')
         else:
-            out.append("%(table)s = Table('%(table)s', meta," % \
-                           {'table': tableName})
+            out.append("%(table)s = Table('%(table)s', %(meta)s," %
+                       {'table': tableName, 'meta': metaName})
             for col in table.columns:
-                out.append("  %s," % self.column_repr(col))
-            out.append(")")
+                out.append("    %s," % self.column_repr(col))
+            out.append(")\n")
         return out
 
-    def _get_tables(self, missingA=False, missingB=False, modified=False):
+    def _get_tables(self,missingA=False,missingB=False,modified=False):
         to_process = []
-        for bool_, names, metadata in (
-            (missingA, self.diff.tables_missing_from_A, self.diff.metadataB),
-            (missingB, self.diff.tables_missing_from_B, self.diff.metadataA),
-            (modified, self.diff.tables_different, self.diff.metadataA),
+        for bool_,names,metadata in (
+            (missingA,self.diff.tables_missing_from_A,self.diff.metadataB),
+            (missingB,self.diff.tables_missing_from_B,self.diff.metadataA),
+            (modified,self.diff.tables_different,self.diff.metadataA),
                 ):
             if bool_:
                 for name in names:
                     yield metadata.tables.get(name)
 
-    def toPython(self):
-        """Assume database is current and model is empty."""
+    def genBDefinition(self):
+        """Generates the source code for a definition of B.
+
+        Assumes a diff where A is empty.
+
+        Was: toPython. Assume database (B) is current and model (A) is empty.
+        """
+
         out = []
         if self.declarative:
             out.append(DECLARATIVE_HEADER)
@@ -131,67 +140,89 @@
             out.append(HEADER)
         out.append("")
         for table in self._get_tables(missingA=True):
-            out.extend(self.getTableDefn(table))
-            out.append("")
+            out.extend(self._getTableDefn(table))
         return '\n'.join(out)
 
-    def toUpgradeDowngradePython(self, indent='    '):
-        ''' Assume model is most current and database is out-of-date. '''
-        decls = ['from rhodecode.lib.dbmigrate.migrate.changeset import schema',
-                 'meta = MetaData()']
-        for table in self._get_tables(
-            missingA=True, missingB=True, modified=True
-            ):
-            decls.extend(self.getTableDefn(table))
+    def genB2AMigration(self, indent='    '):
+        '''Generate a migration from B to A.
+
+        Was: toUpgradeDowngradePython
+        Assume model (A) is most current and database (B) is out-of-date.
+        '''
 
-        upgradeCommands, downgradeCommands = [], []
-        for tableName in self.diff.tables_missing_from_A:
-            upgradeCommands.append("%(table)s.drop()" % {'table': tableName})
-            downgradeCommands.append("%(table)s.create()" % \
-                                         {'table': tableName})
-        for tableName in self.diff.tables_missing_from_B:
-            upgradeCommands.append("%(table)s.create()" % {'table': tableName})
-            downgradeCommands.append("%(table)s.drop()" % {'table': tableName})
+        decls = ['from migrate.changeset import schema',
+                 'pre_meta = MetaData()',
+                 'post_meta = MetaData()',
+                ]
+        upgradeCommands = ['pre_meta.bind = migrate_engine',
+                           'post_meta.bind = migrate_engine']
+        downgradeCommands = list(upgradeCommands)
+
+        for tn in self.diff.tables_missing_from_A:
+            pre_table = self.diff.metadataB.tables[tn]
+            decls.extend(self._getTableDefn(pre_table, metaName='pre_meta'))
+            upgradeCommands.append(
+                "pre_meta.tables[%(table)r].drop()" % {'table': tn})
+            downgradeCommands.append(
+                "pre_meta.tables[%(table)r].create()" % {'table': tn})
 
-        for tableName in self.diff.tables_different:
-            dbTable = self.diff.metadataB.tables[tableName]
-            missingInDatabase, missingInModel, diffDecl = \
-                self.diff.colDiffs[tableName]
-            for col in missingInDatabase:
-                upgradeCommands.append('%s.columns[%r].create()' % (
-                        modelTable, col.name))
-                downgradeCommands.append('%s.columns[%r].drop()' % (
-                        modelTable, col.name))
-            for col in missingInModel:
-                upgradeCommands.append('%s.columns[%r].drop()' % (
-                        modelTable, col.name))
-                downgradeCommands.append('%s.columns[%r].create()' % (
-                        modelTable, col.name))
-            for modelCol, databaseCol, modelDecl, databaseDecl in diffDecl:
+        for tn in self.diff.tables_missing_from_B:
+            post_table = self.diff.metadataA.tables[tn]
+            decls.extend(self._getTableDefn(post_table, metaName='post_meta'))
+            upgradeCommands.append(
+                "post_meta.tables[%(table)r].create()" % {'table': tn})
+            downgradeCommands.append(
+                "post_meta.tables[%(table)r].drop()" % {'table': tn})
+
+        for (tn, td) in self.diff.tables_different.iteritems():
+            if td.columns_missing_from_A or td.columns_different:
+                pre_table = self.diff.metadataB.tables[tn]
+                decls.extend(self._getTableDefn(
+                    pre_table, metaName='pre_meta'))
+            if td.columns_missing_from_B or td.columns_different:
+                post_table = self.diff.metadataA.tables[tn]
+                decls.extend(self._getTableDefn(
+                    post_table, metaName='post_meta'))
+
+            for col in td.columns_missing_from_A:
                 upgradeCommands.append(
-                    'assert False, "Can\'t alter columns: %s:%s=>%s"',
-                    modelTable, modelCol.name, databaseCol.name)
+                    'pre_meta.tables[%r].columns[%r].drop()' % (tn, col))
+                downgradeCommands.append(
+                    'pre_meta.tables[%r].columns[%r].create()' % (tn, col))
+            for col in td.columns_missing_from_B:
+                upgradeCommands.append(
+                    'post_meta.tables[%r].columns[%r].create()' % (tn, col))
                 downgradeCommands.append(
-                    'assert False, "Can\'t alter columns: %s:%s=>%s"',
-                    modelTable, modelCol.name, databaseCol.name)
-        pre_command = '    meta.bind = migrate_engine'
+                    'post_meta.tables[%r].columns[%r].drop()' % (tn, col))
+            for modelCol, databaseCol, modelDecl, databaseDecl in td.columns_different:
+                upgradeCommands.append(
+                    'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
+                    tn, modelCol.name, databaseCol.name))
+                downgradeCommands.append(
+                    'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
+                    tn, modelCol.name, databaseCol.name))
 
         return (
             '\n'.join(decls),
-            '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in upgradeCommands]),
-            '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in downgradeCommands]))
+            '\n'.join('%s%s' % (indent, line) for line in upgradeCommands),
+            '\n'.join('%s%s' % (indent, line) for line in downgradeCommands))
 
-    def _db_can_handle_this_change(self, td):
+    def _db_can_handle_this_change(self,td):
+        """Check if the database can handle going from B to A."""
+
         if (td.columns_missing_from_B
             and not td.columns_missing_from_A
             and not td.columns_different):
-            # Even sqlite can handle this.
+            # Even sqlite can handle column additions.
             return True
         else:
             return not self.engine.url.drivername.startswith('sqlite')
 
-    def applyModel(self):
-        """Apply model to current database."""
+    def runB2A(self):
+        """Goes from B to A.
+
+        Was: applyModel. Apply model (A) to current database (B).
+        """
 
         meta = sqlalchemy.MetaData(self.engine)
 
@@ -251,3 +282,4 @@
                 except:
                     trans.rollback()
                     raise
+
--- a/rhodecode/lib/dbmigrate/migrate/versioning/repository.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/repository.py	Fri Oct 07 01:08:50 2011 +0200
@@ -115,6 +115,7 @@
         options.setdefault('version_table', 'migrate_version')
         options.setdefault('repository_id', name)
         options.setdefault('required_dbs', [])
+        options.setdefault('use_timestamp_numbering', '0')
 
         tmpl = open(os.path.join(tmpl_dir, cls._config)).read()
         ret = TempitaTemplate(tmpl).substitute(options)
@@ -152,11 +153,14 @@
 
     def create_script(self, description, **k):
         """API to :meth:`migrate.versioning.version.Collection.create_new_python_version`"""
+        
+        k['use_timestamp_numbering'] = self.use_timestamp_numbering
         self.versions.create_new_python_version(description, **k)
 
-    def create_script_sql(self, database, **k):
+    def create_script_sql(self, database, description, **k):
         """API to :meth:`migrate.versioning.version.Collection.create_new_sql_version`"""
-        self.versions.create_new_sql_version(database, **k)
+        k['use_timestamp_numbering'] = self.use_timestamp_numbering
+        self.versions.create_new_sql_version(database, description, **k)
 
     @property
     def latest(self):
@@ -173,6 +177,13 @@
         """Returns repository id specified in config"""
         return self.config.get('db_settings', 'repository_id')
 
+    @property
+    def use_timestamp_numbering(self):
+        """Returns use_timestamp_numbering specified in config"""
+        ts_numbering = self.config.get('db_settings', 'use_timestamp_numbering', raw=True)
+        
+        return ts_numbering
+
     def version(self, *p, **k):
         """API to :attr:`migrate.versioning.version.Collection.version`"""
         return self.versions.version(*p, **k)
@@ -218,7 +229,7 @@
     @classmethod
     def create_manage_file(cls, file_, **opts):
         """Create a project management script (manage.py)
-        
+
         :param file_: Destination file to be written
         :param opts: Options that are passed to :func:`migrate.versioning.shell.main`
         """
--- a/rhodecode/lib/dbmigrate/migrate/versioning/schema.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/schema.py	Fri Oct 07 01:08:50 2011 +0200
@@ -11,6 +11,7 @@
 from sqlalchemy.sql import bindparam
 
 from rhodecode.lib.dbmigrate.migrate import exceptions
+from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_07
 from rhodecode.lib.dbmigrate.migrate.versioning import genmodel, schemadiff
 from rhodecode.lib.dbmigrate.migrate.versioning.repository import Repository
 from rhodecode.lib.dbmigrate.migrate.versioning.util import load_model
@@ -57,14 +58,20 @@
         """
         Remove version control from a database.
         """
-        try:
-            self.table.drop()
-        except (sa_exceptions.SQLError):
-            raise exceptions.DatabaseNotControlledError(str(self.table))
+        if SQLA_07:
+            try:
+                self.table.drop()
+            except sa_exceptions.DatabaseError:
+                raise exceptions.DatabaseNotControlledError(str(self.table))
+        else:
+            try:
+                self.table.drop()
+            except (sa_exceptions.SQLError):
+                raise exceptions.DatabaseNotControlledError(str(self.table))
 
     def changeset(self, version=None):
         """API to Changeset creation.
-        
+
         Uses self.version for start version and engine.name
         to get database name.
         """
@@ -110,7 +117,7 @@
         diff = schemadiff.getDiffOfModelAgainstDatabase(
             model, self.engine, excludeTables=[self.repository.version_table]
             )
-        genmodel.ModelGenerator(diff,self.engine).applyModel()
+        genmodel.ModelGenerator(diff,self.engine).runB2A()
 
         self.update_repository_table(self.version, int(self.repository.latest))
 
@@ -210,4 +217,4 @@
         diff = schemadiff.getDiffOfModelAgainstDatabase(
             MetaData(), engine, excludeTables=[repository.version_table]
             )
-        return genmodel.ModelGenerator(diff, engine, declarative).toPython()
+        return genmodel.ModelGenerator(diff, engine, declarative).genBDefinition()
--- a/rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py	Fri Oct 07 01:08:50 2011 +0200
@@ -39,11 +39,11 @@
     Container for differences in one :class:`~sqlalchemy.schema.Column`
     between two :class:`~sqlalchemy.schema.Table` instances, ``A``
     and ``B``.
-    
+
     .. attribute:: col_A
 
       The :class:`~sqlalchemy.schema.Column` object for A.
-      
+
     .. attribute:: col_B
 
       The :class:`~sqlalchemy.schema.Column` object for B.
@@ -51,15 +51,15 @@
     .. attribute:: type_A
 
       The most generic type of the :class:`~sqlalchemy.schema.Column`
-      object in A. 
-      
+      object in A.
+
     .. attribute:: type_B
 
       The most generic type of the :class:`~sqlalchemy.schema.Column`
-      object in A. 
-      
+      object in A.
+
     """
-    
+
     diff = False
 
     def __init__(self,col_A,col_B):
@@ -87,10 +87,10 @@
             if not (A is None or B is None) and A!=B:
                 self.diff=True
                 return
-        
+
     def __nonzero__(self):
         return self.diff
-    
+
 class TableDiff(object):
     """
     Container for differences in one :class:`~sqlalchemy.schema.Table`
@@ -101,12 +101,12 @@
 
       A sequence of column names that were found in B but weren't in
       A.
-      
+
     .. attribute:: columns_missing_from_B
 
       A sequence of column names that were found in A but weren't in
       B.
-      
+
     .. attribute:: columns_different
 
       A dictionary containing information about columns that were
@@ -126,7 +126,7 @@
             self.columns_missing_from_B or
             self.columns_different
             )
-    
+
 class SchemaDiff(object):
     """
     Compute the difference between two :class:`~sqlalchemy.schema.MetaData`
@@ -139,34 +139,34 @@
     The length of a :class:`SchemaDiff` will give the number of
     changes found, enabling it to be used much like a boolean in
     expressions.
-        
+
     :param metadataA:
       First :class:`~sqlalchemy.schema.MetaData` to compare.
-      
+
     :param metadataB:
       Second :class:`~sqlalchemy.schema.MetaData` to compare.
-      
+
     :param labelA:
       The label to use in messages about the first
-      :class:`~sqlalchemy.schema.MetaData`. 
-    
-    :param labelB: 
+      :class:`~sqlalchemy.schema.MetaData`.
+
+    :param labelB:
       The label to use in messages about the second
-      :class:`~sqlalchemy.schema.MetaData`. 
-    
+      :class:`~sqlalchemy.schema.MetaData`.
+
     :param excludeTables:
       A sequence of table names to exclude.
-      
+
     .. attribute:: tables_missing_from_A
 
       A sequence of table names that were found in B but weren't in
       A.
-      
+
     .. attribute:: tables_missing_from_B
 
       A sequence of table names that were found in A but weren't in
       B.
-      
+
     .. attribute:: tables_different
 
       A dictionary containing information about tables that were found
@@ -195,26 +195,26 @@
         self.tables_missing_from_B = sorted(
             A_table_names - B_table_names - excludeTables
             )
-        
+
         self.tables_different = {}
         for table_name in A_table_names.intersection(B_table_names):
 
             td = TableDiff()
-            
+
             A_table = metadataA.tables[table_name]
             B_table = metadataB.tables[table_name]
-            
+
             A_column_names = set(A_table.columns.keys())
             B_column_names = set(B_table.columns.keys())
 
             td.columns_missing_from_A = sorted(
                 B_column_names - A_column_names
                 )
-            
+
             td.columns_missing_from_B = sorted(
                 A_column_names - B_column_names
                 )
-            
+
             td.columns_different = {}
 
             for col_name in A_column_names.intersection(B_column_names):
@@ -226,7 +226,7 @@
 
                 if cd:
                     td.columns_different[col_name]=cd
-                
+
             # XXX - index and constraint differences should
             #       be checked for here
 
@@ -237,7 +237,7 @@
         ''' Summarize differences. '''
         out = []
         column_template ='      %%%is: %%r' % self.label_width
-        
+
         for names,label in (
             (self.tables_missing_from_A,self.labelA),
             (self.tables_missing_from_B,self.labelB),
@@ -248,7 +248,7 @@
                         label,', '.join(sorted(names))
                         )
                     )
-                
+
         for name,td in sorted(self.tables_different.items()):
             out.append(
                '  table with differences: %s' % name
@@ -267,7 +267,7 @@
                 out.append('    column with differences: %s' % name)
                 out.append(column_template % (self.labelA,cd.col_A))
                 out.append(column_template % (self.labelB,cd.col_B))
-                
+
         if out:
             out.insert(0, 'Schema diffs:')
             return '\n'.join(out)
--- a/rhodecode/lib/dbmigrate/migrate/versioning/script/base.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/script/base.py	Fri Oct 07 01:08:50 2011 +0200
@@ -28,7 +28,7 @@
         self.verify(path)
         super(BaseScript, self).__init__(path)
         log.debug('Script %s loaded successfully' % path)
-    
+
     @classmethod
     def verify(cls, path):
         """Ensure this is a valid script
--- a/rhodecode/lib/dbmigrate/migrate/versioning/script/py.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/script/py.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,6 +4,7 @@
 import shutil
 import warnings
 import logging
+import inspect
 from StringIO import StringIO
 
 from rhodecode.lib.dbmigrate import migrate
@@ -24,7 +25,7 @@
     @classmethod
     def create(cls, path, **opts):
         """Create an empty migration script at specified path
-        
+
         :returns: :class:`PythonScript instance <migrate.versioning.script.py.PythonScript>`"""
         cls.require_notfound(path)
 
@@ -37,7 +38,7 @@
     def make_update_script_for_model(cls, engine, oldmodel,
                                      model, repository, **opts):
         """Create a migration script based on difference between two SA models.
-        
+
         :param repository: path to migrate repository
         :param oldmodel: dotted.module.name:SAClass or SAClass object
         :param model: dotted.module.name:SAClass or SAClass object
@@ -60,12 +61,12 @@
 
         # Compute differences.
         diff = schemadiff.getDiffOfModelAgainstModel(
+            model,
             oldmodel,
-            model,
             excludeTables=[repository.version_table])
         # TODO: diff can be False (there is no difference?)
         decls, upgradeCommands, downgradeCommands = \
-            genmodel.ModelGenerator(diff, engine).toUpgradeDowngradePython()
+            genmodel.ModelGenerator(diff,engine).genB2AMigration()
 
         # Store differences into file.
         src = Template(opts.pop('templates_path', None)).get_script(opts.pop('templates_theme', None))
@@ -85,7 +86,7 @@
     @classmethod
     def verify_module(cls, path):
         """Ensure path is a valid script
-        
+
         :param path: Script location
         :type path: string
         :raises: :exc:`InvalidScriptError <migrate.exceptions.InvalidScriptError>`
@@ -100,7 +101,7 @@
         return module
 
     def preview_sql(self, url, step, **args):
-        """Mocks SQLAlchemy Engine to store all executed calls in a string 
+        """Mocks SQLAlchemy Engine to store all executed calls in a string
         and runs :meth:`PythonScript.run <migrate.versioning.script.py.PythonScript.run>`
 
         :returns: SQL file
@@ -118,7 +119,7 @@
         return go(url, step, **args)
 
     def run(self, engine, step):
-        """Core method of Script file. 
+        """Core method of Script file.
         Exectues :func:`update` or :func:`downgrade` functions
 
         :param engine: SQLAlchemy Engine
@@ -136,12 +137,12 @@
         funcname = base.operations[op]
         script_func = self._func(funcname)
 
-        try:
-            script_func(engine)
-        except TypeError:
-            warnings.warn("upgrade/downgrade functions must accept engine"
-                " parameter (since version > 0.5.4)", MigrateDeprecationWarning)
-            raise
+        # check for old way of using engine
+        if not inspect.getargspec(script_func)[0]:
+            raise TypeError("upgrade/downgrade functions must accept engine"
+                " parameter (since version 0.5.4)")
+
+        script_func(engine)
 
     @property
     def module(self):
--- a/rhodecode/lib/dbmigrate/migrate/versioning/script/sql.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/script/sql.py	Fri Oct 07 01:08:50 2011 +0200
@@ -15,9 +15,10 @@
     @classmethod
     def create(cls, path, **opts):
         """Create an empty migration script at specified path
-        
+
         :returns: :class:`SqlScript instance <migrate.versioning.script.sql.SqlScript>`"""
         cls.require_notfound(path)
+
         src = Template(opts.pop('templates_path', None)).get_sql_script(theme=opts.pop('templates_theme', None))
         shutil.copy(src, path)
         return cls(path)
--- a/rhodecode/lib/dbmigrate/migrate/versioning/shell.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/shell.py	Fri Oct 07 01:08:50 2011 +0200
@@ -77,8 +77,7 @@
         %s
 
     Enter "%%prog help COMMAND" for information on a particular command.
-    """ % '\n\t'.join(["%s - %s" % (command.ljust(28),
-                    api.command_desc.get(command)) for command in commands])
+    """ % '\n\t'.join(["%s - %s" % (command.ljust(28), api.command_desc.get(command)) for command in commands])
 
     parser = PassiveOptionParser(usage=usage)
     parser.add_option("-d", "--debug",
--- a/rhodecode/lib/dbmigrate/migrate/versioning/template.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/template.py	Fri Oct 07 01:08:50 2011 +0200
@@ -33,7 +33,7 @@
 
 class Template(pathed.Pathed):
     """Finds the paths/packages of various Migrate templates.
-    
+
     :param path: Templates are loaded from rhodecode.lib.dbmigrate.migrate package
     if `path` is not provided.
     """
@@ -66,7 +66,7 @@
 
     def _get_item(self, collection, theme=None):
         """Locates and returns collection.
-        
+
         :param collection: name of collection to locate
         :param type_: type of subfolder in collection (defaults to "_default")
         :returns: (package, source)
--- a/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/migrate.cfg	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/templates/repository/default/migrate.cfg	Fri Oct 07 01:08:50 2011 +0200
@@ -18,3 +18,8 @@
 # be using to ensure your updates to that database work properly.
 # This must be a list; example: ['postgres','sqlite']
 required_dbs={{ locals().pop('required_dbs') }}
+
+# When creating new change scripts, Migrate will stamp the new script with
+# a version number. By default this is latest_version + 1. You can set this
+# to 'true' to tell Migrate to use the UTC timestamp instead.
+use_timestamp_numbering='false'
\ No newline at end of file
--- a/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -22,7 +22,7 @@
     """Import module and use module-level variable".
 
     :param dotted_name: path to model in form of string: ``some.python.module:Class``
-    
+
     .. versionchanged:: 0.5.4
 
     """
@@ -54,9 +54,9 @@
 
 def guess_obj_type(obj):
     """Do everything to guess object type from string
-    
+
     Tries to convert to `int`, `bool` and finally returns if not succeded.
-    
+
     .. versionadded: 0.5.4
     """
 
@@ -81,7 +81,7 @@
 @decorator
 def catch_known_errors(f, *a, **kw):
     """Decorator that catches known api errors
-    
+
     .. versionadded: 0.5.4
     """
 
--- a/rhodecode/lib/dbmigrate/migrate/versioning/util/importpath.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/util/importpath.py	Fri Oct 07 01:08:50 2011 +0200
@@ -3,7 +3,7 @@
 
 def import_path(fullpath):
     """ Import a file with full path specification. Allows one to
-        import from anywhere, something __import__ does not do. 
+        import from anywhere, something __import__ does not do.
     """
     # http://zephyrfalcon.org/weblog/arch_d7_2002_08_31.html
     path, filename = os.path.split(fullpath)
@@ -13,4 +13,3 @@
     reload(module) # Might be out of date during tests
     del sys.path[-1]
     return module
-
--- a/rhodecode/lib/dbmigrate/migrate/versioning/util/keyedinstance.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/util/keyedinstance.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,7 +4,7 @@
 class KeyedInstance(object):
     """A class whose instances have a unique identifier of some sort
     No two instances with the same unique ID should exist - if we try to create
-    a second instance, the first should be returned. 
+    a second instance, the first should be returned.
     """
 
     _instances = dict()
@@ -24,7 +24,7 @@
     @classmethod
     def _key(cls, *p, **k):
         """Given a unique identifier, return a dictionary key
-        This should be overridden by child classes, to specify which parameters 
+        This should be overridden by child classes, to specify which parameters
         should determine an object's uniqueness
         """
         raise NotImplementedError()
--- a/rhodecode/lib/dbmigrate/migrate/versioning/version.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/migrate/versioning/version.py	Fri Oct 07 01:08:50 2011 +0200
@@ -8,6 +8,7 @@
 
 from rhodecode.lib.dbmigrate.migrate import exceptions
 from rhodecode.lib.dbmigrate.migrate.versioning import pathed, script
+from datetime import datetime
 
 
 log = logging.getLogger(__name__)
@@ -88,9 +89,17 @@
         """:returns: Latest version in Collection"""
         return max([VerNum(0)] + self.versions.keys())
 
+    def _next_ver_num(self, use_timestamp_numbering):
+        print use_timestamp_numbering
+        if use_timestamp_numbering == True:
+            print "Creating new timestamp version!"
+            return VerNum(int(datetime.utcnow().strftime('%Y%m%d%H%M%S')))
+        else:
+            return self.latest + 1
+
     def create_new_python_version(self, description, **k):
         """Create Python files for new version"""
-        ver = self.latest + 1
+        ver = self._next_ver_num(k.pop('use_timestamp_numbering', False))
         extra = str_to_filename(description)
 
         if extra:
@@ -105,14 +114,22 @@
         script.PythonScript.create(filepath, **k)
         self.versions[ver] = Version(ver, self.path, [filename])
         
-    def create_new_sql_version(self, database, **k):
+    def create_new_sql_version(self, database, description, **k):
         """Create SQL files for new version"""
-        ver = self.latest + 1
+        ver = self._next_ver_num(k.pop('use_timestamp_numbering', False))
         self.versions[ver] = Version(ver, self.path, [])
 
+        extra = str_to_filename(description)
+
+        if extra:
+            if extra == '_':
+                extra = ''
+            elif not extra.startswith('_'):
+                extra = '_%s' % extra
+
         # Create new files.
         for op in ('upgrade', 'downgrade'):
-            filename = '%03d_%s_%s.sql' % (ver, database, op)
+            filename = '%03d%s_%s_%s.sql' % (ver, extra, database, op)
             filepath = self._version_path(filename)
             script.SqlScript.create(filepath, **k)
             self.versions[ver].add_script(filepath)
@@ -176,18 +193,26 @@
         elif path.endswith(Extensions.sql):
             self._add_script_sql(path)
 
-    SQL_FILENAME = re.compile(r'^(\d+)_([^_]+)_([^_]+).sql')
+    SQL_FILENAME = re.compile(r'^.*\.sql')
 
     def _add_script_sql(self, path):
         basename = os.path.basename(path)
         match = self.SQL_FILENAME.match(basename)
-
+        
         if match:
-            version, dbms, op = match.group(1), match.group(2), match.group(3)
+            basename = basename.replace('.sql', '')
+            parts = basename.split('_')
+            if len(parts) < 3:
+                raise exceptions.ScriptError(
+                    "Invalid SQL script name %s " % basename + \
+                    "(needs to be ###_description_database_operation.sql)")
+            version = parts[0]
+            op = parts[-1]
+            dbms = parts[-2]
         else:
             raise exceptions.ScriptError(
                 "Invalid SQL script name %s " % basename + \
-                "(needs to be ###_database_operation.sql)")
+                "(needs to be ###_description_database_operation.sql)")
 
         # File the script into a dictionary
         self.sql.setdefault(dbms, {})[op] = script.SqlScript(path)
--- a/rhodecode/lib/dbmigrate/versions/001_initial_release.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/versions/001_initial_release.py	Fri Oct 07 01:08:50 2011 +0200
@@ -14,39 +14,7 @@
 
 log = logging.getLogger(__name__)
 
-class BaseModel(object):
-
-    @classmethod
-    def _get_keys(cls):
-        """return column names for this model """
-        return class_mapper(cls).c.keys()
-
-    def get_dict(self):
-        """return dict with keys and values corresponding 
-        to this model data """
-
-        d = {}
-        for k in self._get_keys():
-            d[k] = getattr(self, k)
-        return d
-
-    def get_appstruct(self):
-        """return list with keys and values tupples corresponding 
-        to this model data """
-
-        l = []
-        for k in self._get_keys():
-            l.append((k, getattr(self, k),))
-        return l
-
-    def populate_obj(self, populate_dict):
-        """populate model with data from given populate_dict"""
-
-        for k in self._get_keys():
-            if k in populate_dict:
-                setattr(self, k, populate_dict[k])
-
-class RhodeCodeSettings(Base, BaseModel):
+class RhodeCodeSettings(Base):
     __tablename__ = 'rhodecode_settings'
     __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
     app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -61,7 +29,7 @@
         return "<RhodeCodeSetting('%s:%s')>" % (self.app_settings_name,
                                                 self.app_settings_value)
 
-class RhodeCodeUi(Base, BaseModel):
+class RhodeCodeUi(Base):
     __tablename__ = 'rhodecode_ui'
     __table_args__ = {'useexisting':True}
     ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -71,7 +39,7 @@
     ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 
 
-class User(Base, BaseModel):
+class User(Base):
     __tablename__ = 'users'
     __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
     user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -111,7 +79,7 @@
             session.rollback()
 
 
-class UserLog(Base, BaseModel):
+class UserLog(Base):
     __tablename__ = 'user_logs'
     __table_args__ = {'useexisting':True}
     user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -125,7 +93,7 @@
     user = relation('User')
     repository = relation('Repository')
 
-class Repository(Base, BaseModel):
+class Repository(Base):
     __tablename__ = 'repositories'
     __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
     repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -148,7 +116,7 @@
     def __repr__(self):
         return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
 
-class Permission(Base, BaseModel):
+class Permission(Base):
     __tablename__ = 'permissions'
     __table_args__ = {'useexisting':True}
     permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -158,7 +126,7 @@
     def __repr__(self):
         return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
 
-class RepoToPerm(Base, BaseModel):
+class RepoToPerm(Base):
     __tablename__ = 'repo_to_perm'
     __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
     repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -170,7 +138,7 @@
     permission = relation('Permission')
     repository = relation('Repository')
 
-class UserToPerm(Base, BaseModel):
+class UserToPerm(Base):
     __tablename__ = 'user_to_perm'
     __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
     user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -180,7 +148,7 @@
     user = relation('User')
     permission = relation('Permission')
 
-class Statistics(Base, BaseModel):
+class Statistics(Base):
     __tablename__ = 'statistics'
     __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
     stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -192,7 +160,7 @@
 
     repository = relation('Repository', single_parent=True)
 
-class UserFollowing(Base, BaseModel):
+class UserFollowing(Base):
     __tablename__ = 'user_followings'
     __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
                       UniqueConstraint('user_id', 'follows_user_id')
@@ -209,7 +177,7 @@
     follows_repository = relation('Repository')
 
 
-class CacheInvalidation(Base, BaseModel):
+class CacheInvalidation(Base):
     __tablename__ = 'cache_invalidation'
     __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
     cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,119 @@
+import logging
+import datetime
+
+from sqlalchemy import *
+from sqlalchemy.exc import DatabaseError
+from sqlalchemy.orm import relation, backref, class_mapper
+from sqlalchemy.orm.session import Session
+
+from rhodecode.lib.dbmigrate.migrate import *
+from rhodecode.lib.dbmigrate.migrate.changeset import *
+
+from rhodecode.model.meta import Base
+
+log = logging.getLogger(__name__)
+
+def upgrade(migrate_engine):
+    """ Upgrade operations go here.
+    Don't create your own engine; bind migrate_engine to your metadata
+    """
+
+    #==========================================================================
+    # Add table `groups``
+    #==========================================================================
+    from rhodecode.model.db import Group
+    Group().__table__.create()
+
+    #==========================================================================
+    # Add table `group_to_perm`
+    #==========================================================================
+    from rhodecode.model.db import GroupToPerm
+    GroupToPerm().__table__.create()
+
+    #==========================================================================
+    # Add table `users_groups`
+    #==========================================================================
+    from rhodecode.model.db import UsersGroup
+    UsersGroup().__table__.create()
+
+    #==========================================================================
+    # Add table `users_groups_members`
+    #==========================================================================
+    from rhodecode.model.db import UsersGroupMember
+    UsersGroupMember().__table__.create()
+
+    #==========================================================================
+    # Add table `users_group_repo_to_perm`
+    #==========================================================================
+    from rhodecode.model.db import UsersGroupRepoToPerm
+    UsersGroupRepoToPerm().__table__.create()
+
+    #==========================================================================
+    # Add table `users_group_to_perm`
+    #==========================================================================
+    from rhodecode.model.db import UsersGroupToPerm
+    UsersGroupToPerm().__table__.create()
+
+    #==========================================================================
+    # Upgrade of `users` table
+    #==========================================================================
+    from rhodecode.model.db import User
+
+    #add column
+    ldap_dn = Column("ldap_dn", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    ldap_dn.create(User().__table__)
+
+    api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    api_key.create(User().__table__)
+
+    #remove old column
+    is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
+    is_ldap.drop(User().__table__)
+
+
+    #==========================================================================
+    # Upgrade of `repositories` table
+    #==========================================================================
+    from rhodecode.model.db import Repository
+
+    #ADD clone_uri column#
+
+    clone_uri = Column("clone_uri", String(length=255, convert_unicode=False,
+                                           assert_unicode=None),
+                        nullable=True, unique=False, default=None)
+
+    clone_uri.create(Repository().__table__)
+    
+    #ADD downloads column#
+    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
+    enable_downloads.create(Repository().__table__)
+
+    #ADD column created_on
+    created_on = Column('created_on', DateTime(timezone=False), nullable=True,
+                        unique=None, default=datetime.datetime.now)
+    created_on.create(Repository().__table__)
+
+    #ADD group_id column#
+    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'),
+                  nullable=True, unique=False, default=None)
+
+    group_id.create(Repository().__table__)
+
+
+    #==========================================================================
+    # Upgrade of `user_followings` table
+    #==========================================================================
+
+    from rhodecode.model.db import UserFollowing
+
+    follows_from = Column('follows_from', DateTime(timezone=False), 
+                          nullable=True, unique=None, 
+                          default=datetime.datetime.now)
+    follows_from.create(UserFollowing().__table__)
+
+    return
+
+
+def downgrade(migrate_engine):
+    meta = MetaData()
+    meta.bind = migrate_engine
--- a/rhodecode/lib/dbmigrate/versions/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/dbmigrate/versions/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Package containing new versions of database models
-    
+
     :created_on: Dec 11, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
--- a/rhodecode/lib/exceptions.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/exceptions.py	Fri Oct 07 01:08:50 2011 +0200
@@ -3,12 +3,11 @@
     rhodecode.lib.exceptions
     ~~~~~~~~~~~~~~~~~~~~~~~~
 
-    Custom Exceptions modules
+    Set of custom exceptions used in RhodeCode
 
-    :created_on: Apr 10, 2010
-    :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
-    :license: GPLv3, see COPYING for more details.
+    :created_on: Nov 17, 2010
+    :copyright: (c) 2010 by marcink.
+    :license: LICENSE_NAME, see LICENSE_FILE for more details.
 """
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -46,3 +45,6 @@
 
 class UserOwnsReposException(Exception):
     pass
+
+class UsersGroupsAssignedException(Exception):
+    pass
--- a/rhodecode/lib/helpers.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/helpers.py	Fri Oct 07 01:08:50 2011 +0200
@@ -7,11 +7,12 @@
 import hashlib
 import StringIO
 import urllib
+import math
 
 from datetime import datetime
 from pygments.formatters import HtmlFormatter
 from pygments import highlight as code_highlight
-from pylons import url, app_globals as g
+from pylons import url, request, config
 from pylons.i18n.translation import _, ungettext
 
 from webhelpers.html import literal, HTML, escape
@@ -36,7 +37,7 @@
 
 from vcs.utils.annotate import annotate_highlight
 from rhodecode.lib.utils import repo_name_slug
-from rhodecode.lib import str2bool, safe_unicode
+from rhodecode.lib import str2bool, safe_unicode, safe_str,get_changeset_safe
 
 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
     """
@@ -89,45 +90,7 @@
 
         :param tooltip_title:
         """
-
-        return wrap_paragraphs(escape(tooltip_title), trim_at)\
-                       .replace('\n', '<br/>')
-
-    def activate(self):
-        """Adds tooltip mechanism to the given Html all tooltips have to have
-        set class `tooltip` and set attribute `tooltip_title`.
-        Then a tooltip will be generated based on that. All with yui js tooltip
-        """
-
-        js = '''
-        YAHOO.util.Event.onDOMReady(function(){
-            function toolTipsId(){
-                var ids = [];
-                var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
-
-                for (var i = 0; i < tts.length; i++) {
-                    //if element doesn't not have and id autogenerate one for tooltip
-
-                    if (!tts[i].id){
-                        tts[i].id='tt'+i*100;
-                    }
-                    ids.push(tts[i].id);
-                }
-                return ids
-            };
-            var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
-                context: [[toolTipsId()],"tl","bl",null,[0,5]],
-                monitorresize:false,
-                xyoffset :[0,0],
-                autodismissdelay:300000,
-                hidedelay:5,
-                showdelay:20,
-            });
-
-        });
-        '''
-        return literal(js)
-
+        return escape(tooltip_title)
 tooltip = _ToolTip()
 
 class _FilesBreadCrumbs(object):
@@ -160,19 +123,84 @@
     def _wrap_code(self, source):
         for cnt, it in enumerate(source):
             i, t = it
-            t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
+            t = '<div id="L%s">%s</div>' % (cnt + 1, t)
             yield i, t
+
+    def _wrap_tablelinenos(self, inner):
+        dummyoutfile = StringIO.StringIO()
+        lncount = 0
+        for t, line in inner:
+            if t:
+                lncount += 1
+            dummyoutfile.write(line)
+
+        fl = self.linenostart
+        mw = len(str(lncount + fl - 1))
+        sp = self.linenospecial
+        st = self.linenostep
+        la = self.lineanchors
+        aln = self.anchorlinenos
+        nocls = self.noclasses
+        if sp:
+            lines = []
+
+            for i in range(fl, fl + lncount):
+                if i % st == 0:
+                    if i % sp == 0:
+                        if aln:
+                            lines.append('<a href="#%s%d" class="special">%*d</a>' %
+                                         (la, i, mw, i))
+                        else:
+                            lines.append('<span class="special">%*d</span>' % (mw, i))
+                    else:
+                        if aln:
+                            lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
+                        else:
+                            lines.append('%*d' % (mw, i))
+                else:
+                    lines.append('')
+            ls = '\n'.join(lines)
+        else:
+            lines = []
+            for i in range(fl, fl + lncount):
+                if i % st == 0:
+                    if aln:
+                        lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
+                    else:
+                        lines.append('%*d' % (mw, i))
+                else:
+                    lines.append('')
+            ls = '\n'.join(lines)
+
+        # in case you wonder about the seemingly redundant <div> here: since the
+        # content in the other cell also is wrapped in a div, some browsers in
+        # some configurations seem to mess up the formatting...
+        if nocls:
+            yield 0, ('<table class="%stable">' % self.cssclass +
+                      '<tr><td><div class="linenodiv" '
+                      'style="background-color: #f0f0f0; padding-right: 10px">'
+                      '<pre style="line-height: 125%">' +
+                      ls + '</pre></div></td><td id="hlcode" class="code">')
+        else:
+            yield 0, ('<table class="%stable">' % self.cssclass +
+                      '<tr><td class="linenos"><div class="linenodiv"><pre>' +
+                      ls + '</pre></div></td><td id="hlcode" class="code">')
+        yield 0, dummyoutfile.getvalue()
+        yield 0, '</td></tr></table>'
+
+
 def pygmentize(filenode, **kwargs):
-    """
-    pygmentize function using pygments
+    """pygmentize function using pygments
+
     :param filenode:
     """
+
     return literal(code_highlight(filenode.content,
                                   filenode.lexer, CodeHtmlFormatter(**kwargs)))
 
-def pygmentize_annotation(filenode, **kwargs):
-    """
-    pygmentize function for annotation
+def pygmentize_annotation(repo_name, filenode, **kwargs):
+    """pygmentize function for annotation
+
     :param filenode:
     """
 
@@ -183,15 +211,30 @@
 
         :returns: RGB tuple
         """
-        import colorsys
+
+        def hsv_to_rgb(h, s, v):
+            if s == 0.0: return v, v, v
+            i = int(h * 6.0) # XXX assume int() truncates!
+            f = (h * 6.0) - i
+            p = v * (1.0 - s)
+            q = v * (1.0 - s * f)
+            t = v * (1.0 - s * (1.0 - f))
+            i = i % 6
+            if i == 0: return v, t, p
+            if i == 1: return q, v, p
+            if i == 2: return p, v, t
+            if i == 3: return p, q, v
+            if i == 4: return t, p, v
+            if i == 5: return v, p, q
+
         golden_ratio = 0.618033988749895
         h = 0.22717784590367374
 
-        for c in xrange(n):
+        for _ in xrange(n):
             h += golden_ratio
             h %= 1
             HSV_tuple = [h, 0.95, 0.95]
-            RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
+            RGB_tuple = hsv_to_rgb(*HSV_tuple)
             yield map(lambda x:str(int(x * 256)), RGB_tuple)
 
     cgenerator = gen_color()
@@ -203,83 +246,54 @@
             col = color_dict[cs] = cgenerator.next()
         return "color: rgb(%s)! important;" % (', '.join(col))
 
-    def url_func(changeset):
-        tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
-        " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
+    def url_func(repo_name):
 
-        tooltip_html = tooltip_html % (changeset.author,
-                                               changeset.date,
-                                               tooltip(changeset.message))
-        lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
-                                 short_id(changeset.raw_id))
-        uri = link_to(
-                lnk_format,
-                url('changeset_home', repo_name=changeset.repository.name,
-                    revision=changeset.raw_id),
-                style=get_color_string(changeset.raw_id),
-                class_='tooltip',
-                title=tooltip_html
-              )
+        def _url_func(changeset):
+            author = changeset.author
+            date = changeset.date
+            message = tooltip(changeset.message)
+
+            tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
+                            " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
+                            "</b> %s<br/></div>")
 
-        uri += '\n'
-        return uri
-    return literal(annotate_highlight(filenode, url_func, **kwargs))
+            tooltip_html = tooltip_html % (author, date, message)
+            lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
+                                     short_id(changeset.raw_id))
+            uri = link_to(
+                    lnk_format,
+                    url('changeset_home', repo_name=repo_name,
+                        revision=changeset.raw_id),
+                    style=get_color_string(changeset.raw_id),
+                    class_='tooltip',
+                    title=tooltip_html
+                  )
 
-def get_changeset_safe(repo, rev):
-    from vcs.backends.base import BaseRepository
-    from vcs.exceptions import RepositoryError
-    if not isinstance(repo, BaseRepository):
-        raise Exception('You must pass an Repository '
-                        'object as first argument got %s', type(repo))
+            uri += '\n'
+            return uri
+        return _url_func
 
-    try:
-        cs = repo.get_changeset(rev)
-    except RepositoryError:
-        from rhodecode.lib.utils import EmptyChangeset
-        cs = EmptyChangeset()
-    return cs
+    return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
 
+def is_following_repo(repo_name, user_id):
+    from rhodecode.model.scm import ScmModel
+    return ScmModel().is_following_repo(repo_name, user_id)
 
 flash = _Flash()
 
-
 #==============================================================================
-# MERCURIAL FILTERS available via h.
+# SCM FILTERS available via h.
 #==============================================================================
-from mercurial import util
-from mercurial.templatefilters import person as _person
-
-def _age(curdate):
-    """turns a datetime into an age string."""
-
-    if not curdate:
-        return ''
-
-    agescales = [("year", 3600 * 24 * 365),
-                 ("month", 3600 * 24 * 30),
-                 ("day", 3600 * 24),
-                 ("hour", 3600),
-                 ("minute", 60),
-                 ("second", 1), ]
-
-    age = datetime.now() - curdate
-    age_seconds = (age.days * agescales[2][1]) + age.seconds
-    pos = 1
-    for scale in agescales:
-        if scale[1] <= age_seconds:
-            if pos == 6:pos = 5
-            return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
-        pos += 1
-
-    return _('just now')
+from vcs.utils import author_name, author_email
+from rhodecode.lib import credentials_filter, age as _age
 
 age = lambda  x:_age(x)
 capitalize = lambda x: x.capitalize()
-email = util.email
-email_or_none = lambda x: util.email(x) if util.email(x) != x else None
-person = lambda x: _person(x)
+email = author_email
+email_or_none = lambda x: email(x) if email(x) != x else None
+person = lambda x: author_name(x)
 short_id = lambda x: x[:12]
-
+hide_credentials = lambda x: ''.join(credentials_filter(x))
 
 def bool2icon(value):
     """Returns True/False values represented as small html image of true/false
@@ -299,13 +313,14 @@
     return value
 
 
-def action_parser(user_log):
-    """
-    This helper will map the specified string action into translated
+def action_parser(user_log, feed=False):
+    """This helper will action_map the specified string action into translated
     fancy names with icons and links
-    
-    @param action:
+
+    :param user_log: user log instance
+    :param feed: use output for feeds (no html and fancy icons)
     """
+
     action = user_log.action
     action_params = ' '
 
@@ -315,56 +330,90 @@
         action, action_params = x
 
     def get_cs_links():
-        revs_limit = 5
+        revs_limit = 3 #display this amount always
+        revs_top_limit = 50 #show upto this amount of changesets hidden
         revs = action_params.split(',')
-        cs_links = " " + ', '.join ([link_to(rev, url('changeset_home',
-                                repo_name=user_log.repository.repo_name,
-                                revision=rev)) for rev in revs[:revs_limit]])
+        repo_name = user_log.repository.repo_name
+
+        from rhodecode.model.scm import ScmModel
+        repo = user_log.repository.scm_instance
+
+        message = lambda rev: get_changeset_safe(repo, rev).message
+        cs_links = []
+        cs_links.append(" " + ', '.join ([link_to(rev,
+                url('changeset_home',
+                repo_name=repo_name,
+                revision=rev), title=tooltip(message(rev)),
+                class_='tooltip') for rev in revs[:revs_limit] ]))
+
+        compare_view = (' <div class="compare_view tooltip" title="%s">'
+                        '<a href="%s">%s</a> '
+                        '</div>' % (_('Show all combined changesets %s->%s' \
+                                      % (revs[0], revs[-1])),
+                                    url('changeset_home', repo_name=repo_name,
+                                        revision='%s...%s' % (revs[0], revs[-1])
+                                    ),
+                                    _('compare view'))
+                        )
+
         if len(revs) > revs_limit:
             uniq_id = revs[0]
             html_tmpl = ('<span> %s '
-            '<a class="show_more" id="_%s" href="#">%s</a> '
+            '<a class="show_more" id="_%s" href="#more">%s</a> '
             '%s</span>')
-            cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
+            if not feed:
+                cs_links.append(html_tmpl % (_('and'), uniq_id, _('%s more') \
                                         % (len(revs) - revs_limit),
-                                        _('revisions'))
+                                        _('revisions')))
 
-            html_tmpl = '<span id="%s" style="display:none"> %s </span>'
-            cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
+            if not feed:
+                html_tmpl = '<span id="%s" style="display:none"> %s </span>'
+            else:
+                html_tmpl = '<span id="%s"> %s </span>'
+
+            cs_links.append(html_tmpl % (uniq_id, ', '.join([link_to(rev,
                 url('changeset_home',
-                repo_name=user_log.repository.repo_name,
-                revision=rev)) for rev in revs[revs_limit:] ]))
-
-        return cs_links
+                repo_name=repo_name, revision=rev),
+                title=message(rev), class_='tooltip')
+                for rev in revs[revs_limit:revs_top_limit]])))
+        if len(revs) > 1:
+            cs_links.append(compare_view)
+        return ''.join(cs_links)
 
     def get_fork_name():
         repo_name = action_params
-        return str(link_to(action_params, url('summary_home',
+        return _('fork name ') + str(link_to(action_params, url('summary_home',
                                           repo_name=repo_name,)))
 
-    map = {'user_deleted_repo':(_('[deleted] repository'), None),
+    action_map = {'user_deleted_repo':(_('[deleted] repository'), None),
            'user_created_repo':(_('[created] repository'), None),
-           'user_forked_repo':(_('[forked] repository as'), get_fork_name),
+           'user_forked_repo':(_('[forked] repository'), get_fork_name),
            'user_updated_repo':(_('[updated] repository'), None),
            'admin_deleted_repo':(_('[delete] repository'), None),
            'admin_created_repo':(_('[created] repository'), None),
            'admin_forked_repo':(_('[forked] repository'), None),
            'admin_updated_repo':(_('[updated] repository'), None),
-           'push':(_('[pushed] '), get_cs_links),
-           'pull':(_('[pulled] '), None),
+           'push':(_('[pushed] into'), get_cs_links),
+           'push_local':(_('[committed via RhodeCode] into'), get_cs_links),
+           'push_remote':(_('[pulled from remote] into'), get_cs_links),
+           'pull':(_('[pulled] from'), None),
            'started_following_repo':(_('[started following] repository'), None),
            'stopped_following_repo':(_('[stopped following] repository'), None),
             }
 
-    action_str = map.get(action, action)
-    action = action_str[0].replace('[', '<span class="journal_highlight">')\
+    action_str = action_map.get(action, action)
+    if feed:
+        action = action_str[0].replace('[', '').replace(']', '')
+    else:
+        action = action_str[0].replace('[', '<span class="journal_highlight">')\
                    .replace(']', '</span>')
+
     action_params_func = lambda :""
 
-    if action_str[1] is not None:
+    if callable(action_str[1]):
         action_params_func = action_str[1]
 
-    return literal(action + " " + action_params_func())
+    return [literal(action), action_params_func]
 
 def action_parser_icon(user_log):
     action = user_log.action
@@ -384,6 +433,7 @@
            'admin_forked_repo':'arrow_divide.png',
            'admin_updated_repo':'database_edit.png',
            'push':'script_add.png',
+           'push_local':'script_edit.png',
            'push_remote':'connect.png',
            'pull':'down_16.png',
            'started_following_repo':'heart_add.png',
@@ -402,9 +452,12 @@
 #==============================================================================
 # GRAVATAR URL
 #==============================================================================
-from pylons import request
 
 def gravatar_url(email_address, size=30):
+    if not str2bool(config['app_conf'].get('use_gravatar')) or \
+        email_address == 'anonymous@rhodecode.org':
+        return url("/images/user%s.png" % size)
+
     ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
     default = 'identicon'
     baseurl_nossl = "http://www.gravatar.com/avatar/"
@@ -413,19 +466,208 @@
 
     if isinstance(email_address, unicode):
         #hashlib crashes on unicode items
-        email_address = email_address.encode('utf8', 'replace')
+        email_address = safe_str(email_address)
     # construct the url
     gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
     gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
 
     return gravatar_url
 
+
+#==============================================================================
+# REPO PAGER, PAGER FOR REPOSITORY
+#==============================================================================
+class RepoPage(Page):
+
+    def __init__(self, collection, page=1, items_per_page=20,
+        item_count=None, url=None, branch_name=None, **kwargs):
+
+        """Create a "RepoPage" instance. special pager for paging
+        repository
+        """
+        self._url_generator = url
+
+        # Safe the kwargs class-wide so they can be used in the pager() method
+        self.kwargs = kwargs
+
+        # Save a reference to the collection
+        self.original_collection = collection
+
+        self.collection = collection
+
+        # The self.page is the number of the current page.
+        # The first page has the number 1!
+        try:
+            self.page = int(page) # make it int() if we get it as a string
+        except (ValueError, TypeError):
+            self.page = 1
+
+        self.items_per_page = items_per_page
+
+        # Unless the user tells us how many items the collections has
+        # we calculate that ourselves.
+        if item_count is not None:
+            self.item_count = item_count
+        else:
+            self.item_count = len(self.collection)
+
+        # Compute the number of the first and last available page
+        if self.item_count > 0:
+            self.first_page = 1
+            self.page_count = int(math.ceil(float(self.item_count) /
+                                            self.items_per_page))
+            self.last_page = self.first_page + self.page_count - 1
+
+            # Make sure that the requested page number is the range of valid pages
+            if self.page > self.last_page:
+                self.page = self.last_page
+            elif self.page < self.first_page:
+                self.page = self.first_page
+
+            # Note: the number of items on this page can be less than
+            #       items_per_page if the last page is not full
+            self.first_item = max(0, (self.item_count) - (self.page *
+                                                          items_per_page))
+            self.last_item = ((self.item_count - 1) - items_per_page *
+                              (self.page - 1))
+
+            iterator = self.collection.get_changesets(start=self.first_item,
+                                                      end=self.last_item,
+                                                      reverse=True,
+                                                      branch_name=branch_name)
+            self.items = list(iterator)
+
+            # Links to previous and next page
+            if self.page > self.first_page:
+                self.previous_page = self.page - 1
+            else:
+                self.previous_page = None
+
+            if self.page < self.last_page:
+                self.next_page = self.page + 1
+            else:
+                self.next_page = None
+
+        # No items available
+        else:
+            self.first_page = None
+            self.page_count = 0
+            self.last_page = None
+            self.first_item = None
+            self.last_item = None
+            self.previous_page = None
+            self.next_page = None
+            self.items = []
+
+        # This is a subclass of the 'list' type. Initialise the list now.
+        list.__init__(self, self.items)
+
+
 def changed_tooltip(nodes):
+    """
+    Generates a html string for changed nodes in changeset page.
+    It limits the output to 30 entries
+    
+    :param nodes: LazyNodesGenerator
+    """
     if nodes:
         pref = ': <br/> '
         suf = ''
         if len(nodes) > 30:
             suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
-        return literal(pref + '<br/> '.join([safe_unicode(x.path) for x in nodes[:30]]) + suf)
+        return literal(pref + '<br/> '.join([safe_unicode(x.path)
+                                             for x in nodes[:30]]) + suf)
     else:
         return ': ' + _('No Files')
+
+
+
+def repo_link(groups_and_repos):
+    """
+    Makes a breadcrumbs link to repo within a group
+    joins &raquo; on each group to create a fancy link
+    
+    ex::
+        group >> subgroup >> repo
+    
+    :param groups_and_repos:
+    """
+    groups, repo_name = groups_and_repos
+
+    if not groups:
+        return repo_name
+    else:
+        def make_link(group):
+            return link_to(group.group_name, url('repos_group',
+                                                 id=group.group_id))
+        return literal(' &raquo; '.join(map(make_link, groups)) + \
+                       " &raquo; " + repo_name)
+
+
+def fancy_file_stats(stats):
+    """
+    Displays a fancy two colored bar for number of added/deleted
+    lines of code on file
+    
+    :param stats: two element list of added/deleted lines of code
+    """
+
+    a, d, t = stats[0], stats[1], stats[0] + stats[1]
+    width = 100
+    unit = float(width) / (t or 1)
+
+    # needs > 9% of width to be visible or 0 to be hidden
+    a_p = max(9, unit * a) if a > 0 else 0
+    d_p = max(9, unit * d) if d > 0 else 0
+    p_sum = a_p + d_p
+
+    if p_sum > width:
+        #adjust the percentage to be == 100% since we adjusted to 9
+        if a_p > d_p:
+            a_p = a_p - (p_sum - width)
+        else:
+            d_p = d_p - (p_sum - width)
+
+    a_v = a if a > 0 else ''
+    d_v = d if d > 0 else ''
+
+
+    def cgen(l_type):
+        mapping = {'tr':'top-right-rounded-corner',
+                   'tl':'top-left-rounded-corner',
+                   'br':'bottom-right-rounded-corner',
+                   'bl':'bottom-left-rounded-corner'}
+        map_getter = lambda x:mapping[x]
+
+        if l_type == 'a' and d_v:
+            #case when added and deleted are present
+            return ' '.join(map(map_getter, ['tl', 'bl']))
+
+        if l_type == 'a' and not d_v:
+            return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
+
+        if l_type == 'd' and a_v:
+            return ' '.join(map(map_getter, ['tr', 'br']))
+
+        if l_type == 'd' and not a_v:
+            return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
+
+
+
+    d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (cgen('a'),
+                                                                 a_p, a_v)
+    d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (cgen('d'),
+                                                                   d_p, d_v)
+    return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
+
+
+def urlify_text(text):
+    import re
+
+    url_pat = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)')
+
+    def url_func(match_obj):
+        url_full = match_obj.groups()[0]
+        return '<a href="%(url)s">%(url)s</a>' % ({'url':url_full})
+
+    return literal(url_pat.sub(url_func, text))
--- a/rhodecode/lib/hooks.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/hooks.py	Fri Oct 07 01:08:50 2011 +0200
@@ -24,14 +24,14 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import os
 import sys
-import getpass
 
-from mercurial.cmdutil import revrange
+from mercurial.scmutil import revrange
 from mercurial.node import nullrev
 
 from rhodecode.lib import helpers as h
 from rhodecode.lib.utils import action_logger
 
+
 def repo_size(ui, repo, hooktype=None, **kwargs):
     """Presents size of repository after push
 
@@ -63,6 +63,7 @@
     sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
                      % (size_hg_f, size_root_f, size_total_f))
 
+
 def log_pull_action(ui, repo, **kwargs):
     """Logs user last pull action
 
@@ -79,6 +80,7 @@
 
     return 0
 
+
 def log_push_action(ui, repo, **kwargs):
     """Maps user last push action to new changeset id, from mercurial
 
@@ -89,7 +91,7 @@
     extra_params = dict(repo.ui.configitems('rhodecode_extras'))
     username = extra_params['username']
     repository = extra_params['repository']
-    action = 'push:%s'
+    action = extra_params['action'] + ':%s'
     node = kwargs['node']
 
     def get_revs(repo, rev_opt):
--- a/rhodecode/lib/indexers/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/indexers/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -31,17 +31,7 @@
 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
 
 from string import strip
-
-from rhodecode.model import init_model
-from rhodecode.model.scm import ScmModel
-from rhodecode.config.environment import load_environment
-from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
-
 from shutil import rmtree
-from webhelpers.html.builder import escape
-from vcs.utils.lazy import LazyProperty
-
-from sqlalchemy import engine_from_config
 
 from whoosh.analysis import RegexTokenizer, LowercaseFilter, StopFilter
 from whoosh.fields import TEXT, ID, STORED, Schema, FieldType
@@ -49,15 +39,19 @@
 from whoosh.formats import Characters
 from whoosh.highlight import highlight, SimpleFragmenter, HtmlFormatter
 
+from webhelpers.html.builder import escape
+from sqlalchemy import engine_from_config
+from vcs.utils.lazy import LazyProperty
+
+from rhodecode.model import init_model
+from rhodecode.model.scm import ScmModel
+from rhodecode.model.repo import RepoModel
+from rhodecode.config.environment import load_environment
+from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP
+from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
 
 #EXTENSIONS WE WANT TO INDEX CONTENT OFF
-INDEX_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c',
-                    'cfg', 'cfm', 'cpp', 'cs', 'css', 'diff', 'do', 'el', 'erl',
-                    'h', 'htm', 'html', 'ini', 'java', 'js', 'jsp', 'jspx', 'lisp',
-                    'lua', 'm', 'mako', 'ml', 'pas', 'patch', 'php', 'php3',
-                    'php4', 'phtml', 'pm', 'py', 'rb', 'rst', 's', 'sh', 'sql',
-                    'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt',
-                    'yaws']
+INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
 
 #CUSTOM ANALYZER wordsplit + lowercase filter
 ANALYZER = RegexTokenizer(expression=r"\w+") | LowercaseFilter()
@@ -96,7 +90,10 @@
         init_model(engine)
 
         index_location = config['index_dir']
-        repo_location = self.options.repo_location
+        repo_location = self.options.repo_location \
+            if self.options.repo_location else RepoModel().repos_path
+        repo_list = map(strip, self.options.repo_list.split(',')) \
+            if self.options.repo_list else None
 
         #======================================================================
         # WHOOSH DAEMON
@@ -104,9 +101,10 @@
         from rhodecode.lib.pidlock import LockHeld, DaemonLock
         from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
         try:
-            l = DaemonLock()
+            l = DaemonLock(file=jn(dn(dn(index_location)), 'make_index.lock'))
             WhooshIndexingDaemon(index_location=index_location,
-                                 repo_location=repo_location)\
+                                 repo_location=repo_location,
+                                 repo_list=repo_list)\
                 .run(full_index=self.options.full_index)
             l.release()
         except LockHeld:
@@ -116,7 +114,13 @@
         self.parser.add_option('--repo-location',
                           action='store',
                           dest='repo_location',
-                          help="Specifies repositories location to index REQUIRED",
+                          help="Specifies repositories location to index OPTIONAL",
+                          )
+        self.parser.add_option('--index-only',
+                          action='store',
+                          dest='repo_list',
+                          help="Specifies a comma separated list of repositores "
+                                "to build index on OPTIONAL",
                           )
         self.parser.add_option('-f',
                           action='store_true',
@@ -194,8 +198,9 @@
         Smart function that implements chunking the content
         but not overlap chunks so it doesn't highlight the same
         close occurrences twice.
-        @param matcher:
-        @param size:
+        
+        :param matcher:
+        :param size:
         """
         memory = [(0, 0)]
         for span in self.matcher.spans():
--- a/rhodecode/lib/indexers/daemon.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/indexers/daemon.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,8 +1,15 @@
-#!/usr/bin/env python
-# encoding: utf-8
-# whoosh indexer daemon for rhodecode
-# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
-#
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.lib.indexers.daemon
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    A daemon will read from task table and run tasks
+
+    :created_on: Jan 26, 2010
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
@@ -15,14 +22,15 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-Created on Jan 26, 2010
 
-@author: marcink
-A deamon will read from task table and run tasks
-"""
+import os
 import sys
-import os
+import logging
+import traceback
+
+from shutil import rmtree
+from time import mktime
+
 from os.path import dirname as dn
 from os.path import join as jn
 
@@ -32,15 +40,14 @@
 
 
 from rhodecode.model.scm import ScmModel
-from rhodecode.lib.helpers import safe_unicode
-from whoosh.index import create_in, open_dir
-from shutil import rmtree
+from rhodecode.lib import safe_unicode
 from rhodecode.lib.indexers import INDEX_EXTENSIONS, SCHEMA, IDX_NAME
 
-from time import mktime
 from vcs.exceptions import ChangesetError, RepositoryError
 
-import logging
+from whoosh.index import create_in, open_dir
+
+
 
 log = logging.getLogger('whooshIndexer')
 # create logger
@@ -51,7 +58,8 @@
 ch.setLevel(logging.DEBUG)
 
 # create formatter
-formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
+formatter = logging.Formatter("%(asctime)s - %(name)s -"
+                              " %(levelname)s - %(message)s")
 
 # add formatter to ch
 ch.setFormatter(formatter)
@@ -61,11 +69,11 @@
 
 class WhooshIndexingDaemon(object):
     """
-    Deamon for atomic jobs
+    Daemon for atomic jobs
     """
 
     def __init__(self, indexname='HG_INDEX', index_location=None,
-                 repo_location=None, sa=None):
+                 repo_location=None, sa=None, repo_list=None):
         self.indexname = indexname
 
         self.index_location = index_location
@@ -76,7 +84,17 @@
         if not repo_location:
             raise Exception('You have to provide repositories location')
 
-        self.repo_paths = ScmModel(sa).repo_scan(self.repo_location, None)
+        self.repo_paths = ScmModel(sa).repo_scan(self.repo_location)
+
+        if repo_list:
+            filtered_repo_paths = {}
+            for repo_name, repo in self.repo_paths.items():
+                if repo_name in repo_list:
+                    filtered_repo_paths[repo_name] = repo
+
+            self.repo_paths = filtered_repo_paths
+
+
         self.initial = False
         if not os.path.isdir(self.index_location):
             os.makedirs(self.index_location)
@@ -90,14 +108,13 @@
         """
         index_paths_ = set()
         try:
-            for topnode, dirs, files in repo.walk('/', 'tip'):
+            tip = repo.get_changeset('tip')
+            for topnode, dirs, files in tip.walk('/'):
                 for f in files:
                     index_paths_.add(jn(repo.path, f.path))
-                for dir in dirs:
-                    for f in files:
-                        index_paths_.add(jn(repo.path, f.path))
 
-        except RepositoryError:
+        except RepositoryError, e:
+            log.debug(traceback.format_exc())
             pass
         return index_paths_
 
@@ -109,14 +126,14 @@
     def get_node_mtime(self, node):
         return mktime(node.last_changeset.date.timetuple())
 
-    def add_doc(self, writer, path, repo):
+    def add_doc(self, writer, path, repo, repo_name):
         """Adding doc to writer this function itself fetches data from
         the instance of vcs backend"""
         node = self.get_node(repo, path)
 
         #we just index the content of chosen files, and skip binary files
         if node.extension in INDEX_EXTENSIONS and not node.is_binary:
-            
+
             u_content = node.content
             if not isinstance(u_content, unicode):
                 log.warning('  >> %s Could not get this content as unicode '
@@ -124,14 +141,14 @@
                 u_content = u''
             else:
                 log.debug('    >> %s [WITH CONTENT]' % path)
-                
+
         else:
             log.debug('    >> %s' % path)
             #just index file name without it's content
             u_content = u''
 
         writer.add_document(owner=unicode(repo.contact),
-                        repository=safe_unicode(repo.name),
+                        repository=safe_unicode(repo_name),
                         path=safe_unicode(path),
                         content=u_content,
                         modtime=self.get_node_mtime(node),
@@ -149,11 +166,11 @@
         idx = create_in(self.index_location, SCHEMA, indexname=IDX_NAME)
         writer = idx.writer()
 
-        for cnt, repo in enumerate(self.repo_paths.values()):
+        for repo_name, repo in self.repo_paths.items():
             log.debug('building index @ %s' % repo.path)
 
             for idx_path in self.get_paths(repo):
-                self.add_doc(writer, idx_path, repo)
+                self.add_doc(writer, idx_path, repo, repo_name)
 
         log.debug('>> COMMITING CHANGES <<')
         writer.commit(merge=True)
@@ -200,12 +217,12 @@
         # Loop over the files in the filesystem
         # Assume we have a function that gathers the filenames of the
         # documents to be indexed
-        for repo in self.repo_paths.values():
+        for repo_name, repo in self.repo_paths.items():
             for path in self.get_paths(repo):
                 if path in to_index or path not in indexed_paths:
                     # This is either a file that's changed, or a new file
                     # that wasn't indexed before. So index it!
-                    self.add_doc(writer, path, repo)
+                    self.add_doc(writer, path, repo, repo_name)
                     log.debug('re indexing %s' % path)
 
         log.debug('>> COMMITING CHANGES <<')
--- a/rhodecode/lib/middleware/https_fixup.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/middleware/https_fixup.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     middleware to handle https correctly
-    
+
     :created_on: May 23, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -25,7 +25,9 @@
 
 from rhodecode.lib import str2bool
 
+
 class HttpsFixup(object):
+
     def __init__(self, app, config):
         self.application = app
         self.config = config
@@ -34,10 +36,10 @@
         self.__fixup(environ)
         return self.application(environ, start_response)
 
-
     def __fixup(self, environ):
-        """Function to fixup the environ as needed. In order to use this
-        middleware you should set this header inside your 
+        """
+        Function to fixup the environ as needed. In order to use this
+        middleware you should set this header inside your
         proxy ie. nginx, apache etc.
         """
         proto = environ.get('HTTP_X_URL_SCHEME')
--- a/rhodecode/lib/middleware/simplegit.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/middleware/simplegit.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,8 +1,16 @@
-#!/usr/bin/env python
-# encoding: utf-8
-# middleware to handle git api calls
-# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
-#
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.lib.middleware.simplegit
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    SimpleGit middleware for handling git protocol request (push/clone etc.)
+    It's implemented with basic auth function
+
+    :created_on: Apr 28, 2010
+    :author: marcink
+    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
@@ -15,34 +23,33 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-Created on 2010-04-28
 
-@author: marcink
-SimpleGit middleware for handling git protocol request (push/clone etc.)
-It's implemented with basic auth function
-"""
+import os
+import logging
+import traceback
 
 from dulwich import server as dulserver
 
+
 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler):
 
     def handle(self):
         write = lambda x: self.proto.write_sideband(1, x)
 
-        graph_walker = dulserver.ProtocolGraphWalker(self, self.repo.object_store,
-            self.repo.get_peeled)
+        graph_walker = dulserver.ProtocolGraphWalker(self,
+                                                     self.repo.object_store,
+                                                     self.repo.get_peeled)
         objects_iter = self.repo.fetch_objects(
           graph_walker.determine_wants, graph_walker, self.progress,
           get_tagged=self.get_tagged)
 
         # Do they want any objects?
-        if len(objects_iter) == 0:
+        if objects_iter is None or len(objects_iter) == 0:
             return
 
         self.progress("counting objects: %d, done.\n" % len(objects_iter))
-        dulserver.write_pack_data(dulserver.ProtocolFile(None, write), objects_iter,
-                        len(objects_iter))
+        dulserver.write_pack_objects(dulserver.ProtocolFile(None, write),
+                                  objects_iter, len(objects_iter))
         messages = []
         messages.append('thank you for using rhodecode')
 
@@ -58,23 +65,24 @@
 
 from dulwich.repo import Repo
 from dulwich.web import HTTPGitApplication
+
 from paste.auth.basic import AuthBasicAuthenticator
 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
+
+from rhodecode.lib import safe_str
 from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
-from rhodecode.lib.utils import invalidate_cache, check_repo_fast
-from rhodecode.model.user import UserModel
+from rhodecode.lib.utils import invalidate_cache, is_valid_repo
+from rhodecode.model.db import User
+
 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
-import logging
-import os
-import traceback
 
 log = logging.getLogger(__name__)
 
+
 def is_git(environ):
-    """
-    Returns True if request's target is git server. ``HTTP_USER_AGENT`` would
-    then have git client version given.
-    
+    """Returns True if request's target is git server.
+    ``HTTP_USER_AGENT`` would then have git client version given.
+
     :param environ:
     """
     http_user_agent = environ.get('HTTP_USER_AGENT')
@@ -82,17 +90,16 @@
         return True
     return False
 
+
 class SimpleGit(object):
 
     def __init__(self, application, config):
         self.application = application
         self.config = config
-        #authenticate this git request using 
+        # base path of repo locations
+        self.basepath = self.config['base_path']
+        #authenticate this mercurial request using authfunc
         self.authenticate = AuthBasicAuthenticator('', authfunc)
-        self.ipaddr = '0.0.0.0'
-        self.repository = None
-        self.username = None
-        self.action = None
 
     def __call__(self, environ, start_response):
         if not is_git(environ):
@@ -100,105 +107,166 @@
 
         proxy_key = 'HTTP_X_REAL_IP'
         def_key = 'REMOTE_ADDR'
-        self.ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
+        ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
+        username = None
+        # skip passing error to error controller
+        environ['pylons.status_code_redirect'] = True
+
+        #======================================================================
+        # EXTRACT REPOSITORY NAME FROM ENV
+        #======================================================================
+        try:
+            repo_name = self.__get_repository(environ)
+            log.debug('Extracted repo name is %s' % repo_name)
+        except:
+            return HTTPInternalServerError()(environ, start_response)
+
+        #======================================================================
+        # GET ACTION PULL or PUSH
+        #======================================================================
+        action = self.__get_action(environ)
+
+        #======================================================================
+        # CHECK ANONYMOUS PERMISSION
+        #======================================================================
+        if action in ['pull', 'push']:
+            anonymous_user = self.__get_user('default')
+            username = anonymous_user.username
+            anonymous_perm = self.__check_permission(action,
+                                                     anonymous_user,
+                                                     repo_name)
+
+            if anonymous_perm is not True or anonymous_user.active is False:
+                if anonymous_perm is not True:
+                    log.debug('Not enough credentials to access this '
+                              'repository as anonymous user')
+                if anonymous_user.active is False:
+                    log.debug('Anonymous access is disabled, running '
+                              'authentication')
+                #==============================================================
+                # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
+                # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
+                #==============================================================
+
+                if not REMOTE_USER(environ):
+                    self.authenticate.realm = \
+                        safe_str(self.config['rhodecode_realm'])
+                    result = self.authenticate(environ)
+                    if isinstance(result, str):
+                        AUTH_TYPE.update(environ, 'basic')
+                        REMOTE_USER.update(environ, result)
+                    else:
+                        return result.wsgi_application(environ, start_response)
+
+                #==============================================================
+                # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM
+                # BASIC AUTH
+                #==============================================================
+
+                if action in ['pull', 'push']:
+                    username = REMOTE_USER(environ)
+                    try:
+                        user = self.__get_user(username)
+                        username = user.username
+                    except:
+                        log.error(traceback.format_exc())
+                        return HTTPInternalServerError()(environ,
+                                                         start_response)
+
+                    #check permissions for this repository
+                    perm = self.__check_permission(action, user,
+                                                   repo_name)
+                    if perm is not True:
+                        return HTTPForbidden()(environ, start_response)
+
+        extras = {'ip': ipaddr,
+                  'username': username,
+                  'action': action,
+                  'repository': repo_name}
 
         #===================================================================
-        # AUTHENTICATE THIS GIT REQUEST
+        # GIT REQUEST HANDLING
         #===================================================================
-        username = REMOTE_USER(environ)
-        if not username:
-            self.authenticate.realm = self.config['rhodecode_realm']
-            result = self.authenticate(environ)
-            if isinstance(result, str):
-                AUTH_TYPE.update(environ, 'basic')
-                REMOTE_USER.update(environ, result)
-            else:
-                return result.wsgi_application(environ, start_response)
+
+        repo_path = safe_str(os.path.join(self.basepath, repo_name))
+        log.debug('Repository path is %s' % repo_path)
+
+        # quick check if that dir exists...
+        if is_valid_repo(repo_name, self.basepath) is False:
+            return HTTPNotFound()(environ, start_response)
+
+        try:
+            #invalidate cache on push
+            if action == 'push':
+                self.__invalidate_cache(repo_name)
+
+            app = self.__make_app(repo_name, repo_path)
+            return app(environ, start_response)
+        except Exception:
+            log.error(traceback.format_exc())
+            return HTTPInternalServerError()(environ, start_response)
+
+    def __make_app(self, repo_name, repo_path):
+        """
+        Make an wsgi application using dulserver
+        
+        :param repo_name: name of the repository
+        :param repo_path: full path to the repository
+        """
+
+        _d = {'/' + repo_name: Repo(repo_path)}
+        backend = dulserver.DictBackend(_d)
+        gitserve = HTTPGitApplication(backend)
 
-        #=======================================================================
-        # GET REPOSITORY
-        #=======================================================================
+        return gitserve
+
+    def __check_permission(self, action, user, repo_name):
+        """
+        Checks permissions using action (push/pull) user and repository
+        name
+
+        :param action: push or pull action
+        :param user: user instance
+        :param repo_name: repository name
+        """
+        if action == 'push':
+            if not HasPermissionAnyMiddleware('repository.write',
+                                              'repository.admin')(user,
+                                                                  repo_name):
+                return False
+
+        else:
+            #any other action need at least read permission
+            if not HasPermissionAnyMiddleware('repository.read',
+                                              'repository.write',
+                                              'repository.admin')(user,
+                                                                  repo_name):
+                return False
+
+        return True
+
+    def __get_repository(self, environ):
+        """
+        Get's repository name out of PATH_INFO header
+
+        :param environ: environ where PATH_INFO is stored
+        """
         try:
             repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
             if repo_name.endswith('/'):
                 repo_name = repo_name.rstrip('/')
-            self.repository = repo_name
         except:
             log.error(traceback.format_exc())
-            return HTTPInternalServerError()(environ, start_response)
-
-        #===================================================================
-        # CHECK PERMISSIONS FOR THIS REQUEST
-        #===================================================================
-        self.action = self.__get_action(environ)
-        if self.action:
-            username = self.__get_environ_user(environ)
-            try:
-                user = self.__get_user(username)
-                self.username = user.username
-            except:
-                log.error(traceback.format_exc())
-                return HTTPInternalServerError()(environ, start_response)
-
-            #check permissions for this repository
-            if self.action == 'push':
-                if not HasPermissionAnyMiddleware('repository.write',
-                                                  'repository.admin')\
-                                                    (user, repo_name):
-                    return HTTPForbidden()(environ, start_response)
-
-            else:
-                #any other action need at least read permission
-                if not HasPermissionAnyMiddleware('repository.read',
-                                                  'repository.write',
-                                                  'repository.admin')\
-                                                    (user, repo_name):
-                    return HTTPForbidden()(environ, start_response)
-
-        self.extras = {'ip':self.ipaddr,
-                       'username':self.username,
-                       'action':self.action,
-                       'repository':self.repository}
-
-        #===================================================================
-        # GIT REQUEST HANDLING
-        #===================================================================
-        self.basepath = self.config['base_path']
-        self.repo_path = os.path.join(self.basepath, self.repo_name)
-        #quick check if that dir exists...
-        if check_repo_fast(self.repo_name, self.basepath):
-            return HTTPNotFound()(environ, start_response)
-        try:
-            app = self.__make_app()
-        except:
-            log.error(traceback.format_exc())
-            return HTTPInternalServerError()(environ, start_response)
-
-        #invalidate cache on push
-        if self.action == 'push':
-            self.__invalidate_cache(self.repo_name)
-            messages = []
-            messages.append('thank you for using rhodecode')
-            return app(environ, start_response)
-        else:
-            return app(environ, start_response)
-
-
-    def __make_app(self):
-        backend = dulserver.DictBackend({'/' + self.repo_name: Repo(self.repo_path)})
-        gitserve = HTTPGitApplication(backend)
-
-        return gitserve
-
-    def __get_environ_user(self, environ):
-        return environ.get('REMOTE_USER')
+            raise
+        repo_name = repo_name.split('/')[0]
+        return repo_name
 
     def __get_user(self, username):
-        return UserModel().get_by_username(username, cache=True)
+        return User.by_username(username)
 
     def __get_action(self, environ):
-        """
-        Maps git request commands into a pull or push command.
+        """Maps git request commands into a pull or push command.
+
         :param environ:
         """
         service = environ['QUERY_STRING'].split('=')
@@ -208,7 +276,8 @@
                        'git-upload-pack': 'pull',
                        }
 
-            return mapping.get(service_cmd, service_cmd if service_cmd else 'other')
+            return mapping.get(service_cmd,
+                               service_cmd if service_cmd else 'other')
         else:
             return 'other'
 
@@ -217,3 +286,4 @@
         invalidate the cache to see the changes right away but only for
         push requests"""
         invalidate_cache('get_repo_cached_%s' % repo_name)
+
--- a/rhodecode/lib/middleware/simplehg.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/middleware/simplehg.py	Fri Oct 07 01:08:50 2011 +0200
@@ -29,24 +29,24 @@
 import traceback
 
 from mercurial.error import RepoError
-from mercurial.hgweb import hgweb
-from mercurial.hgweb.request import wsgiapplication
+from mercurial.hgweb import hgweb_mod
+
 from paste.auth.basic import AuthBasicAuthenticator
 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
+
+from rhodecode.lib import safe_str
 from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
 from rhodecode.lib.utils import make_ui, invalidate_cache, \
-    check_repo_fast, ui_sections
-from rhodecode.model.user import UserModel
+    is_valid_repo, ui_sections
+from rhodecode.model.db import User
+
 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
-import logging
-import os
-import traceback
 
 log = logging.getLogger(__name__)
 
+
 def is_mercurial(environ):
-    """
-    Returns True if request's target is mercurial server - header
+    """Returns True if request's target is mercurial server - header
     ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
     """
     http_accept = environ.get('HTTP_ACCEPT')
@@ -54,17 +54,17 @@
         return True
     return False
 
+
 class SimpleHg(object):
 
     def __init__(self, application, config):
         self.application = application
         self.config = config
+        # base path of repo locations
+        self.basepath = self.config['base_path']
         #authenticate this mercurial request using authfunc
         self.authenticate = AuthBasicAuthenticator('', authfunc)
         self.ipaddr = '0.0.0.0'
-        self.repository = None
-        self.username = None
-        self.action = None
 
     def __call__(self, environ, start_response):
         if not is_mercurial(environ):
@@ -72,82 +72,105 @@
 
         proxy_key = 'HTTP_X_REAL_IP'
         def_key = 'REMOTE_ADDR'
-        self.ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
+        ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
+
         # skip passing error to error controller
         environ['pylons.status_code_redirect'] = True
-
-        #===================================================================
-        # AUTHENTICATE THIS MERCURIAL REQUEST
-        #===================================================================
-        username = REMOTE_USER(environ)
-
-        if not username:
-            self.authenticate.realm = str(self.config['rhodecode_realm'])
-            result = self.authenticate(environ)
-            if isinstance(result, str):
-                AUTH_TYPE.update(environ, 'basic')
-                REMOTE_USER.update(environ, result)
-            else:
-                return result.wsgi_application(environ, start_response)
-
-        #=======================================================================
-        # GET REPOSITORY
-        #=======================================================================
+                
+        #======================================================================
+        # EXTRACT REPOSITORY NAME FROM ENV
+        #======================================================================
         try:
-            repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
-            if repo_name.endswith('/'):
-                repo_name = repo_name.rstrip('/')
-            self.repository = repo_name
+            repo_name = environ['REPO_NAME'] = self.__get_repository(environ)
+            log.debug('Extracted repo name is %s' % repo_name)
         except:
-            log.error(traceback.format_exc())
             return HTTPInternalServerError()(environ, start_response)
 
-        #===================================================================
-        # CHECK PERMISSIONS FOR THIS REQUEST
-        #===================================================================
-        self.action = self.__get_action(environ)
-        if self.action:
-            username = self.__get_environ_user(environ)
-            try:
-                user = self.__get_user(username)
-                self.username = user.username
-            except:
-                log.error(traceback.format_exc())
-                return HTTPInternalServerError()(environ, start_response)
+        #======================================================================
+        # GET ACTION PULL or PUSH
+        #======================================================================
+        action = self.__get_action(environ)
+        
+        #======================================================================
+        # CHECK ANONYMOUS PERMISSION
+        #======================================================================
+        if action in ['pull', 'push']:
+            anonymous_user = self.__get_user('default')
+            username = anonymous_user.username
+            anonymous_perm = self.__check_permission(action,
+                                                     anonymous_user,
+                                                     repo_name)
 
-            #check permissions for this repository
-            if self.action == 'push':
-                if not HasPermissionAnyMiddleware('repository.write',
-                                                  'repository.admin')\
-                                                    (user, repo_name):
-                    return HTTPForbidden()(environ, start_response)
+            if anonymous_perm is not True or anonymous_user.active is False:
+                if anonymous_perm is not True:
+                    log.debug('Not enough credentials to access this '
+                              'repository as anonymous user')
+                if anonymous_user.active is False:
+                    log.debug('Anonymous access is disabled, running '
+                              'authentication')
+                #==============================================================
+                # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
+                # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
+                #==============================================================
+
+                if not REMOTE_USER(environ):
+                    self.authenticate.realm = \
+                        safe_str(self.config['rhodecode_realm'])
+                    result = self.authenticate(environ)
+                    if isinstance(result, str):
+                        AUTH_TYPE.update(environ, 'basic')
+                        REMOTE_USER.update(environ, result)
+                    else:
+                        return result.wsgi_application(environ, start_response)
+
+                #==============================================================
+                # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM
+                # BASIC AUTH
+                #==============================================================
 
-            else:
-                #any other action need at least read permission
-                if not HasPermissionAnyMiddleware('repository.read',
-                                                  'repository.write',
-                                                  'repository.admin')\
-                                                    (user, repo_name):
-                    return HTTPForbidden()(environ, start_response)
+                if action in ['pull', 'push']:
+                    username = REMOTE_USER(environ)
+                    try:
+                        user = self.__get_user(username)
+                        username = user.username
+                    except:
+                        log.error(traceback.format_exc())
+                        return HTTPInternalServerError()(environ,
+                                                         start_response)
 
-        self.extras = {'ip':self.ipaddr,
-                       'username':self.username,
-                       'action':self.action,
-                       'repository':self.repository}
+                    #check permissions for this repository
+                    perm = self.__check_permission(action, user,
+                                                   repo_name)
+                    if perm is not True:
+                        return HTTPForbidden()(environ, start_response)
+
+        extras = {'ip': ipaddr,
+                  'username': username,
+                  'action': action,
+                  'repository': repo_name}
 
-        #===================================================================
+        #======================================================================
         # MERCURIAL REQUEST HANDLING
-        #===================================================================
-        environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path
-        self.baseui = make_ui('db')
-        self.basepath = self.config['base_path']
-        self.repo_path = os.path.join(self.basepath, repo_name)
+        #======================================================================
+        
+        repo_path = safe_str(os.path.join(self.basepath, repo_name))
+        log.debug('Repository path is %s' % repo_path)
+        
+        baseui = make_ui('db')
+        self.__inject_extras(repo_path, baseui, extras)
+        
 
-        #quick check if that dir exists...
-        if check_repo_fast(repo_name, self.basepath):
+        # quick check if that dir exists...
+        if is_valid_repo(repo_name, self.basepath) is False:
             return HTTPNotFound()(environ, start_response)
+
         try:
-            app = wsgiapplication(self.__make_app)
+            #invalidate cache on push
+            if action == 'push':
+                self.__invalidate_cache(repo_name)
+
+            app = self.__make_app(repo_path, baseui, extras)
+            return app(environ, start_response)
         except RepoError, e:
             if str(e).find('not found') != -1:
                 return HTTPNotFound()(environ, start_response)
@@ -155,27 +178,63 @@
             log.error(traceback.format_exc())
             return HTTPInternalServerError()(environ, start_response)
 
-        #invalidate cache on push
-        if self.action == 'push':
-            self.__invalidate_cache(repo_name)
-
-        return app(environ, start_response)
+    def __make_app(self, repo_name, baseui, extras):
+        """
+        Make an wsgi application using hgweb, and inject generated baseui
+        instance, additionally inject some extras into ui object
+        """
+        return hgweb_mod.hgweb(repo_name, name=repo_name, baseui=baseui)
 
 
-    def __make_app(self):
-        hgserve = hgweb(str(self.repo_path), baseui=self.baseui)
-        return  self.__load_web_settings(hgserve, self.extras)
+    def __check_permission(self, action, user, repo_name):
+        """
+        Checks permissions using action (push/pull) user and repository
+        name
+
+        :param action: push or pull action
+        :param user: user instance
+        :param repo_name: repository name
+        """
+        if action == 'push':
+            if not HasPermissionAnyMiddleware('repository.write',
+                                              'repository.admin')(user,
+                                                                  repo_name):
+                return False
 
-    def __get_environ_user(self, environ):
-        return environ.get('REMOTE_USER')
+        else:
+            #any other action need at least read permission
+            if not HasPermissionAnyMiddleware('repository.read',
+                                              'repository.write',
+                                              'repository.admin')(user,
+                                                                  repo_name):
+                return False
+
+        return True
+
+    def __get_repository(self, environ):
+        """
+        Get's repository name out of PATH_INFO header
+
+        :param environ: environ where PATH_INFO is stored
+        """
+        try:
+            repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
+            if repo_name.endswith('/'):
+                repo_name = repo_name.rstrip('/')
+        except:
+            log.error(traceback.format_exc())
+            raise
+
+        return repo_name
 
     def __get_user(self, username):
-        return UserModel().get_by_username(username, cache=True)
+        return User.by_username(username)
 
     def __get_action(self, environ):
         """
         Maps mercurial request commands into a clone,pull or push command.
         This should always return a valid command string
+
         :param environ:
         """
         mapping = {'changegroup': 'pull',
@@ -187,10 +246,10 @@
         for qry in environ['QUERY_STRING'].split('&'):
             if qry.startswith('cmd'):
                 cmd = qry.split('=')[-1]
-                if mapping.has_key(cmd):
+                if cmd in mapping:
                     return mapping[cmd]
                 else:
-                    return cmd
+                    return 'pull'
 
     def __invalidate_cache(self, repo_name):
         """we know that some change was made to repositories and we should
@@ -198,17 +257,25 @@
         push requests"""
         invalidate_cache('get_repo_cached_%s' % repo_name)
 
+    def __inject_extras(self,repo_path, baseui, extras={}):
+        """
+        Injects some extra params into baseui instance
+        
+        also overwrites global settings with those takes from local hgrc file
+        
+        :param baseui: baseui instance
+        :param extras: dict with extra params to put into baseui
+        """
 
-    def __load_web_settings(self, hgserve, extras={}):
-        #set the global ui for hgserve instance passed
-        hgserve.repo.ui = self.baseui
+        hgrc = os.path.join(repo_path, '.hg', 'hgrc')
 
-        hgrc = os.path.join(self.repo_path, '.hg', 'hgrc')
+        # make our hgweb quiet so it doesn't print output
+        baseui.setconfig('ui', 'quiet', 'true')
 
         #inject some additional parameters that will be available in ui
         #for hooks
         for k, v in extras.items():
-            hgserve.repo.ui.setconfig('rhodecode_extras', k, v)
+            baseui.setconfig('rhodecode_extras', k, v)
 
         repoui = make_ui('file', hgrc, False)
 
@@ -216,20 +283,5 @@
             #overwrite our ui instance with the section from hgrc file
             for section in ui_sections:
                 for k, v in repoui.configitems(section):
-                    hgserve.repo.ui.setconfig(section, k, v)
-
-        return hgserve
-
-
-
-
-
+                    baseui.setconfig(section, k, v)
 
-
-
-
-
-
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/lib/odict.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,291 @@
+# Python Software Foundation License
+
+# XXX: it feels like using the class with "is" and "is not" instead of "==" and
+# "!=" should be faster.
+class _Nil(object):
+
+    def __repr__(self):
+        return "nil"
+
+    def __eq__(self, other):
+        if (isinstance(other, _Nil)):
+            return True
+        else:
+            return NotImplemented
+
+    def __ne__(self, other):
+        if (isinstance(other, _Nil)):
+            return False
+        else:
+            return NotImplemented
+
+_nil = _Nil()
+
+class _odict(object):
+    """Ordered dict data structure, with O(1) complexity for dict operations
+    that modify one element.
+    
+    Overwriting values doesn't change their original sequential order.
+    """
+
+    def _dict_impl(self):
+        return None
+
+    def __init__(self, data=(), **kwds):
+        """This doesn't accept keyword initialization as normal dicts to avoid
+        a trap - inside a function or method the keyword args are accessible
+        only as a dict, without a defined order, so their original order is
+        lost.
+        """
+        if kwds:
+            raise TypeError("__init__() of ordered dict takes no keyword "
+                            "arguments to avoid an ordering trap.")
+        self._dict_impl().__init__(self)
+        # If you give a normal dict, then the order of elements is undefined
+        if hasattr(data, "iteritems"):
+            for key, val in data.iteritems():
+                self[key] = val
+        else:
+            for key, val in data:
+                self[key] = val
+
+    # Double-linked list header
+    def _get_lh(self):
+        dict_impl = self._dict_impl()
+        if not hasattr(self, '_lh'):
+            dict_impl.__setattr__(self, '_lh', _nil)
+        return dict_impl.__getattribute__(self, '_lh')
+
+    def _set_lh(self, val):
+        self._dict_impl().__setattr__(self, '_lh', val)
+
+    lh = property(_get_lh, _set_lh)
+
+    # Double-linked list tail
+    def _get_lt(self):
+        dict_impl = self._dict_impl()
+        if not hasattr(self, '_lt'):
+            dict_impl.__setattr__(self, '_lt', _nil)
+        return dict_impl.__getattribute__(self, '_lt')
+
+    def _set_lt(self, val):
+        self._dict_impl().__setattr__(self, '_lt', val)
+
+    lt = property(_get_lt, _set_lt)
+
+    def __getitem__(self, key):
+        return self._dict_impl().__getitem__(self, key)[1]
+
+    def __setitem__(self, key, val):
+        dict_impl = self._dict_impl()
+        try:
+            dict_impl.__getitem__(self, key)[1] = val
+        except KeyError, e:
+            new = [dict_impl.__getattribute__(self, 'lt'), val, _nil]
+            dict_impl.__setitem__(self, key, new)
+            if dict_impl.__getattribute__(self, 'lt') == _nil:
+                dict_impl.__setattr__(self, 'lh', key)
+            else:
+                dict_impl.__getitem__(
+                    self, dict_impl.__getattribute__(self, 'lt'))[2] = key
+            dict_impl.__setattr__(self, 'lt', key)
+
+    def __delitem__(self, key):
+        dict_impl = self._dict_impl()
+        pred, _ , succ = self._dict_impl().__getitem__(self, key)
+        if pred == _nil:
+            dict_impl.__setattr__(self, 'lh', succ)
+        else:
+            dict_impl.__getitem__(self, pred)[2] = succ
+        if succ == _nil:
+            dict_impl.__setattr__(self, 'lt', pred)
+        else:
+            dict_impl.__getitem__(self, succ)[0] = pred
+        dict_impl.__delitem__(self, key)
+
+    def __contains__(self, key):
+        return key in self.keys()
+
+    def __len__(self):
+        return len(self.keys())
+
+    def __str__(self):
+        pairs = ("%r: %r" % (k, v) for k, v in self.iteritems())
+        return "{%s}" % ", ".join(pairs)
+
+    def __repr__(self):
+        if self:
+            pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems())
+            return "odict([%s])" % ", ".join(pairs)
+        else:
+            return "odict()"
+
+    def get(self, k, x=None):
+        if k in self:
+            return self._dict_impl().__getitem__(self, k)[1]
+        else:
+            return x
+
+    def __iter__(self):
+        dict_impl = self._dict_impl()
+        curr_key = dict_impl.__getattribute__(self, 'lh')
+        while curr_key != _nil:
+            yield curr_key
+            curr_key = dict_impl.__getitem__(self, curr_key)[2]
+
+    iterkeys = __iter__
+
+    def keys(self):
+        return list(self.iterkeys())
+
+    def itervalues(self):
+        dict_impl = self._dict_impl()
+        curr_key = dict_impl.__getattribute__(self, 'lh')
+        while curr_key != _nil:
+            _, val, curr_key = dict_impl.__getitem__(self, curr_key)
+            yield val
+
+    def values(self):
+        return list(self.itervalues())
+
+    def iteritems(self):
+        dict_impl = self._dict_impl()
+        curr_key = dict_impl.__getattribute__(self, 'lh')
+        while curr_key != _nil:
+            _, val, next_key = dict_impl.__getitem__(self, curr_key)
+            yield curr_key, val
+            curr_key = next_key
+
+    def items(self):
+        return list(self.iteritems())
+
+    def sort(self, cmp=None, key=None, reverse=False):
+        items = [(k, v) for k, v in self.items()]
+        if cmp is not None:
+            items = sorted(items, cmp=cmp)
+        elif key is not None:
+            items = sorted(items, key=key)
+        else:
+            items = sorted(items, key=lambda x: x[1])
+        if reverse:
+            items.reverse()
+        self.clear()
+        self.__init__(items)
+
+    def clear(self):
+        dict_impl = self._dict_impl()
+        dict_impl.clear(self)
+        dict_impl.__setattr__(self, 'lh', _nil)
+        dict_impl.__setattr__(self, 'lt', _nil)
+
+    def copy(self):
+        return self.__class__(self)
+
+    def update(self, data=(), **kwds):
+        if kwds:
+            raise TypeError("update() of ordered dict takes no keyword "
+                            "arguments to avoid an ordering trap.")
+        if hasattr(data, "iteritems"):
+            data = data.iteritems()
+        for key, val in data:
+            self[key] = val
+
+    def setdefault(self, k, x=None):
+        try:
+            return self[k]
+        except KeyError:
+            self[k] = x
+            return x
+
+    def pop(self, k, x=_nil):
+        try:
+            val = self[k]
+            del self[k]
+            return val
+        except KeyError:
+            if x == _nil:
+                raise
+            return x
+
+    def popitem(self):
+        try:
+            dict_impl = self._dict_impl()
+            key = dict_impl.__getattribute__(self, 'lt')
+            return key, self.pop(key)
+        except KeyError:
+            raise KeyError("'popitem(): ordered dictionary is empty'")
+
+    def riterkeys(self):
+        """To iterate on keys in reversed order.
+        """
+        dict_impl = self._dict_impl()
+        curr_key = dict_impl.__getattribute__(self, 'lt')
+        while curr_key != _nil:
+            yield curr_key
+            curr_key = dict_impl.__getitem__(self, curr_key)[0]
+
+    __reversed__ = riterkeys
+
+    def rkeys(self):
+        """List of the keys in reversed order.
+        """
+        return list(self.riterkeys())
+
+    def ritervalues(self):
+        """To iterate on values in reversed order.
+        """
+        dict_impl = self._dict_impl()
+        curr_key = dict_impl.__getattribute__(self, 'lt')
+        while curr_key != _nil:
+            curr_key, val, _ = dict_impl.__getitem__(self, curr_key)
+            yield val
+
+    def rvalues(self):
+        """List of the values in reversed order.
+        """
+        return list(self.ritervalues())
+
+    def riteritems(self):
+        """To iterate on (key, value) in reversed order.
+        """
+        dict_impl = self._dict_impl()
+        curr_key = dict_impl.__getattribute__(self, 'lt')
+        while curr_key != _nil:
+            pred_key, val, _ = dict_impl.__getitem__(self, curr_key)
+            yield curr_key, val
+            curr_key = pred_key
+
+    def ritems(self):
+        """List of the (key, value) in reversed order.
+        """
+        return list(self.riteritems())
+
+    def firstkey(self):
+        if self:
+            return self._dict_impl().__getattribute__(self, 'lh')
+        else:
+            raise KeyError("'firstkey(): ordered dictionary is empty'")
+
+    def lastkey(self):
+        if self:
+            return self._dict_impl().__getattribute__(self, 'lt')
+        else:
+            raise KeyError("'lastkey(): ordered dictionary is empty'")
+
+    def as_dict(self):
+        return self._dict_impl()(self.items())
+
+    def _repr(self):
+        """_repr(): low level repr of the whole data contained in the odict.
+        Useful for debugging.
+        """
+        dict_impl = self._dict_impl()
+        form = "odict low level repr lh,lt,data: %r, %r, %s"
+        return form % (dict_impl.__getattribute__(self, 'lh'),
+                       dict_impl.__getattribute__(self, 'lt'),
+                       dict_impl.__repr__(self))
+
+class OrderedDict(_odict, dict):
+
+    def _dict_impl(self):
+        return dict
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/lib/oset.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,64 @@
+KEY, PREV, NEXT = range(3)
+import collections
+
+class OrderedSet(collections.MutableSet):
+
+    def __init__(self, iterable=None):
+        self.end = end = []
+        end += [None, end, end]         # sentinel node for doubly linked list
+        self.map = {}                   # key --> [key, prev, next]
+        if iterable is not None:
+            self |= iterable
+
+    def __len__(self):
+        return len(self.map)
+
+    def __contains__(self, key):
+        return key in self.map
+
+    def add(self, key):
+        if key not in self.map:
+            end = self.end
+            curr = end[PREV]
+            curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
+
+    def discard(self, key):
+        if key in self.map:
+            key, prev, next = self.map.pop(key)
+            prev[NEXT] = next
+            next[PREV] = prev
+
+    def __iter__(self):
+        end = self.end
+        curr = end[NEXT]
+        while curr is not end:
+            yield curr[KEY]
+            curr = curr[NEXT]
+
+    def __reversed__(self):
+        end = self.end
+        curr = end[PREV]
+        while curr is not end:
+            yield curr[KEY]
+            curr = curr[PREV]
+
+    def pop(self, last=True):
+        if not self:
+            raise KeyError('set is empty')
+        key = next(reversed(self)) if last else next(iter(self))
+        self.discard(key)
+        return key
+
+    def __repr__(self):
+        if not self:
+            return '%s()' % (self.__class__.__name__,)
+        return '%s(%r)' % (self.__class__.__name__, list(self))
+
+    def __eq__(self, other):
+        if isinstance(other, OrderedSet):
+            return len(self) == len(other) and list(self) == list(other)
+        return set(self) == set(other)
+
+    def __del__(self):
+        self.clear()                    # remove circular references
+
--- a/rhodecode/lib/pidlock.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/pidlock.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,14 +1,17 @@
-import os, time
+import os
 import sys
+import time
+import errno
+
 from warnings import warn
 from multiprocessing.util import Finalize
-import errno
 
 from rhodecode import __platform__, PLATFORM_WIN
 
 if __platform__ in PLATFORM_WIN:
     import ctypes
-    def kill(pid):
+
+    def kill(pid, sig):
         """kill function for Win32"""
         kernel32 = ctypes.windll.kernel32
         handle = kernel32.OpenProcess(1, 0, pid)
@@ -17,7 +20,9 @@
 else:
     kill = os.kill
 
-class LockHeld(Exception):pass
+
+class LockHeld(Exception):
+    pass
 
 
 class DaemonLock(object):
@@ -34,8 +39,9 @@
     def __init__(self, file=None, callbackfn=None,
                  desc='daemon lock', debug=False):
 
-        self.pidfile = file if file else os.path.join(os.path.dirname(__file__),
-                                                      'running.lock')
+        self.pidfile = file if file else os.path.join(
+                                                    os.path.dirname(__file__),
+                                                    'running.lock')
         self.callbackfn = callbackfn
         self.desc = desc
         self.debug = debug
@@ -52,9 +58,10 @@
                 print 'leck held finilazing and running lock.release()'
             lock.release()
 
-
     def lock(self):
-        """locking function, if lock is present it will raise LockHeld exception
+        """
+        locking function, if lock is present it
+        will raise LockHeld exception
         """
         lockname = '%s' % (os.getpid())
         if self.debug:
@@ -75,8 +82,8 @@
             pidfile.close()
 
             if self.debug:
-                print 'lock file present running_pid: %s, checking for execution'\
-                % running_pid
+                print ('lock file present running_pid: %s, '
+                       'checking for execution') % running_pid
             # Now we check the PID from lock file matches to the current
             # process PID
             if running_pid:
@@ -84,7 +91,8 @@
                     kill(running_pid, 0)
                 except OSError, exc:
                     if exc.errno in (errno.ESRCH, errno.EPERM):
-                        print "Lock File is there but the program is not running"
+                        print ("Lock File is there but"
+                               " the program is not running")
                         print "Removing lock file for the: %s" % running_pid
                         self.release()
                     else:
@@ -122,6 +130,7 @@
     def makelock(self, lockname, pidfile):
         """
         this function will make an actual lock
+
         :param lockname: acctual pid of file
         :param pidfile: the file to write the pid in
         """
--- a/rhodecode/lib/profiler.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/profiler.py	Fri Oct 07 01:08:50 2011 +0200
@@ -8,15 +8,16 @@
 
 from StringIO import StringIO
 
+
 class ProfilingMiddleware(object):
     def __init__(self, app):
         self.lock = threading.Lock()
         self.app = app
 
-
     def __call__(self, environ, start_response):
         with self.lock:
             profiler = cProfile.Profile()
+
             def run_app(*a, **kw):
                 self.response = self.app(environ, start_response)
 
@@ -39,7 +40,8 @@
             if resp.strip().startswith('<'):
                 ## The profiling info is just appended to the response.
                 ##  Browsers don't mind this.
-                resp += '<pre style="text-align:left; border-top: 4px dashed red; padding: 1em;">'
+                resp += ('<pre style="text-align:left; '
+                         'border-top: 4px dashed red; padding: 1em;">')
                 resp += cgi.escape(out.getvalue(), True)
 
                 output = StringIO()
--- a/rhodecode/lib/smtp_mailer.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/smtp_mailer.py	Fri Oct 07 01:08:50 2011 +0200
@@ -23,10 +23,12 @@
 from email.utils import formatdate
 from email import encoders
 
+
 class SmtpMailer(object):
     """SMTP mailer class
 
-    mailer = SmtpMailer(mail_from, user, passwd, mail_server, mail_port, ssl, tls)
+    mailer = SmtpMailer(mail_from, user, passwd, mail_server,
+                        mail_port, ssl, tls)
     mailer.send(recipients, subject, body, attachment_files)
 
     :param recipients might be a list of string or single string
@@ -70,16 +72,21 @@
         if self.user and self.passwd:
             smtp_serv.login(self.user, self.passwd)
 
-
         date_ = formatdate(localtime=True)
         msg = MIMEMultipart()
+        msg.set_type('multipart/alternative')
+        msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
+
+        text_msg = MIMEText(body)
+        text_msg.set_type('text/plain')
+        text_msg.set_param('charset', 'UTF-8')
+
         msg['From'] = self.mail_from
         msg['To'] = ','.join(recipients)
         msg['Date'] = date_
         msg['Subject'] = subject
-        msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
 
-        msg.attach(MIMEText(body))
+        msg.attach(text_msg)
 
         if attachment_files:
             self.__atach_files(msg, attachment_files)
@@ -93,16 +100,15 @@
             # sslerror is raised in tls connections on closing sometimes
             pass
 
-
-
     def __atach_files(self, msg, attachment_files):
         if isinstance(attachment_files, dict):
             for f_name, msg_file in attachment_files.items():
                 ctype, encoding = mimetypes.guess_type(f_name)
-                logging.info("guessing file %s type based on %s" , ctype, f_name)
+                logging.info("guessing file %s type based on %s", ctype,
+                             f_name)
                 if ctype is None or encoding is not None:
-                    # No guess could be made, or the file is encoded (compressed), so
-                    # use a generic bag-of-bits type.
+                    # No guess could be made, or the file is encoded
+                    # (compressed), so use a generic bag-of-bits type.
                     ctype = 'application/octet-stream'
                 maintype, subtype = ctype.split('/', 1)
                 if maintype == 'text':
--- a/rhodecode/lib/timerproxy.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/timerproxy.py	Fri Oct 07 01:08:50 2011 +0200
@@ -5,11 +5,13 @@
 
 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
 
+
 def color_sql(sql):
     COLOR_SEQ = "\033[1;%dm"
     COLOR_SQL = YELLOW
     normal = '\x1b[0m'
-    return COLOR_SEQ % COLOR_SQL + sql + normal
+    return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
+
 
 class TimerProxy(ConnectionProxy):
 
--- a/rhodecode/lib/utils.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/lib/utils.py	Fri Oct 07 01:08:50 2011 +0200
@@ -29,24 +29,25 @@
 import traceback
 import paste
 import beaker
+from os.path import dirname as dn, join as jn
 
 from paste.script.command import Command, BadCommand
 
-from UserDict import DictMixin
-
-from mercurial import ui, config, hg
-from mercurial.error import RepoError
+from mercurial import ui, config
 
 from webhelpers.text import collapse, remove_formatting, strip_tags
 
+from vcs import get_backend
 from vcs.backends.base import BaseChangeset
 from vcs.utils.lazy import LazyProperty
+from vcs.utils.helpers import get_scm
+from vcs.exceptions import VCSError
 
 from rhodecode.model import meta
 from rhodecode.model.caching_query import FromCache
-from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog
+from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog, Group, \
+    RhodeCodeSettings
 from rhodecode.model.repo import RepoModel
-from rhodecode.model.user import UserModel
 
 log = logging.getLogger(__name__)
 
@@ -108,11 +109,10 @@
         sa = meta.Session()
 
     try:
-        um = UserModel()
         if hasattr(user, 'user_id'):
             user_obj = user
         elif isinstance(user, basestring):
-            user_obj = um.get_by_username(user, cache=False)
+            user_obj = User.by_username(user, cache=False)
         else:
             raise Exception('You have to provide user object or username')
 
@@ -144,64 +144,77 @@
         sa.rollback()
 
 
-def get_repos(path, recursive=False, initial=False):
+def get_repos(path, recursive=False):
     """
-    Scans given path for repos and return (name,(type,path)) tuple 
-    
-    :param prefix:
-    :param path:
-    :param recursive:
-    :param initial:
+    Scans given path for repos and return (name,(type,path)) tuple
+
+    :param path: path to scann for repositories
+    :param recursive: recursive search and return names with subdirs in front
     """
     from vcs.utils.helpers import get_scm
     from vcs.exceptions import VCSError
 
-    try:
-        scm = get_scm(path)
-    except:
-        pass
-    else:
-        raise Exception('The given path %s should not be a repository got %s',
-                        path, scm)
+    if path.endswith(os.sep):
+        #remove ending slash for better results
+        path = path[:-1]
 
-    for dirpath in os.listdir(path):
-        try:
-            yield dirpath, get_scm(os.path.join(path, dirpath))
-        except VCSError:
-            pass
+    def _get_repos(p):
+        if not os.access(p, os.W_OK):
+            return
+        for dirpath in os.listdir(p):
+            if os.path.isfile(os.path.join(p, dirpath)):
+                continue
+            cur_path = os.path.join(p, dirpath)
+            try:
+                scm_info = get_scm(cur_path)
+                yield scm_info[1].split(path)[-1].lstrip(os.sep), scm_info
+            except VCSError:
+                if not recursive:
+                    continue
+                #check if this dir containts other repos for recursive scan
+                rec_path = os.path.join(p, dirpath)
+                if os.path.isdir(rec_path):
+                    for inner_scm in _get_repos(rec_path):
+                        yield inner_scm
 
-def check_repo_fast(repo_name, base_path):
+    return _get_repos(path)
+
+
+def is_valid_repo(repo_name, base_path):
     """
-    Check given path for existence of directory
+    Returns True if given path is a valid repository False otherwise
     :param repo_name:
     :param base_path:
 
-    :return False: if this directory is present
+    :return True: if given path is a valid repository
     """
-    if os.path.isdir(os.path.join(base_path, repo_name)):
-        return False
-    return True
-
-
-def check_repo(repo_name, base_path, verify=True):
-
-    repo_path = os.path.join(base_path, repo_name)
-
+    full_path = os.path.join(base_path, repo_name)
+    
     try:
-        if not check_repo_fast(repo_name, base_path):
-            return False
-        r = hg.repository(ui.ui(), repo_path)
-        if verify:
-            hg.verify(r)
-        #here we hnow that repo exists it was verified
-        log.info('%s repo is already created', repo_name)
+        get_scm(full_path)
+        return True
+    except VCSError:
         return False
-    except RepoError:
-        #it means that there is no valid repo there...
-        log.info('%s repo is free for creation', repo_name)
+
+def is_valid_repos_group(repos_group_name, base_path):
+    """
+    Returns True if given path is a repos group False otherwise
+    
+    :param repo_name:
+    :param base_path:
+    """
+    full_path = os.path.join(base_path, repos_group_name)
+    
+    # check if it's not a repo
+    if is_valid_repo(repos_group_name, base_path):
+        return False
+    
+    # check if it's a valid path
+    if os.path.isdir(full_path):
         return True
-
-
+    
+    return False
+    
 def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
     while True:
         ok = raw_input(prompt)
@@ -277,8 +290,7 @@
 
     :param config:
     """
-    from rhodecode.model.settings import SettingsModel
-    hgsettings = SettingsModel().get_app_settings()
+    hgsettings = RhodeCodeSettings.get_app_settings()
 
     for k, v in hgsettings.items():
         config[k] = v
@@ -302,13 +314,15 @@
     an EmptyChangeset
     """
 
-    def __init__(self, cs='0' * 40, repo=None):
+    def __init__(self, cs='0' * 40, repo=None, requested_revision=None, alias=None):
         self._empty_cs = cs
         self.revision = -1
         self.message = ''
         self.author = ''
         self.date = ''
         self.repository = repo
+        self.requested_revision = requested_revision
+        self.alias = alias
 
     @LazyProperty
     def raw_id(self):
@@ -319,6 +333,10 @@
         return self._empty_cs
 
     @LazyProperty
+    def branch(self):
+        return get_backend(self.alias).DEFAULT_BRANCH_NAME
+
+    @LazyProperty
     def short_id(self):
         return self.raw_id[:12]
 
@@ -331,135 +349,70 @@
     def get_file_size(self, path):
         return 0
 
+
+def map_groups(groups):
+    """Checks for groups existence, and creates groups structures.
+    It returns last group in structure
+
+    :param groups: list of groups structure
+    """
+    sa = meta.Session()
+
+    parent = None
+    group = None
+    for lvl, group_name in enumerate(groups[:-1]):
+        group = sa.query(Group).filter(Group.group_name == group_name).scalar()
+
+        if group is None:
+            group = Group(group_name, parent)
+            sa.add(group)
+            sa.commit()
+
+        parent = group
+
+    return group
+
+
 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
-    """maps all found repositories into db
+    """maps all repos given in initial_repo_list, non existing repositories
+    are created, if remove_obsolete is True it also check for db entries
+    that are not in initial_repo_list and removes them.
+
+    :param initial_repo_list: list of repositories found by scanning methods
+    :param remove_obsolete: check for obsolete entries in database
     """
 
     sa = meta.Session()
     rm = RepoModel()
     user = sa.query(User).filter(User.admin == True).first()
-
+    added = []
     for name, repo in initial_repo_list.items():
+        group = map_groups(name.split(os.sep))
         if not rm.get_by_repo_name(name, cache=False):
             log.info('repository %s not found creating default', name)
-
+            added.append(name)
             form_data = {
-                         'repo_name':name,
-                         'repo_type':repo.alias,
-                         'description':repo.description \
+                         'repo_name': name,
+                         'repo_name_full': name,
+                         'repo_type': repo.alias,
+                         'description': repo.description \
                             if repo.description != 'unknown' else \
                                         '%s repository' % name,
-                         'private':False
+                         'private': False,
+                         'group_id': getattr(group, 'group_id', None)
                          }
             rm.create(form_data, user, just_db=True)
 
+    removed = []
     if remove_obsolete:
         #remove from database those repositories that are not in the filesystem
         for repo in sa.query(Repository).all():
             if repo.repo_name not in initial_repo_list.keys():
+                removed.append(repo.repo_name)
                 sa.delete(repo)
                 sa.commit()
 
-
-class OrderedDict(dict, DictMixin):
-
-    def __init__(self, *args, **kwds):
-        if len(args) > 1:
-            raise TypeError('expected at most 1 arguments, got %d' % len(args))
-        try:
-            self.__end
-        except AttributeError:
-            self.clear()
-        self.update(*args, **kwds)
-
-    def clear(self):
-        self.__end = end = []
-        end += [None, end, end]         # sentinel node for doubly linked list
-        self.__map = {}                 # key --> [key, prev, next]
-        dict.clear(self)
-
-    def __setitem__(self, key, value):
-        if key not in self:
-            end = self.__end
-            curr = end[1]
-            curr[2] = end[1] = self.__map[key] = [key, curr, end]
-        dict.__setitem__(self, key, value)
-
-    def __delitem__(self, key):
-        dict.__delitem__(self, key)
-        key, prev, next = self.__map.pop(key)
-        prev[2] = next
-        next[1] = prev
-
-    def __iter__(self):
-        end = self.__end
-        curr = end[2]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[2]
-
-    def __reversed__(self):
-        end = self.__end
-        curr = end[1]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[1]
-
-    def popitem(self, last=True):
-        if not self:
-            raise KeyError('dictionary is empty')
-        if last:
-            key = reversed(self).next()
-        else:
-            key = iter(self).next()
-        value = self.pop(key)
-        return key, value
-
-    def __reduce__(self):
-        items = [[k, self[k]] for k in self]
-        tmp = self.__map, self.__end
-        del self.__map, self.__end
-        inst_dict = vars(self).copy()
-        self.__map, self.__end = tmp
-        if inst_dict:
-            return (self.__class__, (items,), inst_dict)
-        return self.__class__, (items,)
-
-    def keys(self):
-        return list(self)
-
-    setdefault = DictMixin.setdefault
-    update = DictMixin.update
-    pop = DictMixin.pop
-    values = DictMixin.values
-    items = DictMixin.items
-    iterkeys = DictMixin.iterkeys
-    itervalues = DictMixin.itervalues
-    iteritems = DictMixin.iteritems
-
-    def __repr__(self):
-        if not self:
-            return '%s()' % (self.__class__.__name__,)
-        return '%s(%r)' % (self.__class__.__name__, self.items())
-
-    def copy(self):
-        return self.__class__(self)
-
-    @classmethod
-    def fromkeys(cls, iterable, value=None):
-        d = cls()
-        for key in iterable:
-            d[key] = value
-        return d
-
-    def __eq__(self, other):
-        if isinstance(other, OrderedDict):
-            return len(self) == len(other) and self.items() == other.items()
-        return dict.__eq__(self, other)
-
-    def __ne__(self, other):
-        return not self == other
-
+    return added, removed
 
 #set cache regions for beaker so celery can utilise it
 def add_cache(settings):
@@ -512,21 +465,25 @@
 #==============================================================================
 # TEST FUNCTIONS AND CREATORS
 #==============================================================================
-def create_test_index(repo_location, full_index):
-    """Makes default test index
-    :param repo_location:
+def create_test_index(repo_location, config, full_index):
+    """
+    Makes default test index
+    
+    :param config: test config
     :param full_index:
     """
+
     from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
     from rhodecode.lib.pidlock import DaemonLock, LockHeld
-    import shutil
+
+    repo_location = repo_location
 
-    index_location = os.path.join(repo_location, 'index')
-    if os.path.exists(index_location):
-        shutil.rmtree(index_location)
+    index_location = os.path.join(config['app_conf']['index_dir'])
+    if not os.path.exists(index_location):
+        os.makedirs(index_location)
 
     try:
-        l = DaemonLock()
+        l = DaemonLock(file=jn(dn(index_location), 'make_index.lock'))
         WhooshIndexingDaemon(index_location=index_location,
                              repo_location=repo_location)\
             .run(full_index=full_index)
@@ -544,30 +501,17 @@
         HG_FORK, GIT_FORK, TESTS_TMP_PATH
     import tarfile
     import shutil
-    from os.path import dirname as dn, join as jn, abspath
-
-    log = logging.getLogger('TestEnvCreator')
-    # create logger
-    log.setLevel(logging.DEBUG)
-    log.propagate = True
-    # create console handler and set level to debug
-    ch = logging.StreamHandler()
-    ch.setLevel(logging.DEBUG)
+    from os.path import abspath
 
-    # create formatter
-    formatter = logging.Formatter("%(asctime)s - %(name)s -"
-                                  " %(levelname)s - %(message)s")
-
-    # add formatter to ch
-    ch.setFormatter(formatter)
-
-    # add ch to logger
-    log.addHandler(ch)
-
-    #PART ONE create db
+    # PART ONE create db
     dbconf = config['sqlalchemy.db1.url']
     log.debug('making test db %s', dbconf)
 
+    # create test dir if it doesn't exist
+    if not os.path.isdir(repos_test_path):
+        log.debug('Creating testdir %s' % repos_test_path)
+        os.makedirs(repos_test_path)
+
     dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
                         tests=True)
     dbmanage.create_tables(override=True)
@@ -577,15 +521,20 @@
     dbmanage.create_permissions()
     dbmanage.populate_default_permissions()
 
-    #PART TWO make test repo
+    # PART TWO make test repo
     log.debug('making test vcs repositories')
 
-    #remove old one from previos tests
-    for r in [HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, HG_FORK, GIT_FORK]:
+    idx_path = config['app_conf']['index_dir']
+    data_path = config['app_conf']['cache_dir']
 
-        if os.path.isdir(jn(TESTS_TMP_PATH, r)):
-            log.debug('removing %s', r)
-            shutil.rmtree(jn(TESTS_TMP_PATH, r))
+    #clean index and data
+    if idx_path and os.path.exists(idx_path):
+        log.debug('remove %s' % idx_path)
+        shutil.rmtree(idx_path)
+
+    if data_path and os.path.exists(data_path):
+        log.debug('remove %s' % data_path)
+        shutil.rmtree(data_path)
 
     #CREATE DEFAULT HG REPOSITORY
     cur_dir = dn(dn(abspath(__file__)))
@@ -659,3 +608,4 @@
         path_to_ini_file = os.path.realpath(conf)
         conf = paste.deploy.appconfig('config:' + path_to_ini_file)
         pylonsconfig.init_app(conf.global_conf, conf.local_conf)
+
--- a/rhodecode/model/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -2,31 +2,31 @@
 """
     rhodecode.model.__init__
     ~~~~~~~~~~~~~~~~~~~~~~~~
-    
+
     The application's model objects
-    
+
     :created_on: Nov 25, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
-    
-    
+
+
     :example:
-    
+
         .. code-block:: python
-    
+
            from paste.deploy import appconfig
            from pylons import config
            from sqlalchemy import engine_from_config
            from rhodecode.config.environment import load_environment
-           
+
            conf = appconfig('config:development.ini', relative_to = './../../')
            load_environment(conf.global_conf, conf.local_conf)
-           
+
            engine = engine_from_config(config, 'sqlalchemy.')
            init_model(engine)
            # RUN YOUR CODE HERE
-    
+
 """
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -42,23 +42,28 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import logging
+
 from rhodecode.model import meta
+
 log = logging.getLogger(__name__)
 
+
 def init_model(engine):
-    """Initializes db session, bind the engine with the metadata,
-    Call this before using any of the tables or classes in the model, preferably
-    once in application start
-    
+    """
+    Initializes db session, bind the engine with the metadata,
+    Call this before using any of the tables or classes in the model,
+    preferably once in application start
+
     :param engine: engine to bind to
     """
-    log.info("initializing db models for %s", engine)
+    log.info("initializing db for %s", engine)
     meta.Base.metadata.bind = engine
 
+
 class BaseModel(object):
     """Base Model for all RhodeCode models, it adds sql alchemy session
     into instance of model
-    
+
     :param sa: If passed it reuses this session instead of creating a new one
     """
 
@@ -66,4 +71,4 @@
         if sa is not None:
             self.sa = sa
         else:
-            self.sa = meta.Session()
+            self.sa = meta.Session
--- a/rhodecode/model/caching_query.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/caching_query.py	Fri Oct 07 01:08:50 2011 +0200
@@ -11,49 +11,51 @@
    parameters on a Query
  * RelationshipCache - a variant of FromCache which is specific
    to a query invoked during a lazy load.
- * _params_from_query - extracts value parameters from 
+ * _params_from_query - extracts value parameters from
    a Query.
 
 The rest of what's here are standard SQLAlchemy and
 Beaker constructs.
-   
+
 """
+import beaker
 from beaker.exceptions import BeakerException
+
 from sqlalchemy.orm.interfaces import MapperOption
 from sqlalchemy.orm.query import Query
 from sqlalchemy.sql import visitors
-import beaker
+
 
 class CachingQuery(Query):
-    """A Query subclass which optionally loads full results from a Beaker 
+    """A Query subclass which optionally loads full results from a Beaker
     cache region.
-    
+
     The CachingQuery stores additional state that allows it to consult
     a Beaker cache before accessing the database:
-    
-    * A "region", which is a cache region argument passed to a 
+
+    * A "region", which is a cache region argument passed to a
       Beaker CacheManager, specifies a particular cache configuration
       (including backend implementation, expiration times, etc.)
     * A "namespace", which is a qualifying name that identifies a
-      group of keys within the cache.  A query that filters on a name 
-      might use the name "by_name", a query that filters on a date range 
+      group of keys within the cache.  A query that filters on a name
+      might use the name "by_name", a query that filters on a date range
       to a joined table might use the name "related_date_range".
-      
+
     When the above state is present, a Beaker cache is retrieved.
-    
-    The "namespace" name is first concatenated with 
-    a string composed of the individual entities and columns the Query 
+
+    The "namespace" name is first concatenated with
+    a string composed of the individual entities and columns the Query
     requests, i.e. such as ``Query(User.id, User.name)``.
-    
+
     The Beaker cache is then loaded from the cache manager based
     on the region and composed namespace.  The key within the cache
     itself is then constructed against the bind parameters specified
-    by this query, which are usually literals defined in the 
+    by this query, which are usually literals defined in the
     WHERE clause.
 
     The FromCache and RelationshipCache mapper options below represent
     the "public" method of configuring this state upon the CachingQuery.
-    
+
     """
 
     def __init__(self, manager, *args, **kw):
@@ -63,7 +65,7 @@
     def __iter__(self):
         """override __iter__ to pull results from Beaker
            if particular attributes have been configured.
-           
+
            Note that this approach does *not* detach the loaded objects from
            the current session. If the cache backend is an in-process cache
            (like "memory") and lives beyond the scope of the current session's
@@ -71,10 +73,11 @@
            modified to first expunge() each loaded item from the current
            session before returning the list of items, so that the items
            in the cache are not the same ones in the current Session.
-           
+
         """
         if hasattr(self, '_cache_parameters'):
-            return self.get_value(createfunc=lambda: list(Query.__iter__(self)))
+            return self.get_value(createfunc=lambda:
+                                  list(Query.__iter__(self)))
         else:
             return Query.__iter__(self)
 
@@ -103,11 +106,13 @@
         cache, cache_key = _get_cache_parameters(self)
         cache.put(cache_key, value)
 
-def query_callable(manager):
+
+def query_callable(manager, query_cls=CachingQuery):
     def query(*arg, **kw):
-        return CachingQuery(manager, *arg, **kw)
+        return query_cls(manager, *arg, **kw)
     return query
 
+
 def get_cache_region(name, region):
     if region not in beaker.cache.cache_regions:
         raise BeakerException('Cache region `%s` not configured '
@@ -115,6 +120,7 @@
     kw = beaker.cache.cache_regions[region]
     return beaker.cache.Cache._get_cache(name, kw)
 
+
 def _get_cache_parameters(query):
     """For a query with cache_region and cache_namespace configured,
     return the correspoinding Cache instance and cache key, based
@@ -122,7 +128,8 @@
 
     """
     if not hasattr(query, '_cache_parameters'):
-        raise ValueError("This Query does not have caching parameters configured.")
+        raise ValueError("This Query does not have caching "
+                         "parameters configured.")
 
     region, namespace, cache_key = query._cache_parameters
 
@@ -142,8 +149,9 @@
 
     return cache, cache_key
 
+
 def _namespace_from_query(namespace, query):
-    # cache namespace - the token handed in by the 
+    # cache namespace - the token handed in by the
     # option + class we're querying against
     namespace = " ".join([namespace] + [str(x) for x in query._entities])
 
@@ -152,6 +160,7 @@
 
     return namespace
 
+
 def _set_cache_parameters(query, region, namespace, cache_key):
 
     if hasattr(query, '_cache_parameters'):
@@ -162,6 +171,7 @@
                     )
     query._cache_parameters = region, namespace, cache_key
 
+
 class FromCache(MapperOption):
     """Specifies that a Query should load results from a cache."""
 
@@ -169,18 +179,18 @@
 
     def __init__(self, region, namespace, cache_key=None):
         """Construct a new FromCache.
-        
+
         :param region: the cache region.  Should be a
         region configured in the Beaker CacheManager.
-        
+
         :param namespace: the cache namespace.  Should
         be a name uniquely describing the target Query's
         lexical structure.
-        
-        :param cache_key: optional.  A string cache key 
+
+        :param cache_key: optional.  A string cache key
         that will serve as the key to the query.   Use this
         if your query has a huge amount of parameters (such
-        as when using in_()) which correspond more simply to 
+        as when using in_()) which correspond more simply to
         some other identifier.
 
         """
@@ -191,33 +201,35 @@
     def process_query(self, query):
         """Process a Query during normal loading operation."""
 
-        _set_cache_parameters(query, self.region, self.namespace, self.cache_key)
+        _set_cache_parameters(query, self.region, self.namespace,
+                              self.cache_key)
+
 
 class RelationshipCache(MapperOption):
-    """Specifies that a Query as called within a "lazy load" 
+    """Specifies that a Query as called within a "lazy load"
        should load results from a cache."""
 
     propagate_to_loaders = True
 
     def __init__(self, region, namespace, attribute):
         """Construct a new RelationshipCache.
-        
+
         :param region: the cache region.  Should be a
         region configured in the Beaker CacheManager.
-        
+
         :param namespace: the cache namespace.  Should
         be a name uniquely describing the target Query's
         lexical structure.
-        
+
         :param attribute: A Class.attribute which
         indicates a particular class relationship() whose
         lazy loader should be pulled from the cache.
-        
+
         """
         self.region = region
         self.namespace = namespace
         self._relationship_options = {
-            (attribute.property.parent.class_, attribute.property.key) : self
+            (attribute.property.parent.class_, attribute.property.key): self
         }
 
     def process_query_conditionally(self, query):
@@ -232,7 +244,8 @@
 
             for cls in mapper.class_.__mro__:
                 if (cls, key) in self._relationship_options:
-                    relationship_option = self._relationship_options[(cls, key)]
+                    relationship_option = \
+                        self._relationship_options[(cls, key)]
                     _set_cache_parameters(
                             query,
                             relationship_option.region,
@@ -241,11 +254,11 @@
 
     def and_(self, option):
         """Chain another RelationshipCache option to this one.
-        
+
         While many RelationshipCache objects can be specified on a single
         Query separately, chaining them together allows for a more efficient
         lookup during load.
-        
+
         """
         self._relationship_options.update(option._relationship_options)
         return self
@@ -253,12 +266,12 @@
 
 def _params_from_query(query):
     """Pull the bind parameter values from a query.
-    
+
     This takes into account any scalar attribute bindparam set up.
-    
+
     E.g. params_from_query(query.filter(Cls.foo==5).filter(Cls.bar==7)))
     would return [5, 7].
-    
+
     """
     v = []
     def visit_bindparam(bind):
--- a/rhodecode/model/db.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/db.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,7 +4,7 @@
     ~~~~~~~~~~~~~~~~~~
 
     Database Models for RhodeCode
-    
+
     :created_on: Apr 08, 2010
     :author: marcink
     :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
@@ -22,23 +22,121 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
 import logging
 import datetime
+import traceback
 from datetime import date
 
 from sqlalchemy import *
 from sqlalchemy.exc import DatabaseError
-from sqlalchemy.orm import relationship, backref
+from sqlalchemy.orm import relationship, backref, joinedload, class_mapper
 from sqlalchemy.orm.interfaces import MapperExtension
 
+from beaker.cache import cache_region, region_invalidate
+
+from vcs import get_backend
+from vcs.utils.helpers import get_scm
+from vcs.exceptions import VCSError
+from vcs.utils.lazy import LazyProperty
+
+from rhodecode.lib.exceptions import UsersGroupsAssignedException
+from rhodecode.lib import str2bool, json, safe_str, get_changeset_safe,\
+    generate_api_key
+
 from rhodecode.model.meta import Base, Session
+from rhodecode.model.caching_query import FromCache
 
 log = logging.getLogger(__name__)
 
+#==============================================================================
+# BASE CLASSES
+#==============================================================================
 
-class RhodeCodeSettings(Base):
+class ModelSerializer(json.JSONEncoder):
+    """
+    Simple Serializer for JSON,
+    
+    usage::
+        
+        to make object customized for serialization implement a __json__
+        method that will return a dict for serialization into json
+        
+    example::
+        
+        class Task(object):
+        
+            def __init__(self, name, value):
+                self.name = name
+                self.value = value
+        
+            def __json__(self):
+                return dict(name=self.name,
+                            value=self.value)     
+        
+    """
+
+    def default(self, obj):
+
+        if hasattr(obj, '__json__'):
+            return obj.__json__()
+        else:
+            return json.JSONEncoder.default(self, obj)
+
+class BaseModel(object):
+    """Base Model for all classess
+
+    """
+
+    @classmethod
+    def _get_keys(cls):
+        """return column names for this model """
+        return class_mapper(cls).c.keys()
+
+    def get_dict(self):
+        """return dict with keys and values corresponding
+        to this model data """
+
+        d = {}
+        for k in self._get_keys():
+            d[k] = getattr(self, k)
+        return d
+
+    def get_appstruct(self):
+        """return list with keys and values tupples corresponding
+        to this model data """
+
+        l = []
+        for k in self._get_keys():
+            l.append((k, getattr(self, k),))
+        return l
+
+    def populate_obj(self, populate_dict):
+        """populate model with data from given populate_dict"""
+
+        for k in self._get_keys():
+            if k in populate_dict:
+                setattr(self, k, populate_dict[k])
+
+    @classmethod
+    def query(cls):
+        return Session.query(cls)
+
+    @classmethod
+    def get(cls, id_):
+        return Session.query(cls).get(id_)
+
+    @classmethod
+    def delete(cls, id_):
+        obj = Session.query(cls).get(id_)
+        Session.delete(obj)
+        Session.commit()
+
+
+class RhodeCodeSettings(Base, BaseModel):
     __tablename__ = 'rhodecode_settings'
-    __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
+    __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
     app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -51,9 +149,52 @@
         return "<%s('%s:%s')>" % (self.__class__.__name__,
                                   self.app_settings_name, self.app_settings_value)
 
-class RhodeCodeUi(Base):
+
+    @classmethod
+    def get_by_name(cls, ldap_key):
+        return Session.query(cls)\
+            .filter(cls.app_settings_name == ldap_key).scalar()
+
+    @classmethod
+    def get_app_settings(cls, cache=False):
+
+        ret = Session.query(cls)
+
+        if cache:
+            ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
+
+        if not ret:
+            raise Exception('Could not get application settings !')
+        settings = {}
+        for each in ret:
+            settings['rhodecode_' + each.app_settings_name] = \
+                each.app_settings_value
+
+        return settings
+
+    @classmethod
+    def get_ldap_settings(cls, cache=False):
+        ret = Session.query(cls)\
+                .filter(cls.app_settings_name.startswith('ldap_'))\
+                .all()
+        fd = {}
+        for row in ret:
+            fd.update({row.app_settings_name:row.app_settings_value})
+
+        fd.update({'ldap_active':str2bool(fd.get('ldap_active'))})
+
+        return fd
+
+
+class RhodeCodeUi(Base, BaseModel):
     __tablename__ = 'rhodecode_ui'
-    __table_args__ = {'useexisting':True}
+    __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
+
+    HOOK_UPDATE = 'changegroup.update'
+    HOOK_REPO_SIZE = 'changegroup.repo_size'
+    HOOK_PUSH = 'pretxnchangegroup.push_logger'
+    HOOK_PULL = 'preoutgoing.pull_logger'
+
     ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -61,9 +202,43 @@
     ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 
 
-class User(Base):
+    @classmethod
+    def get_by_key(cls, key):
+        return Session.query(cls).filter(cls.ui_key == key)
+
+
+    @classmethod
+    def get_builtin_hooks(cls):
+        q = cls.query()
+        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
+                                    cls.HOOK_REPO_SIZE,
+                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
+        return q.all()
+
+    @classmethod
+    def get_custom_hooks(cls):
+        q = cls.query()
+        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
+                                    cls.HOOK_REPO_SIZE,
+                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
+        q = q.filter(cls.ui_section == 'hooks')
+        return q.all()
+
+    @classmethod
+    def create_or_update_hook(cls, key, val):
+        new_ui = cls.get_by_key(key).scalar() or cls()
+        new_ui.ui_section = 'hooks'
+        new_ui.ui_active = True
+        new_ui.ui_key = key
+        new_ui.ui_value = val
+
+        Session.add(new_ui)
+        Session.commit()
+
+
+class User(Base, BaseModel):
     __tablename__ = 'users'
-    __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
+    __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
     user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -73,7 +248,8 @@
     lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
-    is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
+    ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
     user_log = relationship('UserLog', cascade='all')
     user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
@@ -82,6 +258,8 @@
     user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
     repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all')
 
+    group_member = relationship('UsersGroupMember', cascade='all')
+
     @property
     def full_contact(self):
         return '%s %s <%s>' % (self.name, self.lastname, self.email)
@@ -90,39 +268,63 @@
     def short_contact(self):
         return '%s %s' % (self.name, self.lastname)
 
-
     @property
     def is_admin(self):
         return self.admin
 
     def __repr__(self):
-        return "<%s('id:%s:%s')>" % (self.__class__.__name__,
-                                     self.user_id, self.username)
+        try:
+            return "<%s('id:%s:%s')>" % (self.__class__.__name__,
+                                             self.user_id, self.username)
+        except:
+            return self.__class__.__name__
 
     @classmethod
-    def by_username(cls, username):
-        return Session.query(cls).filter(cls.username == username).one()
+    def by_username(cls, username, case_insensitive=False):
+        if case_insensitive:
+            return Session.query(cls).filter(cls.username.like(username)).one()
+        else:
+            return Session.query(cls).filter(cls.username == username).one()
+
+    @classmethod
+    def get_by_api_key(cls, api_key):
+        return Session.query(cls).filter(cls.api_key == api_key).one()
 
 
     def update_lastlogin(self):
         """Update user lastlogin"""
 
+        self.last_login = datetime.datetime.now()
+        Session.add(self)
+        Session.commit()
+        log.debug('updated user %s lastlogin', self.username)
+
+    @classmethod
+    def create(cls, form_data):
+        from rhodecode.lib.auth import get_crypt_password
+        
         try:
-            session = Session.object_session(self)
-            self.last_login = datetime.datetime.now()
-            session.add(self)
-            session.commit()
-            log.debug('updated user %s lastlogin', self.username)
-        except (DatabaseError,):
-            session.rollback()
+            new_user = cls()
+            for k, v in form_data.items():
+                if k == 'password':
+                    v = get_crypt_password(v)
+                setattr(new_user, k, v)
 
+            new_user.api_key = generate_api_key(form_data['username'])
+            Session.add(new_user)
+            Session.commit()
+            return new_user
+        except:
+            log.error(traceback.format_exc())
+            Session.rollback()
+            raise
 
-class UserLog(Base):
+class UserLog(Base, BaseModel):
     __tablename__ = 'user_logs'
-    __table_args__ = {'useexisting':True}
+    __table_args__ = {'extend_existing':True}
     user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
-    repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
+    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
     repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -135,24 +337,147 @@
     user = relationship('User')
     repository = relationship('Repository')
 
-class Repository(Base):
+
+class UsersGroup(Base, BaseModel):
+    __tablename__ = 'users_groups'
+    __table_args__ = {'extend_existing':True}
+
+    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
+    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
+
+    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
+
+    def __repr__(self):
+        return '<userGroup(%s)>' % (self.users_group_name)
+
+    @classmethod
+    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
+        if case_insensitive:
+            gr = Session.query(cls)\
+            .filter(cls.users_group_name.ilike(group_name))
+        else:
+            gr = Session.query(UsersGroup)\
+                .filter(UsersGroup.users_group_name == group_name)
+        if cache:
+            gr = gr.options(FromCache("sql_cache_short",
+                                          "get_user_%s" % group_name))
+        return gr.scalar()
+
+
+    @classmethod
+    def get(cls, users_group_id, cache=False):
+        users_group = Session.query(cls)
+        if cache:
+            users_group = users_group.options(FromCache("sql_cache_short",
+                                    "get_users_group_%s" % users_group_id))
+        return users_group.get(users_group_id)
+
+    @classmethod
+    def create(cls, form_data):
+        try:
+            new_users_group = cls()
+            for k, v in form_data.items():
+                setattr(new_users_group, k, v)
+
+            Session.add(new_users_group)
+            Session.commit()
+            return new_users_group
+        except:
+            log.error(traceback.format_exc())
+            Session.rollback()
+            raise
+
+    @classmethod
+    def update(cls, users_group_id, form_data):
+
+        try:
+            users_group = cls.get(users_group_id, cache=False)
+
+            for k, v in form_data.items():
+                if k == 'users_group_members':
+                    users_group.members = []
+                    Session.flush()
+                    members_list = []
+                    if v:
+                        for u_id in set(v):
+                            members_list.append(UsersGroupMember(
+                                                            users_group_id,
+                                                            u_id))
+                    setattr(users_group, 'members', members_list)
+                setattr(users_group, k, v)
+
+            Session.add(users_group)
+            Session.commit()
+        except:
+            log.error(traceback.format_exc())
+            Session.rollback()
+            raise
+
+    @classmethod
+    def delete(cls, users_group_id):
+        try:
+
+            # check if this group is not assigned to repo
+            assigned_groups = UsersGroupRepoToPerm.query()\
+                .filter(UsersGroupRepoToPerm.users_group_id ==
+                        users_group_id).all()
+
+            if assigned_groups:
+                raise UsersGroupsAssignedException('Group assigned to %s' %
+                                                   assigned_groups)
+
+            users_group = cls.get(users_group_id, cache=False)
+            Session.delete(users_group)
+            Session.commit()
+        except:
+            log.error(traceback.format_exc())
+            Session.rollback()
+            raise
+
+
+class UsersGroupMember(Base, BaseModel):
+    __tablename__ = 'users_groups_members'
+    __table_args__ = {'extend_existing':True}
+
+    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
+
+    user = relationship('User', lazy='joined')
+    users_group = relationship('UsersGroup')
+
+    def __init__(self, gr_id='', u_id=''):
+        self.users_group_id = gr_id
+        self.user_id = u_id
+
+class Repository(Base, BaseModel):
     __tablename__ = 'repositories'
-    __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
+    __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
+
     repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
+    clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
     repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
     user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
     private = Column("private", Boolean(), nullable=True, unique=None, default=None)
     enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
+    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
     description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
+
     fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
+    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
+
 
     user = relationship('User')
     fork = relationship('Repository', remote_side=repo_id)
-    repo_to_perm = relationship('RepoToPerm', cascade='all')
+    group = relationship('Group')
+    repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
+    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
     stats = relationship('Statistics', cascade='all', uselist=False)
 
-    repo_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
+    followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
 
     logs = relationship('UserLog', cascade='all')
 
@@ -160,9 +485,295 @@
         return "<%s('%s:%s')>" % (self.__class__.__name__,
                                   self.repo_id, self.repo_name)
 
-class Permission(Base):
+    @classmethod
+    def by_repo_name(cls, repo_name):
+        q = Session.query(cls).filter(cls.repo_name == repo_name)
+
+        q = q.options(joinedload(Repository.fork))\
+            .options(joinedload(Repository.user))\
+            .options(joinedload(Repository.group))\
+
+        return q.one()
+
+    @classmethod
+    def get_repo_forks(cls, repo_id):
+        return Session.query(cls).filter(Repository.fork_id == repo_id)
+
+    @classmethod
+    def base_path(cls):
+        """
+        Returns base path when all repos are stored
+        
+        :param cls:
+        """
+        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/')
+        q.options(FromCache("sql_cache_short", "repository_repo_path"))
+        return q.one().ui_value
+
+    @property
+    def just_name(self):
+        return self.repo_name.split(os.sep)[-1]
+
+    @property
+    def groups_with_parents(self):
+        groups = []
+        if self.group is None:
+            return groups
+
+        cur_gr = self.group
+        groups.insert(0, cur_gr)
+        while 1:
+            gr = getattr(cur_gr, 'parent_group', None)
+            cur_gr = cur_gr.parent_group
+            if gr is None:
+                break
+            groups.insert(0, gr)
+
+        return groups
+
+    @property
+    def groups_and_repo(self):
+        return self.groups_with_parents, self.just_name
+
+    @LazyProperty
+    def repo_path(self):
+        """
+        Returns base full path for that repository means where it actually
+        exists on a filesystem
+        """
+        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/')
+        q.options(FromCache("sql_cache_short", "repository_repo_path"))
+        return q.one().ui_value
+
+    @property
+    def repo_full_path(self):
+        p = [self.repo_path]
+        # we need to split the name by / since this is how we store the
+        # names in the database, but that eventually needs to be converted
+        # into a valid system path
+        p += self.repo_name.split('/')
+        return os.path.join(*p)
+
+    @property
+    def _ui(self):
+        """
+        Creates an db based ui object for this repository
+        """
+        from mercurial import ui
+        from mercurial import config
+        baseui = ui.ui()
+
+        #clean the baseui object
+        baseui._ocfg = config.config()
+        baseui._ucfg = config.config()
+        baseui._tcfg = config.config()
+
+
+        ret = Session.query(RhodeCodeUi)\
+            .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
+
+        hg_ui = ret
+        for ui_ in hg_ui:
+            if ui_.ui_active:
+                log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
+                          ui_.ui_key, ui_.ui_value)
+                baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
+
+        return baseui
+
+    @classmethod
+    def is_valid(cls, repo_name):
+        """
+        returns True if given repo name is a valid filesystem repository
+         
+        @param cls:
+        @param repo_name:
+        """
+        from rhodecode.lib.utils import is_valid_repo
+
+        return is_valid_repo(repo_name, cls.base_path())
+
+
+    #==========================================================================
+    # SCM PROPERTIES
+    #==========================================================================
+
+    def get_changeset(self, rev):
+        return get_changeset_safe(self.scm_instance, rev)
+
+    @property
+    def tip(self):
+        return self.get_changeset('tip')
+
+    @property
+    def author(self):
+        return self.tip.author
+
+    @property
+    def last_change(self):
+        return self.scm_instance.last_change
+
+    #==========================================================================
+    # SCM CACHE INSTANCE
+    #==========================================================================
+
+    @property
+    def invalidate(self):
+        """
+        Returns Invalidation object if this repo should be invalidated
+        None otherwise. `cache_active = False` means that this cache
+        state is not valid and needs to be invalidated
+        """
+        return Session.query(CacheInvalidation)\
+            .filter(CacheInvalidation.cache_key == self.repo_name)\
+            .filter(CacheInvalidation.cache_active == False)\
+            .scalar()
+
+    def set_invalidate(self):
+        """
+        set a cache for invalidation for this instance
+        """
+        inv = Session.query(CacheInvalidation)\
+            .filter(CacheInvalidation.cache_key == self.repo_name)\
+            .scalar()
+
+        if inv is None:
+            inv = CacheInvalidation(self.repo_name)
+        inv.cache_active = True
+        Session.add(inv)
+        Session.commit()
+
+    @LazyProperty
+    def scm_instance(self):
+        return self.__get_instance()
+
+    @property
+    def scm_instance_cached(self):
+        @cache_region('long_term')
+        def _c(repo_name):
+            return self.__get_instance()
+
+        # TODO: remove this trick when beaker 1.6 is released
+        # and have fixed this issue with not supporting unicode keys
+        rn = safe_str(self.repo_name)
+
+        inv = self.invalidate
+        if inv is not None:
+            region_invalidate(_c, None, rn)
+            # update our cache
+            inv.cache_active = True
+            Session.add(inv)
+            Session.commit()
+
+        return _c(rn)
+
+    def __get_instance(self):
+
+        repo_full_path = self.repo_full_path
+
+        try:
+            alias = get_scm(repo_full_path)[0]
+            log.debug('Creating instance of %s repository', alias)
+            backend = get_backend(alias)
+        except VCSError:
+            log.error(traceback.format_exc())
+            log.error('Perhaps this repository is in db and not in '
+                      'filesystem run rescan repositories with '
+                      '"destroy old data " option from admin panel')
+            return
+
+        if alias == 'hg':
+
+            repo = backend(safe_str(repo_full_path), create=False,
+                           baseui=self._ui)
+            #skip hidden web repository
+            if repo._get_hidden():
+                return
+        else:
+            repo = backend(repo_full_path, create=False)
+
+        return repo
+
+
+class Group(Base, BaseModel):
+    __tablename__ = 'groups'
+    __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
+                      CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
+    __mapper_args__ = {'order_by':'group_name'}
+
+    group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
+    group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
+    group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+
+    parent_group = relationship('Group', remote_side=group_id)
+
+
+    def __init__(self, group_name='', parent_group=None):
+        self.group_name = group_name
+        self.parent_group = parent_group
+
+    def __repr__(self):
+        return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
+                                  self.group_name)
+
+    @classmethod
+    def url_sep(cls):
+        return '/'
+
+    @property
+    def parents(self):
+        parents_recursion_limit = 5
+        groups = []
+        if self.parent_group is None:
+            return groups
+        cur_gr = self.parent_group
+        groups.insert(0, cur_gr)
+        cnt = 0
+        while 1:
+            cnt += 1
+            gr = getattr(cur_gr, 'parent_group', None)
+            cur_gr = cur_gr.parent_group
+            if gr is None:
+                break
+            if cnt == parents_recursion_limit:
+                # this will prevent accidental infinit loops
+                log.error('group nested more than %s' %
+                          parents_recursion_limit)
+                break
+
+            groups.insert(0, gr)
+        return groups
+
+    @property
+    def children(self):
+        return Session.query(Group).filter(Group.parent_group == self)
+
+    @property
+    def full_path(self):
+        return Group.url_sep().join([g.group_name for g in self.parents] +
+                        [self.group_name])
+
+    @property
+    def repositories(self):
+        return Session.query(Repository).filter(Repository.group == self)
+
+    @property
+    def repositories_recursive_count(self):
+        cnt = self.repositories.count()
+
+        def children_count(group):
+            cnt = 0
+            for child in group.children:
+                cnt += child.repositories.count()
+                cnt += children_count(child)
+            return cnt
+
+        return cnt + children_count(self)
+
+class Permission(Base, BaseModel):
     __tablename__ = 'permissions'
-    __table_args__ = {'useexisting':True}
+    __table_args__ = {'extend_existing':True}
     permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -171,9 +782,13 @@
         return "<%s('%s:%s')>" % (self.__class__.__name__,
                                   self.permission_id, self.permission_name)
 
-class RepoToPerm(Base):
+    @classmethod
+    def get_by_key(cls, key):
+        return Session.query(cls).filter(cls.permission_name == key).scalar()
+
+class RepoToPerm(Base, BaseModel):
     __tablename__ = 'repo_to_perm'
-    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
+    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
     repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
     permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
@@ -183,9 +798,9 @@
     permission = relationship('Permission')
     repository = relationship('Repository')
 
-class UserToPerm(Base):
+class UserToPerm(Base, BaseModel):
     __tablename__ = 'user_to_perm'
-    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
+    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
     user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
     permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
@@ -193,9 +808,120 @@
     user = relationship('User')
     permission = relationship('Permission')
 
-class Statistics(Base):
+    @classmethod
+    def has_perm(cls, user_id, perm):
+        if not isinstance(perm, Permission):
+            raise Exception('perm needs to be an instance of Permission class')
+
+        return Session.query(cls).filter(cls.user_id == user_id)\
+            .filter(cls.permission == perm).scalar() is not None
+
+    @classmethod
+    def grant_perm(cls, user_id, perm):
+        if not isinstance(perm, Permission):
+            raise Exception('perm needs to be an instance of Permission class')
+
+        new = cls()
+        new.user_id = user_id
+        new.permission = perm
+        try:
+            Session.add(new)
+            Session.commit()
+        except:
+            Session.rollback()
+
+
+    @classmethod
+    def revoke_perm(cls, user_id, perm):
+        if not isinstance(perm, Permission):
+            raise Exception('perm needs to be an instance of Permission class')
+
+        try:
+            Session.query(cls).filter(cls.user_id == user_id)\
+                .filter(cls.permission == perm).delete()
+            Session.commit()
+        except:
+            Session.rollback()
+
+class UsersGroupRepoToPerm(Base, BaseModel):
+    __tablename__ = 'users_group_repo_to_perm'
+    __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
+    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
+    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
+
+    users_group = relationship('UsersGroup')
+    permission = relationship('Permission')
+    repository = relationship('Repository')
+
+    def __repr__(self):
+        return '<userGroup:%s => %s >' % (self.users_group, self.repository)
+
+class UsersGroupToPerm(Base, BaseModel):
+    __tablename__ = 'users_group_to_perm'
+    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
+
+    users_group = relationship('UsersGroup')
+    permission = relationship('Permission')
+
+
+    @classmethod
+    def has_perm(cls, users_group_id, perm):
+        if not isinstance(perm, Permission):
+            raise Exception('perm needs to be an instance of Permission class')
+
+        return Session.query(cls).filter(cls.users_group_id ==
+                                         users_group_id)\
+                                         .filter(cls.permission == perm)\
+                                         .scalar() is not None
+
+    @classmethod
+    def grant_perm(cls, users_group_id, perm):
+        if not isinstance(perm, Permission):
+            raise Exception('perm needs to be an instance of Permission class')
+
+        new = cls()
+        new.users_group_id = users_group_id
+        new.permission = perm
+        try:
+            Session.add(new)
+            Session.commit()
+        except:
+            Session.rollback()
+
+
+    @classmethod
+    def revoke_perm(cls, users_group_id, perm):
+        if not isinstance(perm, Permission):
+            raise Exception('perm needs to be an instance of Permission class')
+
+        try:
+            Session.query(cls).filter(cls.users_group_id == users_group_id)\
+                .filter(cls.permission == perm).delete()
+            Session.commit()
+        except:
+            Session.rollback()
+
+
+class GroupToPerm(Base, BaseModel):
+    __tablename__ = 'group_to_perm'
+    __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
+
+    group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
+    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
+    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
+
+    user = relationship('User')
+    permission = relationship('Permission')
+    group = relationship('Group')
+
+class Statistics(Base, BaseModel):
     __tablename__ = 'statistics'
-    __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
+    __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
     stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
     stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
@@ -205,25 +931,31 @@
 
     repository = relationship('Repository', single_parent=True)
 
-class UserFollowing(Base):
+class UserFollowing(Base, BaseModel):
     __tablename__ = 'user_followings'
     __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
                       UniqueConstraint('user_id', 'follows_user_id')
-                      , {'useexisting':True})
+                      , {'extend_existing':True})
 
     user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
     follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
     follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
+    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
     user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 
     follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
     follows_repository = relationship('Repository', order_by='Repository.repo_name')
 
-class CacheInvalidation(Base):
+
+    @classmethod
+    def get_repo_followers(cls, repo_id):
+        return Session.query(cls).filter(cls.follows_repo_id == repo_id)
+
+class CacheInvalidation(Base, BaseModel):
     __tablename__ = 'cache_invalidation'
-    __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
+    __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
     cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
     cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
     cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -239,10 +971,9 @@
         return "<%s('%s:%s')>" % (self.__class__.__name__,
                                   self.cache_id, self.cache_key)
 
-class DbMigrateVersion(Base):
+class DbMigrateVersion(Base, BaseModel):
     __tablename__ = 'db_migrate_version'
-    __table_args__ = {'useexisting':True}
-    repository_id = Column('repository_id', String(255), primary_key=True)
+    __table_args__ = {'extend_existing':True}
+    repository_id = Column('repository_id', String(250), primary_key=True)
     repository_path = Column('repository_path', Text)
     version = Column('version', Integer)
-
--- a/rhodecode/model/forms.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/forms.py	Fri Oct 07 01:08:50 2011 +0200
@@ -10,46 +10,45 @@
 allow_extra_fields      False     If True, then it is not an error when keys that aren't associated with a validator are present
 filter_extra_fields     False     If True, then keys that aren't associated with a validator are removed
 if_key_missing          NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
-ignore_key_missing      False     If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already    
-  
-  
+ignore_key_missing      False     If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
+
+
 <name> = formencode.validators.<name of validator>
 <name> must equal form name
 list=[1,2,3,4,5]
 for SELECT use formencode.All(OneOf(list), Int())
-    
+
 """
 import os
 import re
 import logging
+import traceback
 
 import formencode
 from formencode import All
 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
-    Email, Bool, StringBoolean
+    Email, Bool, StringBoolean, Set
 
 from pylons.i18n.translation import _
+from webhelpers.pylonslib.secure_form import authentication_token
 
-import rhodecode.lib.helpers as h
+from rhodecode.lib.utils import repo_name_slug
 from rhodecode.lib.auth import authenticate, get_crypt_password
 from rhodecode.lib.exceptions import LdapImportError
-from rhodecode.model import meta
 from rhodecode.model.user import UserModel
 from rhodecode.model.repo import RepoModel
-from rhodecode.model.db import User
+from rhodecode.model.db import User, UsersGroup, Group
 from rhodecode import BACKENDS
 
-from webhelpers.pylonslib.secure_form import authentication_token
-
 log = logging.getLogger(__name__)
 
 #this is needed to translate the messages using _() in validators
 class State_obj(object):
     _ = staticmethod(_)
 
-#===============================================================================
+#==============================================================================
 # VALIDATORS
-#===============================================================================
+#==============================================================================
 class ValidAuthToken(formencode.validators.FancyValidator):
     messages = {'invalid_token':_('Token mismatch')}
 
@@ -73,20 +72,84 @@
             if old_un != value or not edit:
                 if UserModel().get_by_username(value, cache=False,
                                                case_insensitive=True):
-                    raise formencode.Invalid(_('This username already exists') ,
-                                             value, state)
-
+                    raise formencode.Invalid(_('This username already '
+                                               'exists') , value, state)
 
             if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
                 raise formencode.Invalid(_('Username may only contain '
-                                           'alphanumeric characters underscores, '
-                                           'periods or dashes and must begin with '
-                                           'alphanumeric character'),
-                                      value, state)
+                                           'alphanumeric characters '
+                                           'underscores, periods or dashes '
+                                           'and must begin with alphanumeric '
+                                           'character'), value, state)
+
+    return _ValidUsername
+
+
+def ValidUsersGroup(edit, old_data):
+
+    class _ValidUsersGroup(formencode.validators.FancyValidator):
+
+        def validate_python(self, value, state):
+            if value in ['default']:
+                raise formencode.Invalid(_('Invalid group name'), value, state)
+            #check if group is unique
+            old_ugname = None
+            if edit:
+                old_ugname = UsersGroup.get(
+                            old_data.get('users_group_id')).users_group_name
+
+            if old_ugname != value or not edit:
+                if UsersGroup.get_by_group_name(value, cache=False,
+                                               case_insensitive=True):
+                    raise formencode.Invalid(_('This users group '
+                                               'already exists') , value,
+                                             state)
 
 
+            if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
+                raise formencode.Invalid(_('Group name may only contain '
+                                           'alphanumeric characters '
+                                           'underscores, periods or dashes '
+                                           'and must begin with alphanumeric '
+                                           'character'), value, state)
 
-    return _ValidUsername
+    return _ValidUsersGroup
+
+
+def ValidReposGroup(edit, old_data):
+    class _ValidReposGroup(formencode.validators.FancyValidator):
+
+        def validate_python(self, value, state):
+            #TODO WRITE VALIDATIONS
+            group_name = value.get('group_name')
+            group_parent_id = int(value.get('group_parent_id') or - 1)
+
+            # slugify repo group just in case :)
+            slug = repo_name_slug(group_name)
+
+            # check for parent of self
+            if edit and old_data['group_id'] == group_parent_id:
+                    e_dict = {'group_parent_id':_('Cannot assign this group '
+                                                  'as parent')}
+                    raise formencode.Invalid('', value, state,
+                                             error_dict=e_dict)
+
+            old_gname = None
+            if edit:
+                old_gname = Group.get(
+                            old_data.get('group_id')).group_name
+
+            if old_gname != group_name or not edit:
+                # check filesystem
+                gr = Group.query().filter(Group.group_name == slug)\
+                    .filter(Group.group_parent_id == group_parent_id).scalar()
+
+                if gr:
+                    e_dict = {'group_name':_('This group already exists')}
+                    raise formencode.Invalid('', value, state,
+                                             error_dict=e_dict)
+
+    return _ValidReposGroup
 
 class ValidPassword(formencode.validators.FancyValidator):
 
@@ -125,7 +188,7 @@
 
         if value['password'] != value['password_confirmation']:
             e_dict = {'password_confirmation':
-                   _('Password do not match')}
+                   _('Passwords do not match')}
             raise formencode.Invalid('', value, state, error_dict=e_dict)
 
 class ValidAuth(formencode.validators.FancyValidator):
@@ -163,81 +226,165 @@
 class ValidRepoUser(formencode.validators.FancyValidator):
 
     def to_python(self, value, state):
-        sa = meta.Session()
         try:
-            self.user_db = sa.query(User)\
-                .filter(User.active == True)\
+            User.query().filter(User.active == True)\
                 .filter(User.username == value).one()
         except Exception:
             raise formencode.Invalid(_('This username is not valid'),
                                      value, state)
-        finally:
-            meta.Session.remove()
-
-        return self.user_db.user_id
+        return value
 
 def ValidRepoName(edit, old_data):
     class _ValidRepoName(formencode.validators.FancyValidator):
+        def to_python(self, value, state):
 
-        def to_python(self, value, state):
-            slug = h.repo_name_slug(value)
-            if slug in ['_admin']:
-                raise formencode.Invalid(_('This repository name is disallowed'),
-                                         value, state)
-            if old_data.get('repo_name') != value or not edit:
-                if RepoModel().get_by_repo_name(slug, cache=False):
-                    raise formencode.Invalid(_('This repository already exists') ,
-                                             value, state)
-            return slug
+            repo_name = value.get('repo_name')
+
+            slug = repo_name_slug(repo_name)
+            if slug in ['_admin', '']:
+                e_dict = {'repo_name': _('This repository name is disallowed')}
+                raise formencode.Invalid('', value, state, error_dict=e_dict)
+
+
+            if value.get('repo_group'):
+                gr = Group.get(value.get('repo_group'))
+                group_path = gr.full_path
+                # value needs to be aware of group name in order to check
+                # db key This is an actuall just the name to store in the
+                # database
+                repo_name_full = group_path + Group.url_sep() + repo_name
+            else:
+                group_path = ''
+                repo_name_full = repo_name
+
+
+            value['repo_name_full'] = repo_name_full
+            if old_data.get('repo_name') != repo_name_full or not edit:
+
+                if group_path != '':
+                    if RepoModel().get_by_repo_name(repo_name_full,):
+                        e_dict = {'repo_name':_('This repository already '
+                                                'exists in group "%s"') %
+                                  gr.group_name}
+                        raise formencode.Invalid('', value, state,
+                                                 error_dict=e_dict)
+
+                else:
+                    if RepoModel().get_by_repo_name(repo_name_full):
+                        e_dict = {'repo_name':_('This repository '
+                                                'already exists')}
+                        raise formencode.Invalid('', value, state,
+                                                 error_dict=e_dict)
+            return value
 
 
     return _ValidRepoName
 
+def ValidForkName():
+    class _ValidForkName(formencode.validators.FancyValidator):
+        def to_python(self, value, state):
+            return value
+    return _ValidForkName
+
+
+def SlugifyName():
+    class _SlugifyName(formencode.validators.FancyValidator):
+
+        def to_python(self, value, state):
+            return repo_name_slug(value)
+
+    return _SlugifyName
+
+def ValidCloneUri():
+    from mercurial.httprepo import httprepository, httpsrepository
+    from rhodecode.lib.utils import make_ui
+
+    class _ValidCloneUri(formencode.validators.FancyValidator):
+
+        def to_python(self, value, state):
+            if not value:
+                pass
+            elif value.startswith('https'):
+                try:
+                    httpsrepository(make_ui('db'), value).capabilities
+                except Exception, e:
+                    log.error(traceback.format_exc())
+                    raise formencode.Invalid(_('invalid clone url'), value,
+                                             state)
+            elif value.startswith('http'):
+                try:
+                    httprepository(make_ui('db'), value).capabilities
+                except Exception, e:
+                    log.error(traceback.format_exc())
+                    raise formencode.Invalid(_('invalid clone url'), value,
+                                             state)
+            else:
+                raise formencode.Invalid(_('Invalid clone url, provide a '
+                                           'valid clone http\s url'), value,
+                                         state)
+            return value
+
+    return _ValidCloneUri
+
 def ValidForkType(old_data):
     class _ValidForkType(formencode.validators.FancyValidator):
 
         def to_python(self, value, state):
             if old_data['repo_type'] != value:
-                raise formencode.Invalid(_('Fork have to be the same type as original'),
-                                         value, state)
+                raise formencode.Invalid(_('Fork have to be the same '
+                                           'type as original'), value, state)
+
             return value
     return _ValidForkType
 
 class ValidPerms(formencode.validators.FancyValidator):
-    messages = {'perm_new_user_name':_('This username is not valid')}
+    messages = {'perm_new_member_name':_('This username or users group name'
+                                         ' is not valid')}
 
     def to_python(self, value, state):
         perms_update = []
         perms_new = []
         #build a list of permission to update and new permission to create
         for k, v in value.items():
-            if k.startswith('perm_'):
-                if  k.startswith('perm_new_user'):
-                    new_perm = value.get('perm_new_user', False)
-                    new_user = value.get('perm_new_user_name', False)
-                    if new_user and new_perm:
-                        if (new_user, new_perm) not in perms_new:
-                            perms_new.append((new_user, new_perm))
-                else:
-                    usr = k[5:]
-                    if usr == 'default':
-                        if value['private']:
-                            #set none for default when updating to private repo
-                            v = 'repository.none'
-                    perms_update.append((usr, v))
+            #means new added member to permissions
+            if k.startswith('perm_new_member'):
+                new_perm = value.get('perm_new_member', False)
+                new_member = value.get('perm_new_member_name', False)
+                new_type = value.get('perm_new_member_type')
+
+                if new_member and new_perm:
+                    if (new_member, new_perm, new_type) not in perms_new:
+                        perms_new.append((new_member, new_perm, new_type))
+            elif k.startswith('u_perm_') or k.startswith('g_perm_'):
+                member = k[7:]
+                t = {'u':'user',
+                     'g':'users_group'}[k[0]]
+                if member == 'default':
+                    if value['private']:
+                        #set none for default when updating to private repo
+                        v = 'repository.none'
+                perms_update.append((member, v, t))
+
         value['perms_updates'] = perms_update
         value['perms_new'] = perms_new
-        sa = meta.Session
-        for k, v in perms_new:
+
+        #update permissions
+        for k, v, t in perms_new:
             try:
-                self.user_db = sa.query(User)\
-                    .filter(User.active == True)\
-                    .filter(User.username == k).one()
+                if t is 'user':
+                    self.user_db = User.query()\
+                        .filter(User.active == True)\
+                        .filter(User.username == k).one()
+                if t is 'users_group':
+                    self.user_db = UsersGroup.query()\
+                        .filter(UsersGroup.users_group_active == True)\
+                        .filter(UsersGroup.users_group_name == k).one()
+
             except Exception:
-                msg = self.message('perm_new_user_name',
+                msg = self.message('perm_new_member_name',
                                      state=State_obj)
                 raise formencode.Invalid(msg, value, state,
-                                         error_dict={'perm_new_user_name':msg})
+                                         error_dict={'perm_new_member_name':msg})
         return value
 
 class ValidSettings(formencode.validators.FancyValidator):
@@ -263,15 +410,11 @@
         def to_python(self, value, state):
             value = value.lower()
             if old_data.get('email') != value:
-                sa = meta.Session()
-                try:
-                    user = sa.query(User).filter(User.email == value).scalar()
-                    if user:
-                        raise formencode.Invalid(_("This e-mail address is already taken") ,
-                                                 value, state)
-                finally:
-                    meta.Session.remove()
-
+                user = User.query().filter(User.email == value).scalar()
+                if user:
+                    raise formencode.Invalid(
+                                    _("This e-mail address is already taken"),
+                                    value, state)
             return value
 
     return _UniqSystemEmail
@@ -279,14 +422,10 @@
 class ValidSystemEmail(formencode.validators.FancyValidator):
     def to_python(self, value, state):
         value = value.lower()
-        sa = meta.Session
-        try:
-            user = sa.query(User).filter(User.email == value).scalar()
-            if  user is None:
-                raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
-                                         value, state)
-        finally:
-            meta.Session.remove()
+        user = User.query().filter(User.email == value).scalar()
+        if  user is None:
+            raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
+                                     value, state)
 
         return value
 
@@ -300,31 +439,21 @@
             raise LdapImportError
         return value
 
-def BaseDnValidator(ldap_enable):
-    class _BaseDnValidator(formencode.validators.FancyValidator):
-
-        def to_python(self, value, state):
+class AttrLoginValidator(formencode.validators.FancyValidator):
 
-            if not ldap_enable:
-                return ''
-            try:
-                value % {'user':'valid'}
+    def to_python(self, value, state):
 
-                if value.find('%(user)s') == -1:
-                    raise formencode.Invalid(_("You need to specify %(user)s in "
-                                               "template for example uid=%(user)s "
-                                               ",dc=company...") ,
-                                             value, state)
+        if not value or not isinstance(value, (str, unicode)):
+            raise formencode.Invalid(_("The LDAP Login attribute of the CN "
+                                       "must be specified - this is the name "
+                                       "of the attribute that is equivalent "
+                                       "to 'username'"),
+                                     value, state)
 
-            except KeyError:
-                raise formencode.Invalid(_("Wrong template used, only %(user)s "
-                                           "is an valid entry") ,
-                                             value, state)
+        return value
 
-            return value
-    return _BaseDnValidator
 #===============================================================================
-# FORMS        
+# FORMS
 #===============================================================================
 class LoginForm(formencode.Schema):
     allow_extra_fields = True
@@ -334,17 +463,17 @@
                              min=1,
                              not_empty=True,
                              messages={
-                                       'empty':_('Please enter a login'),
-                                       'tooShort':_('Enter a value %(min)i characters long or more')}
+                                'empty':_('Please enter a login'),
+                                'tooShort':_('Enter a value %(min)i characters long or more')}
                             )
 
     password = UnicodeString(
                             strip=True,
-                            min=6,
+                            min=3,
                             not_empty=True,
                             messages={
-                                      'empty':_('Please enter a password'),
-                                      'tooShort':_('Enter %(min)i characters or more')}
+                                'empty':_('Please enter a password'),
+                                'tooShort':_('Enter %(min)i characters or more')}
                                 )
 
 
@@ -371,6 +500,41 @@
 
     return _UserForm
 
+
+def UsersGroupForm(edit=False, old_data={}, available_members=[]):
+    class _UsersGroupForm(formencode.Schema):
+        allow_extra_fields = True
+        filter_extra_fields = True
+
+        users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
+                       ValidUsersGroup(edit, old_data))
+
+        users_group_active = StringBoolean(if_missing=False)
+
+        if edit:
+            users_group_members = OneOf(available_members, hideList=False,
+                                        testValueList=True,
+                                        if_missing=None, not_empty=False)
+
+    return _UsersGroupForm
+
+def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
+    class _ReposGroupForm(formencode.Schema):
+        allow_extra_fields = True
+        filter_extra_fields = True
+
+        group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
+                               SlugifyName())
+        group_description = UnicodeString(strip=True, min=1,
+                                                not_empty=True)
+        group_parent_id = OneOf(available_groups, hideList=False,
+                                        testValueList=True,
+                                        if_missing=None, not_empty=False)
+
+        chained_validators = [ValidReposGroup(edit, old_data)]
+
+    return _ReposGroupForm
+
 def RegisterForm(edit=False, old_data={}):
     class _RegisterForm(formencode.Schema):
         allow_extra_fields = True
@@ -395,20 +559,27 @@
         email = All(ValidSystemEmail(), Email(not_empty=True))
     return _PasswordResetForm
 
-def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
+def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
+             repo_groups=[]):
     class _RepoForm(formencode.Schema):
         allow_extra_fields = True
         filter_extra_fields = False
         repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
-                        ValidRepoName(edit, old_data))
+                        SlugifyName())
+        clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False),
+                        ValidCloneUri()())
+        repo_group = OneOf(repo_groups, hideList=True)
+        repo_type = OneOf(supported_backends)
         description = UnicodeString(strip=True, min=1, not_empty=True)
         private = StringBoolean(if_missing=False)
         enable_statistics = StringBoolean(if_missing=False)
-        repo_type = OneOf(supported_backends)
+        enable_downloads = StringBoolean(if_missing=False)
+
         if edit:
-            user = All(Int(not_empty=True), ValidRepoUser)
+            #this is repo owner
+            user = All(UnicodeString(not_empty=True), ValidRepoUser)
 
-        chained_validators = [ValidPerms]
+        chained_validators = [ValidRepoName(edit, old_data), ValidPerms]
     return _RepoForm
 
 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
@@ -416,10 +587,13 @@
         allow_extra_fields = True
         filter_extra_fields = False
         fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
-                        ValidRepoName(edit, old_data))
+                        SlugifyName())
         description = UnicodeString(strip=True, min=1, not_empty=True)
         private = StringBoolean(if_missing=False)
         repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
+
+        chained_validators = [ValidForkName()]
+
     return _RepoForkForm
 
 def RepoSettingsForm(edit=False, old_data={}):
@@ -427,11 +601,11 @@
         allow_extra_fields = True
         filter_extra_fields = False
         repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
-                        ValidRepoName(edit, old_data))
+                        SlugifyName())
         description = UnicodeString(strip=True, min=1, not_empty=True)
         private = StringBoolean(if_missing=False)
 
-        chained_validators = [ValidPerms, ValidSettings]
+        chained_validators = [ValidRepoName(edit, old_data), ValidPerms, ValidSettings]
     return _RepoForm
 
 
@@ -441,6 +615,7 @@
         filter_extra_fields = False
         rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
         rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
+        rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
 
     return _ApplicationSettingsForm
 
@@ -470,7 +645,7 @@
     return _DefaultPermissionsForm
 
 
-def LdapSettingsForm(ldap_enable):
+def LdapSettingsForm(tls_reqcert_choices, search_scope_choices, tls_kind_choices):
     class _LdapSettingsForm(formencode.Schema):
         allow_extra_fields = True
         filter_extra_fields = True
@@ -478,9 +653,16 @@
         ldap_active = StringBoolean(if_missing=False)
         ldap_host = UnicodeString(strip=True,)
         ldap_port = Number(strip=True,)
-        ldap_ldaps = StringBoolean(if_missing=False)
+        ldap_tls_kind = OneOf(tls_kind_choices)
+        ldap_tls_reqcert = OneOf(tls_reqcert_choices)
         ldap_dn_user = UnicodeString(strip=True,)
         ldap_dn_pass = UnicodeString(strip=True,)
-        ldap_base_dn = All(BaseDnValidator(ldap_enable), UnicodeString(strip=True,))
+        ldap_base_dn = UnicodeString(strip=True,)
+        ldap_filter = UnicodeString(strip=True,)
+        ldap_search_scope = OneOf(search_scope_choices)
+        ldap_attr_login = All(AttrLoginValidator, UnicodeString(strip=True,))
+        ldap_attr_firstname = UnicodeString(strip=True,)
+        ldap_attr_lastname = UnicodeString(strip=True,)
+        ldap_attr_email = UnicodeString(strip=True,)
 
     return _LdapSettingsForm
--- a/rhodecode/model/meta.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/meta.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,6 +1,6 @@
 """SQLAlchemy Metadata and Session object"""
 from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import scoped_session, sessionmaker, class_mapper
+from sqlalchemy.orm import scoped_session, sessionmaker
 from beaker import cache
 
 from rhodecode.model import caching_query
@@ -19,52 +19,8 @@
                 )
           )
 
-class BaseModel(object):
-    """Base Model for all classess
-    
-    """
-
-    @classmethod
-    def _get_keys(cls):
-        """return column names for this model """
-        return class_mapper(cls).c.keys()
-
-    def get_dict(self):
-        """return dict with keys and values corresponding 
-        to this model data """
-
-        d = {}
-        for k in self._get_keys():
-            d[k] = getattr(self, k)
-        return d
-
-    def get_appstruct(self):
-        """return list with keys and values tupples corresponding 
-        to this model data """
-
-        l = []
-        for k in self._get_keys():
-            l.append((k, getattr(self, k),))
-        return l
-
-    def populate_obj(self, populate_dict):
-        """populate model with data from given populate_dict"""
-
-        for k in self._get_keys():
-            if k in populate_dict:
-                setattr(self, k, populate_dict[k])
-
-    @classmethod
-    def query(cls):
-        return Session.query(cls)
-
-    @classmethod
-    def get(cls, id_):
-        return Session.query(cls).get(id_)
-
-
 # The declarative Base
-Base = declarative_base(cls=BaseModel)
+Base = declarative_base()
 
 #to use cache use this in query
 #.options(FromCache("sqlalchemy_cache_type", "cachekey"))
--- a/rhodecode/model/permission.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/permission.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     permissions model for RhodeCode
-    
+
     :created_on: Aug 20, 2010
     :author: marcink
-    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -41,7 +41,7 @@
 
     def get_permission(self, permission_id, cache=False):
         """Get's permissions by id
-        
+
         :param permission_id: id of permission to get from database
         :param cache: use Cache for this query
         """
@@ -53,7 +53,7 @@
 
     def get_permission_by_name(self, name, cache=False):
         """Get's permissions by given name
-        
+
         :param name: name to fetch
         :param cache: Use cache for this query
         """
@@ -66,15 +66,17 @@
 
     def update(self, form_result):
         perm_user = self.sa.query(User)\
-                .filter(User.username == form_result['perm_user_name']).scalar()
-        u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all()
+                .filter(User.username ==
+                        form_result['perm_user_name']).scalar()
+        u2p = self.sa.query(UserToPerm).filter(UserToPerm.user ==
+                                               perm_user).all()
         if len(u2p) != 3:
             raise Exception('Defined: %s should be 3  permissions for default'
                             ' user. This should not happen please verify'
                             ' your database' % len(u2p))
 
         try:
-            #stage 1 change defaults    
+            #stage 1 change defaults
             for p in u2p:
                 if p.permission.permission_name.startswith('repository.'):
                     p.permission = self.get_permission_by_name(
@@ -104,7 +106,6 @@
                 perm_user.active = bool(form_result['anonymous'])
                 self.sa.add(perm_user)
 
-
             self.sa.commit()
         except (DatabaseError,):
             log.error(traceback.format_exc())
--- a/rhodecode/model/repo.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/repo.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~
 
     Repository model for rhodecode
-    
+
     :created_on: Jun 5, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -33,14 +33,17 @@
 from vcs.utils.lazy import LazyProperty
 from vcs.backends import get_backend
 
+from rhodecode.lib import safe_str
+
 from rhodecode.model import BaseModel
 from rhodecode.model.caching_query import FromCache
 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
-    Statistics, RhodeCodeUi
+    Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, Group
 from rhodecode.model.user import UserModel
 
 log = logging.getLogger(__name__)
 
+
 class RepoModel(BaseModel):
 
     @LazyProperty
@@ -60,7 +63,6 @@
                                           "get_repo_%s" % repo_id))
         return repo.scalar()
 
-
     def get_by_repo_name(self, repo_name, cache=False):
         repo = self.sa.query(Repository)\
             .filter(Repository.repo_name == repo_name)
@@ -70,56 +72,96 @@
                                           "get_repo_%s" % repo_name))
         return repo.scalar()
 
+
     def get_users_js(self):
 
         users = self.sa.query(User).filter(User.active == True).all()
         u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
-        users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
+        users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
                                                     u.lastname, u.username)
                                         for u in users])
         return users_array
 
+    def get_users_groups_js(self):
+        users_groups = self.sa.query(UsersGroup)\
+            .filter(UsersGroup.users_group_active == True).all()
+
+        g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
+
+        users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
+                                    (gr.users_group_id, gr.users_group_name,
+                                     len(gr.members))
+                                        for gr in users_groups])
+        return users_groups_array
 
     def update(self, repo_name, form_data):
         try:
             cur_repo = self.get_by_repo_name(repo_name, cache=False)
-            user_model = UserModel(self.sa)
 
             #update permissions
-            for username, perm in form_data['perms_updates']:
-                r2p = self.sa.query(RepoToPerm)\
-                        .filter(RepoToPerm.user == user_model.get_by_username(username))\
-                        .filter(RepoToPerm.repository == cur_repo)\
-                        .one()
+            for member, perm, member_type in form_data['perms_updates']:
+                if member_type == 'user':
+                    r2p = self.sa.query(RepoToPerm)\
+                            .filter(RepoToPerm.user == User.by_username(member))\
+                            .filter(RepoToPerm.repository == cur_repo)\
+                            .one()
 
-                r2p.permission = self.sa.query(Permission)\
-                                    .filter(Permission.permission_name == perm)\
-                                    .scalar()
-                self.sa.add(r2p)
+                    r2p.permission = self.sa.query(Permission)\
+                                        .filter(Permission.permission_name ==
+                                                perm).scalar()
+                    self.sa.add(r2p)
+                else:
+                    g2p = self.sa.query(UsersGroupRepoToPerm)\
+                            .filter(UsersGroupRepoToPerm.users_group ==
+                                    UsersGroup.get_by_group_name(member))\
+                            .filter(UsersGroupRepoToPerm.repository ==
+                                    cur_repo).one()
+
+                    g2p.permission = self.sa.query(Permission)\
+                                        .filter(Permission.permission_name ==
+                                                perm).scalar()
+                    self.sa.add(g2p)
 
             #set new permissions
-            for username, perm in form_data['perms_new']:
-                r2p = RepoToPerm()
-                r2p.repository = cur_repo
-                r2p.user = user_model.get_by_username(username, cache=False)
+            for member, perm, member_type in form_data['perms_new']:
+                if member_type == 'user':
+                    r2p = RepoToPerm()
+                    r2p.repository = cur_repo
+                    r2p.user = User.by_username(member)
 
-                r2p.permission = self.sa.query(Permission)\
-                                    .filter(Permission.permission_name == perm)\
-                                    .scalar()
-                self.sa.add(r2p)
+                    r2p.permission = self.sa.query(Permission)\
+                                        .filter(Permission.
+                                                permission_name == perm)\
+                                                .scalar()
+                    self.sa.add(r2p)
+                else:
+                    g2p = UsersGroupRepoToPerm()
+                    g2p.repository = cur_repo
+                    g2p.users_group = UsersGroup.get_by_group_name(member)
+                    g2p.permission = self.sa.query(Permission)\
+                                        .filter(Permission.
+                                                permission_name == perm)\
+                                                .scalar()
+                    self.sa.add(g2p)
 
             #update current repo
             for k, v in form_data.items():
                 if k == 'user':
-                    cur_repo.user = user_model.get(v)
+                    cur_repo.user = User.by_username(v)
+                elif k == 'repo_name':
+                    cur_repo.repo_name = form_data['repo_name_full']
+                elif k == 'repo_group':
+                    cur_repo.group_id = v
+
                 else:
                     setattr(cur_repo, k, v)
 
             self.sa.add(cur_repo)
 
-            if repo_name != form_data['repo_name']:
-                #rename our data
-                self.__rename_repo(repo_name, form_data['repo_name'])
+            if repo_name != form_data['repo_name_full']:
+                # rename repository
+                self.__rename_repo(old=repo_name,
+                                   new=form_data['repo_name_full'])
 
             self.sa.commit()
         except:
@@ -128,24 +170,33 @@
             raise
 
     def create(self, form_data, cur_user, just_db=False, fork=False):
+
         try:
             if fork:
-                #force str since hg doesn't go with unicode
-                repo_name = str(form_data['fork_name'])
-                org_name = str(form_data['repo_name'])
+                repo_name = form_data['fork_name']
+                org_name = form_data['repo_name']
+                org_full_name = org_name
 
             else:
-                org_name = repo_name = str(form_data['repo_name'])
+                org_name = repo_name = form_data['repo_name']
+                repo_name_full = form_data['repo_name_full']
+
             new_repo = Repository()
-            new_repo.enable_statistics = True
+            new_repo.enable_statistics = False
             for k, v in form_data.items():
                 if k == 'repo_name':
-                    v = repo_name
+                    if fork:
+                        v = repo_name
+                    else:
+                        v = repo_name_full
+                if k == 'repo_group':
+                    k = 'group_id'
+
                 setattr(new_repo, k, v)
 
             if fork:
                 parent_repo = self.sa.query(Repository)\
-                        .filter(Repository.repo_name == org_name).scalar()
+                        .filter(Repository.repo_name == org_full_name).one()
                 new_repo.fork = parent_repo
 
             new_repo.user_id = cur_user.user_id
@@ -154,7 +205,8 @@
             #create default permission
             repo_to_perm = RepoToPerm()
             default = 'repository.read'
-            for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
+            for p in UserModel(self.sa).get_by_username('default',
+                                                    cache=False).user_perms:
                 if p.permission.permission_name.startswith('repository.'):
                     default = p.permission.permission_name
                     break
@@ -172,7 +224,9 @@
             self.sa.add(repo_to_perm)
 
             if not just_db:
-                self.__create_repo(repo_name, form_data['repo_type'])
+                self.__create_repo(repo_name, form_data['repo_type'],
+                                   form_data['repo_group'],
+                                   form_data['clone_uri'])
 
             self.sa.commit()
 
@@ -212,6 +266,19 @@
             self.sa.rollback()
             raise
 
+    def delete_perm_users_group(self, form_data, repo_name):
+        try:
+            self.sa.query(UsersGroupRepoToPerm)\
+                .filter(UsersGroupRepoToPerm.repository \
+                        == self.get_by_repo_name(repo_name))\
+                .filter(UsersGroupRepoToPerm.users_group_id \
+                        == form_data['users_group_id']).delete()
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+            raise
+
     def delete_stats(self, repo_name):
         try:
             self.sa.query(Statistics)\
@@ -223,23 +290,40 @@
             self.sa.rollback()
             raise
 
+    def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
+        """
+        makes repository on filesystem. It's group aware means it'll create
+        a repository within a group, and alter the paths accordingly of
+        group location
 
-    def __create_repo(self, repo_name, alias):
-        """
-        makes repository on filesystem
         :param repo_name:
         :param alias:
+        :param parent_id:
+        :param clone_uri:
         """
-        from rhodecode.lib.utils import check_repo
-        repo_path = os.path.join(self.repos_path, repo_name)
-        if check_repo(repo_name, self.repos_path):
-            log.info('creating repo %s in %s', repo_name, repo_path)
+        from rhodecode.lib.utils import is_valid_repo
+        
+        if new_parent_id:
+            paths = Group.get(new_parent_id).full_path.split(Group.url_sep())
+            new_parent_path = os.sep.join(paths)
+        else:
+            new_parent_path = ''
+
+        repo_path = os.path.join(*map(lambda x:safe_str(x),
+                                [self.repos_path, new_parent_path, repo_name]))
+
+        if is_valid_repo(repo_path, self.repos_path) is False:
+            log.info('creating repo %s in %s @ %s', repo_name, repo_path,
+                     clone_uri)
             backend = get_backend(alias)
-            backend(repo_path, create=True)
+
+            backend(repo_path, create=True, src_url=clone_uri)
+
 
     def __rename_repo(self, old, new):
         """
         renames repository on filesystem
+
         :param old: old name
         :param new: new name
         """
@@ -248,8 +332,8 @@
         old_path = os.path.join(self.repos_path, old)
         new_path = os.path.join(self.repos_path, new)
         if os.path.isdir(new_path):
-            raise Exception('Was trying to rename to already existing dir %s',
-                            new_path)
+            raise Exception('Was trying to rename to already existing dir %s' \
+            		     % new_path)
         shutil.move(old_path, new_path)
 
     def __delete_repo(self, repo):
@@ -258,6 +342,7 @@
         added rm__ prefix into dir, and rename internat .hg/.git dirs so this
         repository is no longer valid for rhodecode, can be undeleted later on
         by reverting the renames on this repository
+
         :param repo: repo object
         """
         rm_path = os.path.join(self.repos_path, repo.repo_name)
@@ -268,5 +353,6 @@
                     os.path.join(rm_path, 'rm__.%s' % alias))
         #disable repo
         shutil.move(rm_path, os.path.join(self.repos_path, 'rm__%s__%s' \
-                                          % (datetime.today().isoformat(),
-                                             repo.repo_name)))
+                                          % (datetime.today()\
+                                             .strftime('%Y%m%d_%H%M%S_%f'),
+                                            repo.repo_name)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/model/repos_group.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.model.user_group
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    users groups model for RhodeCode
+
+    :created_on: Jan 25, 2011
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import logging
+import traceback
+import shutil
+
+from pylons.i18n.translation import _
+
+from vcs.utils.lazy import LazyProperty
+
+from rhodecode.model import BaseModel
+from rhodecode.model.caching_query import FromCache
+from rhodecode.model.db import Group, RhodeCodeUi
+
+log = logging.getLogger(__name__)
+
+
+class ReposGroupModel(BaseModel):
+
+    @LazyProperty
+    def repos_path(self):
+        """
+        Get's the repositories root path from database
+        """
+
+        q = RhodeCodeUi.get_by_key('/').one()
+        return q.ui_value
+
+    def __create_group(self, group_name, parent_id):
+        """
+        makes repositories group on filesystem
+
+        :param repo_name:
+        :param parent_id:
+        """
+
+        if parent_id:
+            paths = Group.get(parent_id).full_path.split(Group.url_sep())
+            parent_path = os.sep.join(paths)
+        else:
+            parent_path = ''
+
+        create_path = os.path.join(self.repos_path, parent_path, group_name)
+        log.debug('creating new group in %s', create_path)
+
+        if os.path.isdir(create_path):
+            raise Exception('That directory already exists !')
+
+
+        os.makedirs(create_path)
+
+
+    def __rename_group(self, old, old_parent_id, new, new_parent_id):
+        """
+        Renames a group on filesystem
+        
+        :param group_name:
+        """
+        log.debug('renaming repos group from %s to %s', old, new)
+
+        if new_parent_id:
+            paths = Group.get(new_parent_id).full_path.split(Group.url_sep())
+            new_parent_path = os.sep.join(paths)
+        else:
+            new_parent_path = ''
+
+        if old_parent_id:
+            paths = Group.get(old_parent_id).full_path.split(Group.url_sep())
+            old_parent_path = os.sep.join(paths)
+        else:
+            old_parent_path = ''
+
+        old_path = os.path.join(self.repos_path, old_parent_path, old)
+        new_path = os.path.join(self.repos_path, new_parent_path, new)
+
+        log.debug('renaming repos paths from %s to %s', old_path, new_path)
+
+        if os.path.isdir(new_path):
+            raise Exception('Was trying to rename to already '
+                            'existing dir %s' % new_path)
+        shutil.move(old_path, new_path)
+
+    def __delete_group(self, group):
+        """
+        Deletes a group from a filesystem
+        
+        :param group: instance of group from database
+        """
+        paths = group.full_path.split(Group.url_sep())
+        paths = os.sep.join(paths)
+
+        rm_path = os.path.join(self.repos_path, paths)
+        os.rmdir(rm_path)
+
+    def create(self, form_data):
+        try:
+            new_repos_group = Group()
+            new_repos_group.group_name = form_data['group_name']
+            new_repos_group.group_description = \
+                form_data['group_description']
+            new_repos_group.group_parent_id = form_data['group_parent_id']
+
+            self.sa.add(new_repos_group)
+
+            self.__create_group(form_data['group_name'],
+                                form_data['group_parent_id'])
+
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+            raise
+
+    def update(self, repos_group_id, form_data):
+
+        try:
+            repos_group = Group.get(repos_group_id)
+            old_name = repos_group.group_name
+            old_parent_id = repos_group.group_parent_id
+
+            repos_group.group_name = form_data['group_name']
+            repos_group.group_description = \
+                form_data['group_description']
+            repos_group.group_parent_id = form_data['group_parent_id']
+
+            self.sa.add(repos_group)
+
+            if old_name != form_data['group_name'] or (old_parent_id !=
+                                                form_data['group_parent_id']):
+                self.__rename_group(old=old_name, old_parent_id=old_parent_id,
+                                    new=form_data['group_name'],
+                                    new_parent_id=form_data['group_parent_id'])
+
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+            raise
+
+    def delete(self, users_group_id):
+        try:
+            users_group = Group.get(users_group_id)
+            self.sa.delete(users_group)
+            self.__delete_group(users_group)
+            self.sa.commit()
+        except:
+            log.error(traceback.format_exc())
+            self.sa.rollback()
+            raise
--- a/rhodecode/model/scm.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/scm.py	Fri Oct 07 01:08:50 2011 +0200
@@ -27,29 +27,23 @@
 import traceback
 import logging
 
+from sqlalchemy.exc import DatabaseError
+
 from vcs import get_backend
-from vcs.utils.helpers import get_scm
-from vcs.exceptions import RepositoryError, VCSError
+from vcs.exceptions import RepositoryError
 from vcs.utils.lazy import LazyProperty
-
-from mercurial import ui
-
-from beaker.cache import cache_region, region_invalidate
+from vcs.nodes import FileNode
 
 from rhodecode import BACKENDS
 from rhodecode.lib import helpers as h
+from rhodecode.lib import safe_str
 from rhodecode.lib.auth import HasRepoPermissionAny
-from rhodecode.lib.utils import get_repos, make_ui, action_logger
+from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
+    action_logger, EmptyChangeset
 from rhodecode.model import BaseModel
 from rhodecode.model.user import UserModel
-
 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
     UserFollowing, UserLog
-from rhodecode.model.caching_query import FromCache
-
-from sqlalchemy.orm import joinedload
-from sqlalchemy.orm.session import make_transient
-from sqlalchemy.exc import DatabaseError
 
 log = logging.getLogger(__name__)
 
@@ -69,6 +63,61 @@
     def __repr__(self):
         return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
 
+class CachedRepoList(object):
+
+    def __init__(self, db_repo_list, repos_path, order_by=None):
+        self.db_repo_list = db_repo_list
+        self.repos_path = repos_path
+        self.order_by = order_by
+        self.reversed = (order_by or '').startswith('-')
+
+    def __len__(self):
+        return len(self.db_repo_list)
+
+    def __repr__(self):
+        return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
+
+    def __iter__(self):
+        for dbr in self.db_repo_list:
+
+            scmr = dbr.scm_instance_cached
+
+            # check permission at this level
+            if not HasRepoPermissionAny('repository.read', 'repository.write',
+                                        'repository.admin')(dbr.repo_name,
+                                                            'get repo check'):
+                continue
+
+            if scmr is None:
+                log.error('%s this repository is present in database but it '
+                          'cannot be created as an scm instance',
+                          dbr.repo_name)
+                continue
+
+            last_change = scmr.last_change
+            tip = h.get_changeset_safe(scmr, 'tip')
+
+            tmp_d = {}
+            tmp_d['name'] = dbr.repo_name
+            tmp_d['name_sort'] = tmp_d['name'].lower()
+            tmp_d['description'] = dbr.description
+            tmp_d['description_sort'] = tmp_d['description']
+            tmp_d['last_change'] = last_change
+            tmp_d['last_change_sort'] = time.mktime(last_change \
+                                                    .timetuple())
+            tmp_d['tip'] = tip.raw_id
+            tmp_d['tip_sort'] = tip.revision
+            tmp_d['rev'] = tip.revision
+            tmp_d['contact'] = dbr.user.full_contact
+            tmp_d['contact_sort'] = tmp_d['contact']
+            tmp_d['owner_sort'] = tmp_d['contact']
+            tmp_d['repo_archives'] = list(scmr._get_archives())
+            tmp_d['last_msg'] = tip.message
+            tmp_d['author'] = tip.author
+            tmp_d['dbrepo'] = dbr.get_dict()
+            tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork \
+                                                                    else {}
+            yield tmp_d
 
 class ScmModel(BaseModel):
     """Generic Scm Model
@@ -83,21 +132,22 @@
 
         return q.ui_value
 
-    def repo_scan(self, repos_path, baseui):
+    def repo_scan(self, repos_path=None):
         """Listing of repositories in given path. This path should not be a
         repository itself. Return a dictionary of repository objects
 
         :param repos_path: path to directory containing repositories
-        :param baseui: baseui instance to instantiate MercurialRepostitory with
         """
 
         log.info('scanning for repositories in %s', repos_path)
 
-        if not isinstance(baseui, ui.ui):
-            baseui = make_ui('db')
+        if repos_path is None:
+            repos_path = self.repos_path
+
+        baseui = make_ui('db')
         repos_list = {}
 
-        for name, path in get_repos(repos_path):
+        for name, path in get_filesystem_repos(repos_path, recursive=True):
             try:
                 if name in repos_list:
                     raise RepositoryError('Duplicate repository name %s '
@@ -107,7 +157,10 @@
                     klass = get_backend(path[0])
 
                     if path[0] == 'hg' and path[0] in BACKENDS.keys():
-                        repos_list[name] = klass(path[1], baseui=baseui)
+
+                        # for mercurial we need to have an str path
+                        repos_list[name] = klass(safe_str(path[1]),
+                                                 baseui=baseui)
 
                     if path[0] == 'git' and path[0] in BACKENDS.keys():
                         repos_list[name] = klass(path[1])
@@ -116,121 +169,23 @@
 
         return repos_list
 
-    def get_repos(self, all_repos=None):
-        """Get all repos from db and for each repo create it's
-        backend instance.and fill that backed with information from database
+    def get_repos(self, all_repos=None, sort_key=None):
+        """
+        Get all repos from db and for each repo create it's
+        backend instance and fill that backed with information from database
 
-        :param all_repos: give specific repositories list, good for filtering
+        :param all_repos: list of repository names as strings
+            give specific repositories list, good for filtering
         """
-
         if all_repos is None:
             all_repos = self.sa.query(Repository)\
-                .order_by(Repository.repo_name).all()
-
-        #get the repositories that should be invalidated
-        invalidation_list = [str(x.cache_key) for x in \
-                             self.sa.query(CacheInvalidation.cache_key)\
-                             .filter(CacheInvalidation.cache_active == False)\
-                             .all()]
-
-        for r in all_repos:
-
-            repo = self.get(r.repo_name, invalidation_list)
-
-            if repo is not None:
-                last_change = repo.last_change
-                tip = h.get_changeset_safe(repo, 'tip')
-
-                tmp_d = {}
-                tmp_d['name'] = repo.name
-                tmp_d['name_sort'] = tmp_d['name'].lower()
-                tmp_d['description'] = repo.dbrepo.description
-                tmp_d['description_sort'] = tmp_d['description']
-                tmp_d['last_change'] = last_change
-                tmp_d['last_change_sort'] = time.mktime(last_change \
-                                                        .timetuple())
-                tmp_d['tip'] = tip.raw_id
-                tmp_d['tip_sort'] = tip.revision
-                tmp_d['rev'] = tip.revision
-                tmp_d['contact'] = repo.dbrepo.user.full_contact
-                tmp_d['contact_sort'] = tmp_d['contact']
-                tmp_d['owner_sort'] = tmp_d['contact']
-                tmp_d['repo_archives'] = list(repo._get_archives())
-                tmp_d['last_msg'] = tip.message
-                tmp_d['repo'] = repo
-                yield tmp_d
-
-    def get_repo(self, repo_name):
-        return self.get(repo_name)
-
-    def get(self, repo_name, invalidation_list=None):
-        """Get's repository from given name, creates BackendInstance and
-        propagates it's data from database with all additional information
-
-        :param repo_name:
-        :param invalidation_list: if a invalidation list is given the get
-            method should not manually check if this repository needs
-            invalidation and just invalidate the repositories in list
-
-        """
-        if not HasRepoPermissionAny('repository.read', 'repository.write',
-                            'repository.admin')(repo_name, 'get repo check'):
-            return
+                        .filter(Repository.group_id == None)\
+                        .order_by(Repository.repo_name).all()
 
-        #======================================================================
-        # CACHE FUNCTION
-        #======================================================================
-        @cache_region('long_term')
-        def _get_repo(repo_name):
-
-            repo_path = os.path.join(self.repos_path, repo_name)
-
-            try:
-                alias = get_scm(repo_path)[0]
-
-                log.debug('Creating instance of %s repository', alias)
-                backend = get_backend(alias)
-            except VCSError:
-                log.error(traceback.format_exc())
-                return
-
-            if alias == 'hg':
-                from pylons import app_globals as g
-                repo = backend(repo_path, create=False, baseui=g.baseui)
-                #skip hidden web repository
-                if repo._get_hidden():
-                    return
-            else:
-                repo = backend(repo_path, create=False)
+        repo_iter = CachedRepoList(all_repos, repos_path=self.repos_path,
+                                   order_by=sort_key)
 
-            dbrepo = self.sa.query(Repository)\
-                .options(joinedload(Repository.fork))\
-                .options(joinedload(Repository.user))\
-                .filter(Repository.repo_name == repo_name)\
-                .scalar()
-
-            make_transient(dbrepo)
-            if dbrepo.user:
-                make_transient(dbrepo.user)
-            if dbrepo.fork:
-                make_transient(dbrepo.fork)
-
-            repo.dbrepo = dbrepo
-            return repo
-
-        pre_invalidate = True
-        if invalidation_list is not None:
-            pre_invalidate = repo_name in invalidation_list
-
-        if pre_invalidate:
-            invalidate = self._should_invalidate(repo_name)
-
-            if invalidate:
-                log.info('invalidating cache for repository %s', repo_name)
-                region_invalidate(_get_repo, None, repo_name)
-                self._mark_invalidated(invalidate)
-
-        return _get_repo(repo_name)
+        return repo_iter
 
     def mark_for_invalidation(self, repo_name):
         """Puts cache invalidation task into db for
@@ -244,7 +199,7 @@
             .filter(CacheInvalidation.cache_key == repo_name).scalar()
 
         if cache:
-            #mark this cache as inactive
+            # mark this cache as inactive
             cache.cache_active = False
         else:
             log.debug('cache key not found in invalidation db -> creating one')
@@ -317,7 +272,7 @@
             self.sa.rollback()
             raise
 
-    def is_following_repo(self, repo_name, user_id):
+    def is_following_repo(self, repo_name, user_id, cache=False):
         r = self.sa.query(Repository)\
             .filter(Repository.repo_name == repo_name).scalar()
 
@@ -327,7 +282,7 @@
 
         return f is not None
 
-    def is_following_user(self, username, user_id):
+    def is_following_user(self, username, user_id, cache=False):
         u = UserModel(self.sa).get_by_username(username)
 
         f = self.sa.query(UserFollowing)\
@@ -337,13 +292,106 @@
         return f is not None
 
     def get_followers(self, repo_id):
+        if not isinstance(repo_id, int):
+            repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id')
+
         return self.sa.query(UserFollowing)\
                 .filter(UserFollowing.follows_repo_id == repo_id).count()
 
     def get_forks(self, repo_id):
+        if not isinstance(repo_id, int):
+            repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id')
+
         return self.sa.query(Repository)\
                 .filter(Repository.fork_id == repo_id).count()
 
+    def pull_changes(self, repo_name, username):
+        dbrepo = Repository.by_repo_name(repo_name)
+        clone_uri = dbrepo.clone_uri
+        if not clone_uri:
+            raise Exception("This repository doesn't have a clone uri")
+        
+        repo = dbrepo.scm_instance
+        try:
+            extras = {'ip': '',
+                      'username': username,
+                      'action': 'push_remote',
+                      'repository': repo_name}
+
+            #inject ui extra param to log this action via push logger
+            for k, v in extras.items():
+                repo._repo.ui.setconfig('rhodecode_extras', k, v)
+
+            repo.pull(clone_uri)
+            self.mark_for_invalidation(repo_name)
+        except:
+            log.error(traceback.format_exc())
+            raise
+
+    def commit_change(self, repo, repo_name, cs, user, author, message, content,
+                      f_path):
+
+        if repo.alias == 'hg':
+            from vcs.backends.hg import MercurialInMemoryChangeset as IMC
+        elif repo.alias == 'git':
+            from vcs.backends.git import GitInMemoryChangeset as IMC
+
+        # decoding here will force that we have proper encoded values
+        # in any other case this will throw exceptions and deny commit
+        content = safe_str(content)
+        message = safe_str(message)
+        path = safe_str(f_path)
+        author = safe_str(author)
+        m = IMC(repo)
+        m.change(FileNode(path, content))
+        tip = m.commit(message=message,
+                 author=author,
+                 parents=[cs], branch=cs.branch)
+
+        new_cs = tip.short_id
+        action = 'push_local:%s' % new_cs
+
+        action_logger(user, action, repo_name)
+
+        self.mark_for_invalidation(repo_name)
+
+    def create_node(self, repo, repo_name, cs, user, author, message, content,
+                      f_path):
+        if repo.alias == 'hg':
+            from vcs.backends.hg import MercurialInMemoryChangeset as IMC
+        elif repo.alias == 'git':
+            from vcs.backends.git import GitInMemoryChangeset as IMC
+        # decoding here will force that we have proper encoded values
+        # in any other case this will throw exceptions and deny commit
+        
+        if isinstance(content,(basestring,)):
+            content = safe_str(content)
+        elif isinstance(content,file):
+            content = content.read()
+            
+        message = safe_str(message)
+        path = safe_str(f_path)
+        author = safe_str(author)
+        m = IMC(repo)
+
+        if isinstance(cs, EmptyChangeset):
+            # Emptychangeset means we we're editing empty repository
+            parents = None
+        else:
+            parents = [cs]
+
+        m.add(FileNode(path, content=content))
+        tip = m.commit(message=message,
+                 author=author,
+                 parents=parents, branch=cs.branch)
+        new_cs = tip.short_id
+        action = 'push_local:%s' % new_cs
+
+        action_logger(user, action, repo_name)
+
+        self.mark_for_invalidation(repo_name)
+
+
     def get_unread_journal(self):
         return self.sa.query(UserLog).count()
 
@@ -354,27 +402,9 @@
         """
 
         ret = self.sa.query(CacheInvalidation)\
-            .options(FromCache('sql_cache_short',
-                           'get_invalidation_%s' % repo_name))\
             .filter(CacheInvalidation.cache_key == repo_name)\
             .filter(CacheInvalidation.cache_active == False)\
             .scalar()
 
         return ret
 
-    def _mark_invalidated(self, cache_key):
-        """ Marks all occurences of cache to invaldation as
-        already invalidated
-
-        :param cache_key:
-        """
-
-        if cache_key:
-            log.debug('marking %s as already invalidated', cache_key)
-        try:
-            cache_key.cache_active = True
-            self.sa.add(cache_key)
-            self.sa.commit()
-        except (DatabaseError,):
-            log.error(traceback.format_exc())
-            self.sa.rollback()
--- a/rhodecode/model/settings.py	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    rhodecode.model.settings
-    ~~~~~~~~~~~~~~~~~~~~~~~~
-
-    Settings model for RhodeCode
-
-    :created on Nov 17, 2010
-    :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
-    :license: GPLv3, see COPYING for more details.
-"""
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import logging
-
-from rhodecode.model import BaseModel
-from rhodecode.model.caching_query import FromCache
-from rhodecode.model.db import  RhodeCodeSettings
-
-log = logging.getLogger(__name__)
-
-class SettingsModel(BaseModel):
-    """
-    Settings model
-    """
-
-    def get(self, settings_key, cache=False):
-        r = self.sa.query(RhodeCodeSettings)\
-            .filter(RhodeCodeSettings.app_settings_name == settings_key).scalar()
-        if cache:
-            r = r.options(FromCache("sql_cache_short",
-                                          "get_setting_%s" % settings_key))
-        return r
-
-    def get_app_settings(self, cache=False):
-        """Get's config from database, each config key is prefixed with 
-        'rhodecode_' prefix, than global pylons config is updated with such 
-        keys
-        """
-
-        ret = self.sa.query(RhodeCodeSettings)
-
-        if cache:
-            ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
-
-        if not ret:
-            raise Exception('Could not get application settings !')
-        settings = {}
-        for each in ret:
-            settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
-
-        return settings
-
-    def get_ldap_settings(self):
-        """
-        Returns ldap settings from database
-        :returns:
-        ldap_active
-        ldap_host
-        ldap_port 
-        ldap_ldaps
-        ldap_tls_reqcert
-        ldap_dn_user 
-        ldap_dn_pass 
-        ldap_base_dn
-        ldap_filter
-        ldap_search_scope
-        ldap_attr_login
-        ldap_attr_firstname
-        ldap_attr_lastname
-        ldap_attr_email
-        """
-        # ldap_search_scope
-
-        r = self.sa.query(RhodeCodeSettings)\
-                .filter(RhodeCodeSettings.app_settings_name\
-                        .startswith('ldap_'))\
-                .all()
-
-        fd = {}
-
-        for row in r:
-            v = row.app_settings_value
-            if v in ['true', 'yes', 'on', 'y', 't', '1']:
-                v = True
-            elif v in ['false', 'no', 'off', 'n', 'f', '0']:
-                v = False
-
-            fd.update({row.app_settings_name:v})
-
-        return fd
--- a/rhodecode/model/user.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/model/user.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~~~
 
     users model for RhodeCode
-    
+
     :created_on: Apr 9, 2010
     :author: marcink
-    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
     :license: GPLv3, see COPYING for more details.
 """
 # This program is free software: you can redistribute it and/or modify
@@ -30,14 +30,23 @@
 
 from rhodecode.model import BaseModel
 from rhodecode.model.caching_query import FromCache
-from rhodecode.model.db import User
-
-from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
+from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
+    UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember
+from rhodecode.lib.exceptions import DefaultUserException, \
+    UserOwnsReposException
 
 from sqlalchemy.exc import DatabaseError
+from rhodecode.lib import generate_api_key
+from sqlalchemy.orm import joinedload
 
 log = logging.getLogger(__name__)
 
+PERM_WEIGHTS = {'repository.none': 0,
+                'repository.read': 1,
+                'repository.write': 3,
+                'repository.admin': 3}
+
+
 class UserModel(BaseModel):
 
     def get(self, user_id, cache=False):
@@ -47,7 +56,6 @@
                                           "get_user_%s" % user_id))
         return user.get(user_id)
 
-
     def get_by_username(self, username, cache=False, case_insensitive=False):
 
         if case_insensitive:
@@ -60,12 +68,22 @@
                                           "get_user_%s" % username))
         return user.scalar()
 
+    def get_by_api_key(self, api_key, cache=False):
+
+        user = self.sa.query(User)\
+                .filter(User.api_key == api_key)
+        if cache:
+            user = user.options(FromCache("sql_cache_short",
+                                          "get_user_%s" % api_key))
+        return user.scalar()
+
     def create(self, form_data):
         try:
             new_user = User()
             for k, v in form_data.items():
                 setattr(new_user, k, v)
 
+            new_user.api_key = generate_api_key(form_data['username'])
             self.sa.add(new_user)
             self.sa.commit()
         except:
@@ -73,26 +91,29 @@
             self.sa.rollback()
             raise
 
-    def create_ldap(self, username, password):
+    def create_ldap(self, username, password, user_dn, attrs):
         """
         Checks if user is in database, if not creates this user marked
         as ldap user
         :param username:
         :param password:
+        :param user_dn:
+        :param attrs:
         """
         from rhodecode.lib.auth import get_crypt_password
         log.debug('Checking for such ldap account in RhodeCode database')
         if self.get_by_username(username, case_insensitive=True) is None:
             try:
                 new_user = User()
-                new_user.username = username.lower()#add ldap account always lowercase
+                # add ldap account always lowercase
+                new_user.username = username.lower()
                 new_user.password = get_crypt_password(password)
-                new_user.email = '%s@ldap.server' % username
+                new_user.api_key = generate_api_key(username)
+                new_user.email = attrs['email']
                 new_user.active = True
-                new_user.is_ldap = True
-                new_user.name = '%s@ldap' % username
-                new_user.lastname = ''
-
+                new_user.ldap_dn = user_dn
+                new_user.name = attrs['name']
+                new_user.lastname = attrs['lastname']
 
                 self.sa.add(new_user)
                 self.sa.commit()
@@ -130,19 +151,20 @@
 
     def update(self, user_id, form_data):
         try:
-            new_user = self.get(user_id, cache=False)
-            if new_user.username == 'default':
+            user = self.get(user_id, cache=False)
+            if user.username == 'default':
                 raise DefaultUserException(
                                 _("You can't Edit this user since it's"
                                   " crucial for entire application"))
 
             for k, v in form_data.items():
                 if k == 'new_password' and v != '':
-                    new_user.password = v
+                    user.password = v
+                    user.api_key = generate_api_key(user.username)
                 else:
-                    setattr(new_user, k, v)
+                    setattr(user, k, v)
 
-            self.sa.add(new_user)
+            self.sa.add(user)
             self.sa.commit()
         except:
             log.error(traceback.format_exc())
@@ -151,19 +173,20 @@
 
     def update_my_account(self, user_id, form_data):
         try:
-            new_user = self.get(user_id, cache=False)
-            if new_user.username == 'default':
+            user = self.get(user_id, cache=False)
+            if user.username == 'default':
                 raise DefaultUserException(
                                 _("You can't Edit this user since it's"
                                   " crucial for entire application"))
             for k, v in form_data.items():
                 if k == 'new_password' and v != '':
-                    new_user.password = v
+                    user.password = v
+                    user.api_key = generate_api_key(user.username)
                 else:
                     if k not in ['admin', 'active']:
-                        setattr(new_user, k, v)
+                        setattr(user, k, v)
 
-            self.sa.add(new_user)
+            self.sa.add(user)
             self.sa.commit()
         except:
             log.error(traceback.format_exc())
@@ -190,32 +213,175 @@
             self.sa.rollback()
             raise
 
+    def reset_password_link(self, data):
+        from rhodecode.lib.celerylib import tasks, run_task
+        run_task(tasks.send_password_link, data['email'])
+
     def reset_password(self, data):
         from rhodecode.lib.celerylib import tasks, run_task
         run_task(tasks.reset_user_password, data['email'])
 
+    def fill_data(self, auth_user, user_id=None, api_key=None):
+        """
+        Fetches auth_user by user_id,or api_key if present.
+        Fills auth_user attributes with those taken from database.
+        Additionally set's is_authenitated if lookup fails
+        present in database
 
-    def fill_data(self, user):
+        :param auth_user: instance of user to set attributes
+        :param user_id: user id to fetch by
+        :param api_key: api key to fetch by
         """
-        Fills user data with those from database and log out user if not 
-        present in database
-        :param user:
+        if user_id is None and api_key is None:
+            raise Exception('You need to pass user_id or api_key')
+
+        try:
+            if api_key:
+                dbuser = self.get_by_api_key(api_key)
+            else:
+                dbuser = self.get(user_id)
+
+            if dbuser is not None:
+                log.debug('filling %s data', dbuser)
+                for k, v in dbuser.get_dict().items():
+                    setattr(auth_user, k, v)
+
+        except:
+            log.error(traceback.format_exc())
+            auth_user.is_authenticated = False
+
+        return auth_user
+
+    def fill_perms(self, user):
+        """
+        Fills user permission attribute with permissions taken from database
+        works for permissions given for repositories, and for permissions that
+        are granted to groups
+
+        :param user: user instance to fill his perms
         """
 
-        if not hasattr(user, 'user_id') or user.user_id is None:
-            raise Exception('passed in user has to have the user_id attribute')
+        user.permissions['repositories'] = {}
+        user.permissions['global'] = set()
+
+        #======================================================================
+        # fetch default permissions
+        #======================================================================
+        default_user = self.get_by_username('default', cache=True)
+
+        default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
+            .join((Repository, RepoToPerm.repository_id ==
+                   Repository.repo_id))\
+            .join((Permission, RepoToPerm.permission_id ==
+                   Permission.permission_id))\
+            .filter(RepoToPerm.user == default_user).all()
+
+        if user.is_admin:
+            #==================================================================
+            # #admin have all default rights set to admin
+            #==================================================================
+            user.permissions['global'].add('hg.admin')
+
+            for perm in default_perms:
+                p = 'repository.admin'
+                user.permissions['repositories'][perm.RepoToPerm.
+                                                 repository.repo_name] = p
 
+        else:
+            #==================================================================
+            # set default permissions
+            #==================================================================
+            uid = user.user_id
+
+            #default global
+            default_global_perms = self.sa.query(UserToPerm)\
+                .filter(UserToPerm.user == default_user)
+
+            for perm in default_global_perms:
+                user.permissions['global'].add(perm.permission.permission_name)
+
+            #default for repositories
+            for perm in default_perms:
+                if perm.Repository.private and not (perm.Repository.user_id ==
+                                                    uid):
+                    #diself.sable defaults for private repos,
+                    p = 'repository.none'
+                elif perm.Repository.user_id == uid:
+                    #set admin if owner
+                    p = 'repository.admin'
+                else:
+                    p = perm.Permission.permission_name
+
+                user.permissions['repositories'][perm.RepoToPerm.
+                                                 repository.repo_name] = p
+
+            #==================================================================
+            # overwrite default with user permissions if any
+            #==================================================================
 
-        log.debug('filling auth user data')
-        try:
-            dbuser = self.get(user.user_id)
-            user.username = dbuser.username
-            user.is_admin = dbuser.admin
-            user.name = dbuser.name
-            user.lastname = dbuser.lastname
-            user.email = dbuser.email
-        except:
-            log.error(traceback.format_exc())
-            user.is_authenticated = False
+            #user global
+            user_perms = self.sa.query(UserToPerm)\
+                    .options(joinedload(UserToPerm.permission))\
+                    .filter(UserToPerm.user_id == uid).all()
+
+            for perm in user_perms:
+                user.permissions['global'].add(perm.permission.
+                                               permission_name)
+
+            #user repositories
+            user_repo_perms = self.sa.query(RepoToPerm, Permission,
+                                            Repository)\
+                .join((Repository, RepoToPerm.repository_id ==
+                       Repository.repo_id))\
+                .join((Permission, RepoToPerm.permission_id ==
+                       Permission.permission_id))\
+                .filter(RepoToPerm.user_id == uid).all()
+
+            for perm in user_repo_perms:
+                # set admin if owner
+                if perm.Repository.user_id == uid:
+                    p = 'repository.admin'
+                else:
+                    p = perm.Permission.permission_name
+                user.permissions['repositories'][perm.RepoToPerm.
+                                                 repository.repo_name] = p
+
+            #==================================================================
+            # check if user is part of groups for this repository and fill in
+            # (or replace with higher) permissions
+            #==================================================================
+
+            #users group global
+            user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
+                .options(joinedload(UsersGroupToPerm.permission))\
+                .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
+                       UsersGroupMember.users_group_id))\
+                .filter(UsersGroupMember.user_id == uid).all()
+
+            for perm in user_perms_from_users_groups:
+                user.permissions['global'].add(perm.permission.permission_name)
+
+            #users group repositories
+            user_repo_perms_from_users_groups = self.sa.query(
+                                                UsersGroupRepoToPerm,
+                                                Permission, Repository,)\
+                .join((Repository, UsersGroupRepoToPerm.repository_id ==
+                       Repository.repo_id))\
+                .join((Permission, UsersGroupRepoToPerm.permission_id ==
+                       Permission.permission_id))\
+                .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
+                       UsersGroupMember.users_group_id))\
+                .filter(UsersGroupMember.user_id == uid).all()
+
+            for perm in user_repo_perms_from_users_groups:
+                p = perm.Permission.permission_name
+                cur_perm = user.permissions['repositories'][perm.
+                                                    UsersGroupRepoToPerm.
+                                                    repository.repo_name]
+                #overwrite permission only if it's greater than permission
+                # given from other sources
+                if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
+                    user.permissions['repositories'][perm.UsersGroupRepoToPerm.
+                                                     repository.repo_name] = p
 
         return user
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/public/css/codemirror.css	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,55 @@
+.CodeMirror {
+  overflow: auto;
+  height: 450px;
+  line-height: 1em;
+  font-family: monospace;
+  _position: relative; /* IE6 hack */
+  margin:20px;
+}
+
+.CodeMirror-gutter {
+  position: absolute; left: 0; top: 0;
+  background-color: #f7f7f7;
+  border-right: 1px solid #eee;
+  min-width: 2em;
+  height: 100%;
+}
+.CodeMirror-gutter-text {
+  color: #aaa;
+  text-align: right;
+  padding: .4em .2em .4em .4em;
+}
+.CodeMirror-lines {
+  padding: .4em;
+}
+
+.CodeMirror pre {
+  -moz-border-radius: 0;
+  -webkit-border-radius: 0;
+  -o-border-radius: 0;
+  border-radius: 0;
+  border-width: 0; margin: 0; padding: 0; background: transparent;
+  font-family: inherit;
+}
+
+.CodeMirror-cursor {
+  z-index: 10;
+  position: absolute;
+  visibility: hidden;
+  border-left: 1px solid black !important;
+}
+.CodeMirror-focused .CodeMirror-cursor {
+  visibility: visible;
+}
+
+span.CodeMirror-selected {
+  background: #ccc !important;
+  color: HighlightText !important;
+}
+.CodeMirror-focused span.CodeMirror-selected {
+  background: Highlight !important;
+}
+
+.CodeMirror-matchingbracket {color: #0f0 !important;}
+.CodeMirror-nonmatchingbracket {color: #f22 !important;}
+.CodeMirror-gutter-text{color: #003367 !important;}
\ No newline at end of file
--- a/rhodecode/public/css/pygments.css	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/public/css/pygments.css	Fri Oct 07 01:08:50 2011 +0200
@@ -24,7 +24,11 @@
 }
 
 div.codeblock .code-body table{
-    width: 0 !important;    
+    width: 0 !important;
+    border: 0px !important;
+}
+div.codeblock .code-body table td {
+	border: 0px !important;
 }
 div.code-body {
 	background-color: #FFFFFF;
@@ -53,6 +57,10 @@
 	padding: 5px;
     margin: 0;
 }
+.code-highlight pre div:target { 
+    background-color: #FFFFBE !important;
+}
+    
 .linenos a { text-decoration: none; }
 
 .code { display: block; }
--- a/rhodecode/public/css/style.css	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/public/css/style.css	Fri Oct 07 01:08:50 2011 +0200
@@ -52,7 +52,6 @@
 color:#003367;
 text-decoration:none;
 cursor:pointer;
-font-weight:700;
 }
 
 a:hover {
@@ -198,7 +197,8 @@
 -moz-border-radius: 0px 0px 8px 8px;
 border-radius: 0px 0px 8px 8px;
 height:37px;
-background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367
+background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
+box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 }
 
 #header ul#logged-user li {
@@ -250,9 +250,13 @@
 clear:both;
 position:relative;
 background:#003367 url("../images/header_inner.png") repeat-x;
-border-bottom:2px solid #fff;
 margin:0;
 padding:0;
+box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
+-webkit-border-radius: 4px 4px 4px 4px;
+-khtml-border-radius: 4px 4px 4px 4px; 
+-moz-border-radius: 4px 4px 4px 4px;
+border-radius: 4px 4px 4px 4px;
 }
 
 #header #header-inner #home a {
@@ -290,7 +294,7 @@
 float:right;
 list-style-type:none;
 list-style-position:outside;
-margin:10px 5px 0 0;
+margin:6px 5px 0 0;
 padding:0;
 }
 
@@ -311,8 +315,12 @@
 color:#FFF;
 font-weight:700;
 text-decoration:none;
-background:#369 url("../images/quick_l.png") no-repeat top left;
+background:#369;
 padding:0;
+-webkit-border-radius: 4px 4px 4px 4px;
+-khtml-border-radius: 4px 4px 4px 4px; 
+-moz-border-radius: 4px 4px 4px 4px;
+border-radius: 4px 4px 4px 4px;
 }
 
 #header #header-inner #quick li span.short {
@@ -325,7 +333,6 @@
 height:1%;
 display:block;
 float:left;
-background:url("../images/quick_r.png") no-repeat top right;
 border-left:1px solid #3f6f9f;
 margin:0;
 padding:10px 12px 8px 10px;
@@ -340,7 +347,6 @@
 top:0;
 left:0;
 border-left:none;
-background:url("../images/quick_l.png") no-repeat top left;
 border-right:1px solid #2e5c89;
 padding:8px 8px 4px;
 }
@@ -349,26 +355,22 @@
 top:0;
 left:0;
 border-left:none;
-background:url("../images/quick_l.png") no-repeat top left;
 border-right:1px solid #2e5c89;
 padding:9px 4px 4px;
 }
 
 #header #header-inner #quick li a:hover {
-background:#4e4e4e url("../images/quick_l_selected.png") no-repeat top left;
+background:#4e4e4e  no-repeat top left;
 }
 
 #header #header-inner #quick li a:hover span {
 border-left:1px solid #545454;
-background:url("../images/quick_r_selected.png") no-repeat top right;
 }
 
 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short {
 border-left:none;
 border-right:1px solid #464646;
-background:url("../images/quick_l_selected.png") no-repeat top left;
-}
-
+}
 
 #header #header-inner #quick ul {
 top:29px;
@@ -389,6 +391,12 @@
 overflow-x:hidden;
 overflow-y:auto;
 }
+#header #header-inner #quick ul.repo_switcher li.qfilter_rs {
+float:none;
+margin:0;
+border-bottom:2px solid #003367;
+}
+
 
 #header #header-inner #quick .repo_switcher_type{
 position:absolute;
@@ -471,6 +479,13 @@
 padding:12px 9px 7px 24px;
 }
 
+#header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover {
+background:url("../images/icons/database_link.png") no-repeat scroll 4px 9px #FFF;
+width:167px;
+margin:0;
+padding:12px 9px 7px 24px;
+}
+
 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
 width:167px;
@@ -548,6 +563,47 @@
 padding:12px 9px 7px 24px;
 }
 
+
+.quick_repo_menu{
+	background: #FFF url("../images/vertical-indicator.png") 8px 50% no-repeat !important;
+	cursor: pointer;
+	width: 8px;
+}
+.quick_repo_menu.active{
+    background: #FFF url("../images/horizontal-indicator.png") 4px 50% no-repeat !important;
+    cursor: pointer;
+}
+.quick_repo_menu .menu_items{
+	margin-top:6px;
+	width:150px;
+	position: absolute;
+	background-color:#FFF;
+    background: none repeat scroll 0 0 #FFFFFF;
+    border-color: #003367 #666666 #666666;
+    border-right: 1px solid #666666;
+    border-style: solid;
+    border-width: 1px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+.quick_repo_menu .menu_items li{
+    padding:0 !important;
+}
+.quick_repo_menu .menu_items a{
+	display: block;
+	padding: 4px 12px 4px 8px;
+}
+.quick_repo_menu .menu_items a:hover{
+    background-color: #EEE;
+    text-decoration: none;
+    
+}
+.quick_repo_menu .menu_items .icon img{
+	margin-bottom:-2px;
+}
+.quick_repo_menu .menu_items.hidden{
+	display: none;
+}
+
 #content #left {
 left:0;
 width:280px;
@@ -564,6 +620,12 @@
 background:#fff;
 margin:0 0 10px;
 padding:0 0 10px;
+-webkit-border-radius: 4px 4px 4px 4px;
+-khtml-border-radius: 4px 4px 4px 4px; 
+-moz-border-radius: 4px 4px 4px 4px;
+border-radius: 4px 4px 4px 4px;
+box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
+
 }
 
 #content div.box-left {
@@ -829,8 +891,8 @@
 }
 
 #content div.box div.form div.fields div.field div.label {
-left:80px;
-width:auto;
+left:70px;
+width:155px;
 position:absolute;
 margin:0;
 padding:8px 0 0 5px;
@@ -866,6 +928,9 @@
 #content div.box div.form div.fields div.field div.input {
 margin:0 0 0 200px;
 }
+#content div.box div.form div.fields div.field div.file {
+margin:0 0 0 200px;
+}
 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
 margin:0 0 0 0px;
 }
@@ -883,6 +948,17 @@
 padding:7px 7px 6px;
 }
 
+#content div.box div.form div.fields div.field div.file input {
+    background: none repeat scroll 0 0 #FFFFFF;
+    border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
+    border-style: solid;
+    border-width: 1px;
+    color: #000000;
+    font-family: Lucida Grande,Verdana,Lucida Sans Regular,Lucida Sans Unicode,Arial,sans-serif;
+    font-size: 11px;
+    margin: 0;
+    padding: 7px 7px 6px;
+}
 
 
 #content div.box div.form div.fields div.field div.input input.small {
@@ -981,55 +1057,13 @@
 padding:0 0 0 8px;
 }
 
-div.form div.fields div.field div.highlight .ui-button {
-background:#4e85bb url("../images/button_highlight.png") repeat-x;
-border-top:1px solid #5c91a4;
-border-left:1px solid #2a6f89;
-border-right:1px solid #2b7089;
-border-bottom:1px solid #1a6480;
-color:#FFF;
-margin:0;
-padding:6px 12px;
-}
-
-div.form div.fields div.field div.highlight .ui-state-hover {
-background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
-border-top:1px solid #78acbf;
-border-left:1px solid #34819e;
-border-right:1px solid #35829f;
-border-bottom:1px solid #257897;
-color:#FFF;
-margin:0;
-padding:6px 12px;
-}
-
-#content div.box div.form div.fields div.buttons div.highlight input.ui-button {
-background:#4e85bb url("../images/button_highlight.png") repeat-x;
-border-top:1px solid #5c91a4;
-border-left:1px solid #2a6f89;
-border-right:1px solid #2b7089;
-border-bottom:1px solid #1a6480;
-color:#fff;
-margin:0;
-padding:6px 12px;
-}
-
-#content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
-background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
-border-top:1px solid #78acbf;
-border-left:1px solid #34819e;
-border-right:1px solid #35829f;
-border-bottom:1px solid #257897;
-color:#fff;
-margin:0;
-padding:6px 12px;
-}
 
 #content div.box table {
 width:100%;
 border-collapse:collapse;
 margin:0;
 padding:0;
+border: 1px solid #eee;
 }
 
 #content div.box table th {
@@ -1260,6 +1294,23 @@
 padding:0 3px 2px;
 }
 
+#summary{
+
+}
+
+#summary .desc{
+white-space: pre;
+width: 100%;
+}
+
+#summary .repo_name{
+font-size: 1.6em;
+font-weight: bold;
+vertical-align: baseline;
+clear:right
+}
+
+
 #footer {
 clear:both;
 overflow:hidden;
@@ -1271,7 +1322,11 @@
 
 #footer div#footer-inner {
 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
-border-top:2px solid #FFFFFF;
+box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
+-webkit-border-radius: 4px 4px 4px 4px;
+-khtml-border-radius: 4px 4px 4px 4px; 
+-moz-border-radius: 4px 4px 4px 4px;
+border-radius: 4px 4px 4px 4px;
 }
 
 #footer div#footer-inner p {
@@ -1344,6 +1399,83 @@
 padding:0 0 2px;
 }
 
+#quick_login{
+top: 31px;
+background-color: rgb(0, 51, 103);
+z-index: 999; 
+height: 150px;
+position: absolute;
+margin-left: -16px;
+width: 281px;
+-webkit-border-radius: 0px 0px 4px 4px;
+-khtml-border-radius: 0px 0px 4px 4px; 
+-moz-border-radius: 0px 0px 4px 4px;
+border-radius: 0px 0px 4px 4px;
+
+box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
+}
+
+#quick_login .password_forgoten{
+padding-right:10px;
+padding-top:0px;
+float:left;
+}
+#quick_login .password_forgoten a{
+	font-size: 10px
+}
+
+#quick_login .register{
+padding-right:10px;
+padding-top:5px;
+float:left;
+}
+
+#quick_login .register a{
+	font-size: 10px
+}
+#quick_login div.form div.fields{
+padding-top: 2px;
+padding-left:10px;
+}
+
+#quick_login div.form div.fields div.field{
+ padding: 5px;
+}
+
+#quick_login div.form div.fields div.field div.label label{
+color:#fff;
+padding-bottom: 3px;
+}
+
+#quick_login div.form div.fields div.field div.input input {
+width:236px;
+background:#FFF;
+border-top:1px solid #b3b3b3;
+border-left:1px solid #b3b3b3;
+border-right:1px solid #eaeaea;
+border-bottom:1px solid #eaeaea;
+color:#000;
+font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
+font-size:11px;
+margin:0;
+padding:5px 7px 4px;
+}
+
+#quick_login div.form div.fields div.buttons {
+clear:both;
+overflow:hidden;
+text-align:right;
+margin:0;
+padding:10px 14px 3px 5px;
+}
+
+#quick_login div.form div.links {
+clear:both;
+overflow:hidden;
+margin:10px 0 0;
+padding:0 0 2px;
+}
+
 #register div.title {
 clear:both;
 overflow:hidden;
@@ -1392,13 +1524,6 @@
 padding:10px 0 0 150px;
 }
 
-#register div.form div.fields div.buttons div.highlight input.ui-button {
-background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
-color:#FFF;
-border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
-border-style:solid;
-border-width:1px;
-}
 
 #register div.form div.activation_msg {
 padding-top:4px;
@@ -1546,6 +1671,24 @@
 font-weight: bold;
 }
 
+.cs_files .node{
+float: left;
+}
+.cs_files .changes{
+float: right;
+}
+.cs_files .changes .added{
+background-color: #BBFFBB;
+float: left;
+text-align: center;
+font-size: 90%; 
+}
+.cs_files .changes .deleted{
+background-color: #FF8888;
+float: left;
+text-align: center;
+font-size: 90%;
+}
 .cs_files .cs_added {
 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
 height:16px;
@@ -1575,15 +1718,15 @@
 }
 
 #graph_nodes {
-width:160px;
-float:left;
-margin-left:-50px;
-margin-top:5px;
+float: left;
+margin-right: -6px;
+margin-top: -4px;
 }
 
 #graph_content {
 width:800px;
 float:left;
+
 }
 
 #graph_content .container_header {
@@ -1597,7 +1740,7 @@
 border-bottom:1px solid #CCC;
 border-left:1px solid #CCC;
 border-right:1px solid #CCC;
-min-height:80px;
+min-height:70px;
 overflow:hidden;
 font-size:1.2em;
 }
@@ -1617,6 +1760,17 @@
 vertical-align: text-top;    
 }
 
+#graph_content .container .left .author{
+    height: 22px;
+}
+#graph_content .container .left .author .user{
+color: #444444;
+float: left;
+font-size: 12px;
+margin-left: -4px;
+margin-top: 4px;
+}
+
 #graph_content .container .left .message {
 font-size:100%;
 padding-top:3px;
@@ -1627,6 +1781,16 @@
 clear:both;
 }
 
+.right .changes .changed_total{
+border:1px solid #DDD;
+display:block;
+float:right;
+text-align:center;
+min-width:45px;
+cursor: pointer;
+background:#FD8;
+font-weight: bold;
+}
 .right .changes .added,.changed,.removed {
 border:1px solid #DDD;
 display:block;
@@ -1693,7 +1857,7 @@
 
 div.browserblock .browser-header {
 background:#FFF;
-padding:10px 0px 35px 0px;
+padding:10px 0px 15px 0px;
 width: 100%;
 }
 div.browserblock .browser-nav {
@@ -1701,19 +1865,53 @@
 }
 
 div.browserblock .browser-branch {
-padding:10px 0 0 0;
 float:left;
 }
+
 div.browserblock .browser-branch label {
 color:#4A4A4A;
 vertical-align:text-top;
 }
 
 div.browserblock .browser-header span {
-margin-left:25px;
+margin-left:5px;
 font-weight:700;
 }
 
+div.browserblock .browser-search{
+	clear:both;
+	padding:8px 8px 0px 5px;
+	height: 20px;
+}
+div.browserblock #node_filter_box {
+}
+
+div.browserblock .search_activate{
+    float: left
+}
+
+div.browserblock .add_node{
+    float: left;
+    padding-left: 5px;
+}
+
+div.browserblock .search_activate #filter_activate,div.browserblock .add_node a{
+	vertical-align: sub;
+	border: 1px solid;
+	padding:2px;
+	-webkit-border-radius: 4px 4px 4px 4px;
+	-khtml-border-radius: 4px 4px 4px 4px; 
+	-moz-border-radius: 4px 4px 4px 4px;
+	border-radius: 4px 4px 4px 4px;
+	background: url("../images/button.png") repeat-x scroll 0 0 #E5E3E3;
+	border-color: #DDDDDD #DDDDDD #C6C6C6 #C6C6C6;
+	color: #515151;
+}
+
+div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover{
+    text-decoration: none !important;    
+}
+
 div.browserblock .browser-body {
 background:#EEE;
 border-top:1px solid #CCC;
@@ -1799,26 +1997,30 @@
 padding-left:4px;
 }
 
-.info_box * {
-background:url("../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
-color:#4A4A4A;
-font-weight:700;
-height:1%;
-display:inline;
-border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
-border-style:solid;
-border-width:1px;
-padding:4px 6px;
-}
-
 .info_box span {
 margin-left:3px;
 margin-right:3px;
 }
 
-.info_box input#at_rev {
-text-align:center;
-padding:5px 3px 3px 2px;
+.info_box .rev {
+color: #003367;
+font-size: 1.6em;
+font-weight: bold;
+vertical-align: sub;
+}
+
+
+.info_box input#at_rev,.info_box input#size {
+background:#FFF;
+border-top:1px solid #b3b3b3;
+border-left:1px solid #b3b3b3;
+border-right:1px solid #eaeaea;
+border-bottom:1px solid #eaeaea;
+color:#000;
+font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
+font-size:12px;
+margin:0;
+padding:1px 5px 1px;
 }
 
 .info_box input#view {
@@ -1843,11 +2045,12 @@
 width:auto;
 opacity:1px;
 padding:8px;
-white-space: pre;
+white-space: pre-wrap;
 -webkit-border-radius: 8px 8px 8px 8px;
 -khtml-border-radius: 8px 8px 8px 8px; 
 -moz-border-radius: 8px 8px 8px 8px;
 border-radius: 8px 8px 8px 8px;
+box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 }
 
 .ac {
@@ -2134,6 +2337,19 @@
 float:left;
 margin-right:0.7em;
 padding:2px 2px 0;
+
+-webkit-border-radius: 6px;
+-khtml-border-radius: 6px; 
+-moz-border-radius: 6px;
+border-radius: 6px;
+
+}
+
+div.gravatar img {
+-webkit-border-radius: 4px;
+-khtml-border-radius: 4px; 
+-moz-border-radius: 4px;
+border-radius: 4px;	
 }
 
 #header,#content,#footer {
@@ -2141,7 +2357,6 @@
 }
 
 #content {
-min-height:100%;
 clear:both;
 overflow:hidden;
 padding:14px 10px;
@@ -2156,37 +2371,51 @@
 border:1px solid #316293;
 }
 
-#content div.box div.title div.search div.button input.ui-button {
-background:#4e85bb url("../images/button_highlight.png") repeat-x;
-border:1px solid #316293;
-border-left:none;
-color:#FFF;
-}
-
-#content div.box div.title div.search div.button input.ui-state-hover {
-background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
-border:1px solid #316293;
-border-left:none;
-color:#FFF;
-}
-
-#content div.box div.form div.fields div.field div.highlight .ui-button {
+
+input.ui-button-small {
+background:#e5e3e3 url("../images/button.png") repeat-x !important;
+border-top:1px solid #DDD !important;
+border-left:1px solid #c6c6c6 !important;
+border-right:1px solid #DDD !important;
+border-bottom:1px solid #c6c6c6 !important;
+color:#515151 !important;
+outline:none !important;
+margin:0 !important;
+-webkit-border-radius: 4px 4px 4px 4px !important;
+-khtml-border-radius: 4px 4px 4px 4px !important; 
+-moz-border-radius: 4px 4px 4px 4px !important;
+border-radius: 4px 4px 4px 4px !important;
+box-shadow: 0 1px 0 #ececec !important;
+cursor: pointer !important;
+}
+
+input.ui-button-small:hover {
+background:#b4b4b4 url("../images/button_selected.png") repeat-x !important;
+border-top:1px solid #ccc !important;
+border-left:1px solid #bebebe !important;
+border-right:1px solid #b1b1b1 !important;
+border-bottom:1px solid #afafaf !important;	
+}
+
+input.ui-button-small-blue {
 background:#4e85bb url("../images/button_highlight.png") repeat-x;
 border-top:1px solid #5c91a4;
 border-left:1px solid #2a6f89;
 border-right:1px solid #2b7089;
 border-bottom:1px solid #1a6480;
 color:#fff;
-}
-
-#content div.box div.form div.fields div.field div.highlight .ui-state-hover {
-background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
-border-top:1px solid #78acbf;
-border-left:1px solid #34819e;
-border-right:1px solid #35829f;
-border-bottom:1px solid #257897;
-color:#fff;
-}
+-webkit-border-radius: 4px 4px 4px 4px;
+-khtml-border-radius: 4px 4px 4px 4px; 
+-moz-border-radius: 4px 4px 4px 4px;
+border-radius: 4px 4px 4px 4px;
+box-shadow: 0 1px 0 #ececec;
+cursor: pointer;
+}
+
+input.ui-button-small-blue:hover {
+	
+}
+
 
 ins,div.options a:hover {
 text-decoration:none;
@@ -2206,6 +2435,7 @@
 padding:0;
 }
 
+
 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
 float:left;
 }
@@ -2319,7 +2549,7 @@
 margin:0;
 }
 
-div.form div.fields div.field div.button .ui-button,#content div.box div.form div.fields div.buttons input.ui-button {
+input.ui-button {
 background:#e5e3e3 url("../images/button.png") repeat-x;
 border-top:1px solid #DDD;
 border-left:1px solid #c6c6c6;
@@ -2329,18 +2559,20 @@
 outline:none;
 margin:0;
 padding:6px 12px;
-}
-
-div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
+-webkit-border-radius: 4px 4px 4px 4px;
+-khtml-border-radius: 4px 4px 4px 4px; 
+-moz-border-radius: 4px 4px 4px 4px;
+border-radius: 4px 4px 4px 4px;
+box-shadow: 0 1px 0 #ececec;
+cursor: pointer;
+}
+
+input.ui-button:hover {
 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
 border-top:1px solid #ccc;
 border-left:1px solid #bebebe;
 border-right:1px solid #b1b1b1;
 border-bottom:1px solid #afafaf;
-color:#515151;
-outline:none;
-margin:0;
-padding:6px 12px;
 }
 
 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
@@ -2367,16 +2599,6 @@
 padding:0;
 }
 
-#content div.box div.action div.button input.ui-button,#login div.form div.fields div.buttons input.ui-button,#register div.form div.fields div.buttons input.ui-button {
-background:#e5e3e3 url("../images/button.png") repeat-x;
-border-top:1px solid #DDD;
-border-left:1px solid #c6c6c6;
-border-right:1px solid #DDD;
-border-bottom:1px solid #c6c6c6;
-color:#515151;
-margin:0;
-padding:6px 12px;
-}
 
 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
@@ -2520,3 +2742,8 @@
 padding-left:3px;
 }
 
+#node_filter{
+border:0px solid #545454;
+color:#AAAAAA;
+padding-left:3px;
+}
Binary file rhodecode/public/images/horizontal-indicator.png has changed
Binary file rhodecode/public/images/quick_l.png has changed
Binary file rhodecode/public/images/quick_l_selected.png has changed
Binary file rhodecode/public/images/quick_r.png has changed
Binary file rhodecode/public/images/quick_r_selected.png has changed
Binary file rhodecode/public/images/user14.png has changed
Binary file rhodecode/public/images/user16.png has changed
Binary file rhodecode/public/images/user20.png has changed
Binary file rhodecode/public/images/user24.png has changed
Binary file rhodecode/public/images/user30.png has changed
Binary file rhodecode/public/images/vertical-indicator.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/public/js/codemirror.js	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,1915 @@
+// All functions that need access to the editor's state live inside
+// the CodeMirror function. Below that, at the bottom of the file,
+// some utilities are defined.
+
+// CodeMirror is the only global var we claim
+var CodeMirror = (function() {
+  // This is the function that produces an editor instance. It's
+  // closure is used to store the editor state.
+  function CodeMirror(place, givenOptions) {
+    // Determine effective options based on given values and defaults.
+    var options = {}, defaults = CodeMirror.defaults;
+    for (var opt in defaults)
+      if (defaults.hasOwnProperty(opt))
+        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
+
+    // The element in which the editor lives. Takes care of scrolling
+    // (if enabled).
+    var wrapper = document.createElement("div");
+    wrapper.className = "CodeMirror";
+    // This mess creates the base DOM structure for the editor.
+    wrapper.innerHTML =
+      '<div style="position: relative">' + // Set to the height of the text, causes scrolling
+        '<pre style="position: relative; height: 0; visibility: hidden; overflow: hidden;">' + // To measure line/char size
+           '<span>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span></pre>' +
+        '<div style="position: relative">' + // Moved around its parent to cover visible view
+          '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
+          '<div style="overflow: hidden; position: absolute; width: 0; left: 0">' + // Wraps and hides input textarea
+            '<textarea style="height: 1px; position: absolute; width: 1px;" wrap="off"></textarea></div>' +
+          // Provides positioning relative to (visible) text origin
+          '<div class="CodeMirror-lines"><div style="position: relative">' +
+            '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
+            '<div></div></div></div></div></div>'; // This DIV contains the actual code
+    if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
+    // I've never seen more elegant code in my life.
+    var code = wrapper.firstChild, measure = code.firstChild, mover = measure.nextSibling,
+        gutter = mover.firstChild, gutterText = gutter.firstChild,
+        inputDiv = gutter.nextSibling, input = inputDiv.firstChild,
+        lineSpace = inputDiv.nextSibling.firstChild, cursor = lineSpace.firstChild, lineDiv = cursor.nextSibling;
+    if (options.tabindex != null) input.tabindex = options.tabindex;
+    if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
+
+    // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
+    var poll = new Delayed(), highlight = new Delayed(), blinker;
+
+    // mode holds a mode API object. lines an array of Line objects
+    // (see Line constructor), work an array of lines that should be
+    // parsed, and history the undo history (instance of History
+    // constructor).
+    var mode, lines = [new Line("")], work, history = new History(), focused;
+    loadMode();
+    // The selection. These are always maintained to point at valid
+    // positions. Inverted is used to remember that the user is
+    // selecting bottom-to-top.
+    var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
+    // Selection-related flags. shiftSelecting obviously tracks
+    // whether the user is holding shift. reducedSelection is a hack
+    // to get around the fact that we can't create inverted
+    // selections. See below.
+    var shiftSelecting, reducedSelection;
+    // Variables used by startOperation/endOperation to track what
+    // happened during the operation.
+    var updateInput, changes, textChanged, selectionChanged, leaveInputAlone;
+    // Current visible range (may be bigger than the view window).
+    var showingFrom = 0, showingTo = 0, lastHeight = 0, curKeyId = null;
+    // editing will hold an object describing the things we put in the
+    // textarea, to help figure out whether something changed.
+    // bracketHighlighted is used to remember that a backet has been
+    // marked.
+    var editing, bracketHighlighted;
+
+    // Initialize the content. Somewhat hacky (delayed prepareInput)
+    // to work around browser issues.
+    operation(function(){setValue(options.value || ""); updateInput = false;})();
+    setTimeout(prepareInput, 20);
+
+    // Register our event handlers.
+    connect(wrapper, "mousedown", operation(onMouseDown));
+    // Gecko browsers fire contextmenu *after* opening the menu, at
+    // which point we can't mess with it anymore. Context menu is
+    // handled in onMouseDown for Gecko.
+    if (!gecko) connect(wrapper, "contextmenu", operation(onContextMenu));
+    connect(code, "dblclick", operation(onDblClick));
+    connect(wrapper, "scroll", function() {updateDisplay([]); if (options.onScroll) options.onScroll(instance);});
+    connect(window, "resize", function() {updateDisplay(true);});
+    connect(input, "keyup", operation(onKeyUp));
+    connect(input, "keydown", operation(onKeyDown));
+    connect(input, "keypress", operation(onKeyPress));
+    connect(input, "focus", onFocus);
+    connect(input, "blur", onBlur);
+
+    connect(wrapper, "dragenter", function(e){e.stop();});
+    connect(wrapper, "dragover", function(e){e.stop();});
+    connect(wrapper, "drop", operation(onDrop));
+    connect(wrapper, "paste", function(){input.focus(); fastPoll();});
+    connect(input, "paste", function(){fastPoll();});
+    connect(input, "cut", function(){fastPoll();});
+
+    if (document.activeElement == input) onFocus();
+    else onBlur();
+
+    function isLine(l) {return l >= 0 && l < lines.length;}
+    // The instance object that we'll return. Mostly calls out to
+    // local functions in the CodeMirror function. Some do some extra
+    // range checking and/or clipping. operation is used to wrap the
+    // call so that changes it makes are tracked, and the display is
+    // updated afterwards.
+    var instance = {
+      getValue: getValue,
+      setValue: operation(setValue),
+      getSelection: getSelection,
+      replaceSelection: operation(replaceSelection),
+      focus: function(){input.focus(); onFocus(); fastPoll();},
+      setOption: function(option, value) {
+        options[option] = value;
+        if (option == "lineNumbers" || option == "gutter") gutterChanged();
+        else if (option == "mode" || option == "indentUnit") loadMode();
+      },
+      getOption: function(option) {return options[option];},
+      undo: operation(undo),
+      redo: operation(redo),
+      indentLine: operation(function(n) {if (isLine(n)) indentLine(n, "smart");}),
+      historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
+      matchBrackets: operation(function(){matchBrackets(true);}),
+      getTokenAt: function(pos) {
+        pos = clipPos(pos);
+        return lines[pos.line].getTokenAt(mode, getStateBefore(pos.line), pos.ch);
+      },
+      cursorCoords: function(start){
+        if (start == null) start = sel.inverted;
+        return pageCoords(start ? sel.from : sel.to);
+      },
+      charCoords: function(pos){return pageCoords(clipPos(pos));},
+      coordsChar: function(coords) {
+        var off = eltOffset(lineSpace);
+        var line = Math.min(showingTo - 1, showingFrom + Math.floor(coords.y / lineHeight()));
+        return clipPos({line: line, ch: charFromX(clipLine(line), coords.x)});
+      },
+      getSearchCursor: function(query, pos, caseFold) {return new SearchCursor(query, pos, caseFold);},
+      markText: operation(function(a, b, c){return operation(markText(a, b, c));}),
+      setMarker: addGutterMarker,
+      clearMarker: removeGutterMarker,
+      setLineClass: operation(setLineClass),
+      lineInfo: lineInfo,
+      addWidget: function(pos, node, scroll) {
+        var pos = localCoords(clipPos(pos), true);
+        node.style.top = (showingFrom * lineHeight() + pos.yBot + paddingTop()) + "px";
+        node.style.left = (pos.x + paddingLeft()) + "px";
+        code.appendChild(node);
+        if (scroll)
+          scrollIntoView(pos.x, pos.yBot, pos.x + node.offsetWidth, pos.yBot + node.offsetHeight);
+      },
+
+      lineCount: function() {return lines.length;},
+      getCursor: function(start) {
+        if (start == null) start = sel.inverted;
+        return copyPos(start ? sel.from : sel.to);
+      },
+      somethingSelected: function() {return !posEq(sel.from, sel.to);},
+      setCursor: operation(function(line, ch) {
+        if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch);
+        else setCursor(line, ch);
+      }),
+      setSelection: operation(function(from, to) {setSelection(clipPos(from), clipPos(to || from));}),
+      getLine: function(line) {if (isLine(line)) return lines[line].text;},
+      setLine: operation(function(line, text) {
+        if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: lines[line].text.length});
+      }),
+      removeLine: operation(function(line) {
+        if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
+      }),
+      replaceRange: operation(replaceRange),
+      getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
+
+      operation: function(f){return operation(f)();},
+      refresh: function(){updateDisplay(true);},
+      getInputField: function(){return input;},
+      getWrapperElement: function(){return wrapper;}
+    };
+
+    function setValue(code) {
+      history = null;
+      var top = {line: 0, ch: 0};
+      updateLines(top, {line: lines.length - 1, ch: lines[lines.length-1].text.length},
+                  splitLines(code), top, top);
+      history = new History();
+    }
+    function getValue(code) {
+      var text = [];
+      for (var i = 0, l = lines.length; i < l; ++i)
+        text.push(lines[i].text);
+      return text.join("\n");
+    }
+
+    function onMouseDown(e) {
+      // First, see if this is a click in the gutter
+      for (var n = e.target(); n != wrapper; n = n.parentNode)
+        if (n.parentNode == gutterText) {
+          if (options.onGutterClick)
+            options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom);
+          return e.stop();
+        }
+
+      if (gecko && e.button() == 3) onContextMenu(e);
+      if (e.button() != 1) return;
+      // For button 1, if it was clicked inside the editor
+      // (posFromMouse returning non-null), we have to adjust the
+      // selection.
+      var start = posFromMouse(e), last = start, going;
+      if (!start) {if (e.target() == wrapper) e.stop(); return;}
+      setCursor(start.line, start.ch, false);
+
+      if (!focused) onFocus();
+      e.stop();
+      // And then we have to see if it's a drag event, in which case
+      // the dragged-over text must be selected.
+      function end() {
+        input.focus();
+        updateInput = true;
+        move(); up();
+      }
+      function extend(e) {
+        var cur = posFromMouse(e, true);
+        if (cur && !posEq(cur, last)) {
+          if (!focused) onFocus();
+          last = cur;
+          setSelection(start, cur);
+          updateInput = false;
+          var visible = visibleLines();
+          if (cur.line >= visible.to || cur.line < visible.from)
+            going = setTimeout(operation(function(){extend(e);}), 150);
+        }
+      }
+
+      var move = connect(document, "mousemove", operation(function(e) {
+        clearTimeout(going);
+        e.stop();
+        extend(e);
+      }), true);
+      var up = connect(document, "mouseup", operation(function(e) {
+        clearTimeout(going);
+        var cur = posFromMouse(e);
+        if (cur) setSelection(start, cur);
+        e.stop();
+        end();
+      }), true);
+    }
+    function onDblClick(e) {
+      var pos = posFromMouse(e);
+      if (!pos) return;
+      selectWordAt(pos);
+      e.stop();
+    }
+    function onDrop(e) {
+      var pos = posFromMouse(e, true), files = e.e.dataTransfer.files;
+      if (!pos || options.readOnly) return;
+      if (files && files.length && window.FileReader && window.File) {
+        var n = files.length, text = Array(n), read = 0;
+        for (var i = 0; i < n; ++i) loadFile(files[i], i);
+        function loadFile(file, i) {
+          var reader = new FileReader;
+          reader.onload = function() {
+            text[i] = reader.result;
+            if (++read == n) replaceRange(text.join(""), clipPos(pos), clipPos(pos));
+          };
+          reader.readAsText(file);
+        }
+      }
+      else {
+        try {
+          var text = e.e.dataTransfer.getData("Text");
+          if (text) replaceRange(text, pos, pos);
+        }
+        catch(e){}
+      }
+    }
+    function onKeyDown(e) {
+      if (!focused) onFocus();
+
+      var code = e.e.keyCode;
+      // Tries to detect ctrl on non-mac, cmd on mac.
+      var mod = (mac ? e.e.metaKey : e.e.ctrlKey) && !e.e.altKey, anyMod = e.e.ctrlKey || e.e.altKey || e.e.metaKey;
+      if (code == 16 || e.e.shiftKey) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
+      else shiftSelecting = null;
+      // First give onKeyEvent option a chance to handle this.
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
+
+      if (code == 33 || code == 34) {scrollPage(code == 34); return e.stop();} // page up/down
+      if (mod && (code == 36 || code == 35)) {scrollEnd(code == 36); return e.stop();} // ctrl-home/end
+      if (mod && code == 65) {selectAll(); return e.stop();} // ctrl-a
+      if (!options.readOnly) {
+        if (!anyMod && code == 13) {return;} // enter
+        if (!anyMod && code == 9 && handleTab(e.e.shiftKey)) return e.stop(); // tab
+        if (mod && code == 90) {undo(); return e.stop();} // ctrl-z
+        if (mod && ((e.e.shiftKey && code == 90) || code == 89)) {redo(); return e.stop();} // ctrl-shift-z, ctrl-y
+      }
+
+      // Key id to use in the movementKeys map. We also pass it to
+      // fastPoll in order to 'self learn'. We need this because
+      // reducedSelection, the hack where we collapse the selection to
+      // its start when it is inverted and a movement key is pressed
+      // (and later restore it again), shouldn't be used for
+      // non-movement keys.
+      curKeyId = (mod ? "c" : "") + code;
+      if (sel.inverted && movementKeys.hasOwnProperty(curKeyId)) {
+        var range = selRange(input);
+        if (range) {
+          reducedSelection = {anchor: range.start};
+          setSelRange(input, range.start, range.start);
+        }
+      }
+      fastPoll(curKeyId);
+    }
+    function onKeyUp(e) {
+      if (reducedSelection) {
+        reducedSelection = null;
+        updateInput = true;
+      }
+      if (e.e.keyCode == 16) shiftSelecting = null;
+    }
+    function onKeyPress(e) {
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
+      if (options.electricChars && mode.electricChars) {
+        var ch = String.fromCharCode(e.e.charCode == null ? e.e.keyCode : e.e.charCode);
+        if (mode.electricChars.indexOf(ch) > -1)
+          setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 50);
+      }
+      var code = e.e.keyCode;
+      // Re-stop tab and enter. Necessary on some browsers.
+      if (code == 13) {handleEnter(); e.stop();}
+      else if (code == 9 && options.tabMode != "default") e.stop();
+      else fastPoll(curKeyId);
+    }
+
+    function onFocus() {
+      if (!focused && options.onFocus) options.onFocus(instance);
+      focused = true;
+      slowPoll();
+      if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
+        wrapper.className += " CodeMirror-focused";
+      restartBlink();
+    }
+    function onBlur() {
+      if (focused && options.onBlur) options.onBlur(instance);
+      clearInterval(blinker);
+      shiftSelecting = null;
+      focused = false;
+      wrapper.className = wrapper.className.replace(" CodeMirror-focused", "");
+    }
+
+    // Replace the range from from to to by the strings in newText.
+    // Afterwards, set the selection to selFrom, selTo.
+    function updateLines(from, to, newText, selFrom, selTo) {
+      if (history) {
+        var old = [];
+        for (var i = from.line, e = to.line + 1; i < e; ++i) old.push(lines[i].text);
+        history.addChange(from.line, newText.length, old);
+        while (history.done.length > options.undoDepth) history.done.shift();
+      }
+      updateLinesNoUndo(from, to, newText, selFrom, selTo);
+    }
+    function unredoHelper(from, to) {
+      var change = from.pop();
+      if (change) {
+        var replaced = [], end = change.start + change.added;
+        for (var i = change.start; i < end; ++i) replaced.push(lines[i].text);
+        to.push({start: change.start, added: change.old.length, old: replaced});
+        var pos = clipPos({line: change.start + change.old.length - 1,
+                           ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
+        updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: lines[end-1].text.length}, change.old, pos, pos);
+      }
+    }
+    function undo() {unredoHelper(history.done, history.undone);}
+    function redo() {unredoHelper(history.undone, history.done);}
+
+    function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
+      var nlines = to.line - from.line, firstLine = lines[from.line], lastLine = lines[to.line];
+      // First adjust the line structure, taking some care to leave highlighting intact.
+      if (firstLine == lastLine) {
+        if (newText.length == 1)
+          firstLine.replace(from.ch, to.ch, newText[0]);
+        else {
+          lastLine = firstLine.split(to.ch, newText[newText.length-1]);
+          var spliceargs = [from.line + 1, nlines];
+          firstLine.replace(from.ch, firstLine.text.length, newText[0]);
+          for (var i = 1, e = newText.length - 1; i < e; ++i) spliceargs.push(new Line(newText[i]));
+          spliceargs.push(lastLine);
+          lines.splice.apply(lines, spliceargs);
+        }
+      }
+      else if (newText.length == 1) {
+        firstLine.replace(from.ch, firstLine.text.length, newText[0] + lastLine.text.slice(to.ch));
+        lines.splice(from.line + 1, nlines);
+      }
+      else {
+        var spliceargs = [from.line + 1, nlines - 1];
+        firstLine.replace(from.ch, firstLine.text.length, newText[0]);
+        lastLine.replace(0, to.ch, newText[newText.length-1]);
+        for (var i = 1, e = newText.length - 1; i < e; ++i) spliceargs.push(new Line(newText[i]));
+        lines.splice.apply(lines, spliceargs);
+      }
+
+      // Add these lines to the work array, so that they will be
+      // highlighted. Adjust work lines if lines were added/removed.
+      var newWork = [], lendiff = newText.length - nlines - 1;
+      for (var i = 0, l = work.length; i < l; ++i) {
+        var task = work[i];
+        if (task < from.line) newWork.push(task);
+        else if (task > to.line) newWork.push(task + lendiff);
+      }
+      if (newText.length) newWork.push(from.line);
+      work = newWork;
+      startWorker(100);
+      // Remember that these lines changed, for updating the display
+      changes.push({from: from.line, to: to.line + 1, diff: lendiff});
+      textChanged = true;
+
+      // Update the selection
+      function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
+      setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));
+
+      // Make sure the scroll-size div has the correct height.
+      code.style.height = (lines.length * lineHeight() + 2 * paddingTop()) + "px";
+    }
+
+    function replaceRange(code, from, to) {
+      from = clipPos(from);
+      if (!to) to = from; else to = clipPos(to);
+      code = splitLines(code);
+      function adjustPos(pos) {
+        if (posLess(pos, from)) return pos;
+        if (!posLess(to, pos)) return end;
+        var line = pos.line + code.length - (to.line - from.line) - 1;
+        var ch = pos.ch;
+        if (pos.line == to.line)
+          ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0));
+        return {line: line, ch: ch};
+      }
+      var end;
+      replaceRange1(code, from, to, function(end1) {
+        end = end1;
+        return {from: adjustPos(sel.from), to: adjustPos(sel.to)};
+      });
+      return end;
+    }
+    function replaceSelection(code, collapse) {
+      replaceRange1(splitLines(code), sel.from, sel.to, function(end) {
+        if (collapse == "end") return {from: end, to: end};
+        else if (collapse == "start") return {from: sel.from, to: sel.from};
+        else return {from: sel.from, to: end};
+      });
+    }
+    function replaceRange1(code, from, to, computeSel) {
+      var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length;
+      var newSel = computeSel({line: from.line + code.length - 1, ch: endch});
+      updateLines(from, to, code, newSel.from, newSel.to);
+    }
+
+    function getRange(from, to) {
+      var l1 = from.line, l2 = to.line;
+      if (l1 == l2) return lines[l1].text.slice(from.ch, to.ch);
+      var code = [lines[l1].text.slice(from.ch)];
+      for (var i = l1 + 1; i < l2; ++i) code.push(lines[i].text);
+      code.push(lines[l2].text.slice(0, to.ch));
+      return code.join("\n");
+    }
+    function getSelection() {
+      return getRange(sel.from, sel.to);
+    }
+
+    var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
+    function slowPoll() {
+      if (pollingFast) return;
+      poll.set(2000, function() {
+        startOperation();
+        readInput();
+        if (focused) slowPoll();
+        endOperation();
+      });
+    }
+    function fastPoll(keyId) {
+      var missed = false;
+      pollingFast = true;
+      function p() {
+        startOperation();
+        var changed = readInput();
+        if (changed == "moved" && keyId) movementKeys[keyId] = true;
+        if (!changed && !missed) {missed = true; poll.set(80, p);}
+        else {pollingFast = false; slowPoll();}
+        endOperation();
+      }
+      poll.set(20, p);
+    }
+
+    // Inspects the textarea, compares its state (content, selection)
+    // to the data in the editing variable, and updates the editor
+    // content or cursor if something changed.
+    function readInput() {
+      var changed = false, text = input.value, sr = selRange(input);
+      if (!sr) return false;
+      var changed = editing.text != text, rs = reducedSelection;
+      var moved = changed || sr.start != editing.start || sr.end != (rs ? editing.start : editing.end);
+      if (reducedSelection && !moved && sel.from.line == 0 && sel.from.ch == 0)
+        reducedSelection = null;
+      else if (!moved) return false;
+      if (changed) {
+        shiftSelecting = reducedSelection = null;
+        if (options.readOnly) {updateInput = true; return "changed";}
+      }
+
+      // Compute selection start and end based on start/end offsets in textarea
+      function computeOffset(n, startLine) {
+        var pos = 0;
+        for (;;) {
+          var found = text.indexOf("\n", pos);
+          if (found == -1 || (text.charAt(found-1) == "\r" ? found - 1 : found) >= n)
+            return {line: startLine, ch: n - pos};
+          ++startLine;
+          pos = found + 1;
+        }
+      }
+      var from = computeOffset(sr.start, editing.from),
+          to = computeOffset(sr.end, editing.from);
+      // Here we have to take the reducedSelection hack into account,
+      // so that you can, for example, press shift-up at the start of
+      // your selection and have the right thing happen.
+      if (rs) {
+        from = sr.start == rs.anchor ? to : from;
+        to = shiftSelecting ? sel.to : sr.start == rs.anchor ? from : to;
+        if (!posLess(from, to)) {
+          reducedSelection = null;
+          sel.inverted = false;
+          var tmp = from; from = to; to = tmp;
+        }
+      }
+
+      // In some cases (cursor on same line as before), we don't have
+      // to update the textarea content at all.
+      if (from.line == to.line && from.line == sel.from.line && from.line == sel.to.line && !shiftSelecting)
+        updateInput = false;
+
+      // Magic mess to extract precise edited range from the changed
+      // string.
+      if (changed) {
+        var start = 0, end = text.length, len = Math.min(end, editing.text.length);
+        var c, line = editing.from, nl = -1;
+        while (start < len && (c = text.charAt(start)) == editing.text.charAt(start)) {
+          ++start;
+          if (c == "\n") {line++; nl = start;}
+        }
+        var ch = nl > -1 ? start - nl : start, endline = editing.to - 1, edend = editing.text.length;
+        for (;;) {
+          c = editing.text.charAt(edend);
+          if (c == "\n") endline--;
+          if (text.charAt(end) != c) {++end; ++edend; break;}
+          if (edend <= start || end <= start) break;
+          --end; --edend;
+        }
+        var nl = editing.text.lastIndexOf("\n", edend - 1), endch = nl == -1 ? edend : edend - nl - 1;
+        updateLines({line: line, ch: ch}, {line: endline, ch: endch}, splitLines(text.slice(start, end)), from, to);
+        if (line != endline || from.line != line) updateInput = true;
+      }
+      else setSelection(from, to);
+
+      editing.text = text; editing.start = sr.start; editing.end = sr.end;
+      return changed ? "changed" : moved ? "moved" : false;
+    }
+
+    // Set the textarea content and selection range to match the
+    // editor state.
+    function prepareInput() {
+      var text = [];
+      var from = Math.max(0, sel.from.line - 1), to = Math.min(lines.length, sel.to.line + 2);
+      for (var i = from; i < to; ++i) text.push(lines[i].text);
+      text = input.value = text.join(lineSep);
+      var startch = sel.from.ch, endch = sel.to.ch;
+      for (var i = from; i < sel.from.line; ++i)
+        startch += lineSep.length + lines[i].text.length;
+      for (var i = from; i < sel.to.line; ++i)
+        endch += lineSep.length + lines[i].text.length;
+      editing = {text: text, from: from, to: to, start: startch, end: endch};
+      setSelRange(input, startch, reducedSelection ? startch : endch);
+    }
+
+    function scrollCursorIntoView() {
+      var cursor = localCoords(sel.inverted ? sel.from : sel.to);
+      return scrollIntoView(cursor.x, cursor.y, cursor.x, cursor.yBot);
+    }
+    function scrollIntoView(x1, y1, x2, y2) {
+      var pl = paddingLeft(), pt = paddingTop();
+      y1 += pt; y2 += pt; x1 += pl; x2 += pl;
+      var screen = wrapper.clientHeight, screentop = wrapper.scrollTop, scrolled = false, result = true;
+      if (y1 < screentop) {wrapper.scrollTop = Math.max(0, y1 - 10); scrolled = true;}
+      else if (y2 > screentop + screen) {wrapper.scrollTop = y2 + 10 - screen; scrolled = true;}
+
+      var screenw = wrapper.clientWidth, screenleft = wrapper.scrollLeft;
+      if (x1 < screenleft) {wrapper.scrollLeft = Math.max(0, x1 - 10); scrolled = true;}
+      else if (x2 > screenw + screenleft) {
+        wrapper.scrollLeft = x2 + 10 - screenw;
+        scrolled = true;
+        if (x2 > code.clientWidth) result = false;
+      }
+      if (scrolled && options.onScroll) options.onScroll(instance);
+      return result;
+    }
+
+    function visibleLines() {
+      var lh = lineHeight(), top = wrapper.scrollTop - paddingTop();
+      return {from: Math.min(lines.length, Math.max(0, Math.floor(top / lh))),
+              to: Math.min(lines.length, Math.ceil((top + wrapper.clientHeight) / lh))};
+    }
+    // Uses a set of changes plus the current scroll position to
+    // determine which DOM updates have to be made, and makes the
+    // updates.
+    function updateDisplay(changes) {
+      if (!wrapper.clientWidth) {
+        showingFrom = showingTo = 0;
+        return;
+      }
+      // First create a range of theoretically intact lines, and punch
+      // holes in that using the change info.
+      var intact = changes === true ? [] : [{from: showingFrom, to: showingTo, domStart: 0}];
+      for (var i = 0, l = changes.length || 0; i < l; ++i) {
+        var change = changes[i], intact2 = [], diff = change.diff || 0;
+        for (var j = 0, l2 = intact.length; j < l2; ++j) {
+          var range = intact[j];
+          if (change.to <= range.from)
+            intact2.push({from: range.from + diff, to: range.to + diff, domStart: range.domStart});
+          else if (range.to <= change.from)
+            intact2.push(range);
+          else {
+            if (change.from > range.from)
+              intact2.push({from: range.from, to: change.from, domStart: range.domStart})
+            if (change.to < range.to)
+              intact2.push({from: change.to + diff, to: range.to + diff,
+                            domStart: range.domStart + (change.to - range.from)});
+          }
+        }
+        intact = intact2;
+      }
+
+      // Then, determine which lines we'd want to see, and which
+      // updates have to be made to get there.
+      var visible = visibleLines();
+      var from = Math.min(showingFrom, Math.max(visible.from - 3, 0)),
+          to = Math.min(lines.length, Math.max(showingTo, visible.to + 3)),
+          updates = [], domPos = 0, domEnd = showingTo - showingFrom, pos = from, changedLines = 0;
+
+      for (var i = 0, l = intact.length; i < l; ++i) {
+        var range = intact[i];
+        if (range.to <= from) continue;
+        if (range.from >= to) break;
+        if (range.domStart > domPos || range.from > pos) {
+          updates.push({from: pos, to: range.from, domSize: range.domStart - domPos, domStart: domPos});
+          changedLines += range.from - pos;
+        }
+        pos = range.to;
+        domPos = range.domStart + (range.to - range.from);
+      }
+      if (domPos != domEnd || pos != to) {
+        changedLines += Math.abs(to - pos);
+        updates.push({from: pos, to: to, domSize: domEnd - domPos, domStart: domPos});
+      }
+
+      if (!updates.length) return;
+      lineDiv.style.display = "none";
+      // If more than 30% of the screen needs update, just do a full
+      // redraw (which is quicker than patching)
+      if (changedLines > (visible.to - visible.from) * .3)
+        refreshDisplay(from = Math.max(visible.from - 10, 0), to = Math.min(visible.to + 7, lines.length));
+      // Otherwise, only update the stuff that needs updating.
+      else
+        patchDisplay(updates);
+      lineDiv.style.display = "";
+
+      // Position the mover div to align with the lines it's supposed
+      // to be showing (which will cover the visible display)
+      var different = from != showingFrom || to != showingTo || lastHeight != wrapper.clientHeight;
+      showingFrom = from; showingTo = to;
+      mover.style.top = (from * lineHeight()) + "px";
+      if (different) {
+        lastHeight = wrapper.clientHeight;
+        code.style.height = (lines.length * lineHeight() + 2 * paddingTop()) + "px";
+        updateGutter();
+      }
+
+      // Since this is all rather error prone, it is honoured with the
+      // only assertion in the whole file.
+      if (lineDiv.childNodes.length != showingTo - showingFrom)
+        throw new Error("BAD PATCH! " + JSON.stringify(updates) + " size=" + (showingTo - showingFrom) +
+                        " nodes=" + lineDiv.childNodes.length);
+      updateCursor();
+    }
+
+    function refreshDisplay(from, to) {
+      var html = [], start = {line: from, ch: 0}, inSel = posLess(sel.from, start) && !posLess(sel.to, start);
+      for (var i = from; i < to; ++i) {
+        var ch1 = null, ch2 = null;
+        if (inSel) {
+          ch1 = 0;
+          if (sel.to.line == i) {inSel = false; ch2 = sel.to.ch;}
+        }
+        else if (sel.from.line == i) {
+          if (sel.to.line == i) {ch1 = sel.from.ch; ch2 = sel.to.ch;}
+          else {inSel = true; ch1 = sel.from.ch;}
+        }
+        html.push(lines[i].getHTML(ch1, ch2, true));
+      }
+      lineDiv.innerHTML = html.join("");
+    }
+    function patchDisplay(updates) {
+      // Slightly different algorithm for IE (badInnerHTML), since
+      // there .innerHTML on PRE nodes is dumb, and discards
+      // whitespace.
+      var sfrom = sel.from.line, sto = sel.to.line, off = 0,
+          scratch = badInnerHTML && document.createElement("div");
+      for (var i = 0, e = updates.length; i < e; ++i) {
+        var rec = updates[i];
+        var extra = (rec.to - rec.from) - rec.domSize;
+        var nodeAfter = lineDiv.childNodes[rec.domStart + rec.domSize + off] || null;
+        if (badInnerHTML)
+          for (var j = Math.max(-extra, rec.domSize); j > 0; --j)
+            lineDiv.removeChild(nodeAfter ? nodeAfter.previousSibling : lineDiv.lastChild);
+        else if (extra) {
+          for (var j = Math.max(0, extra); j > 0; --j)
+            lineDiv.insertBefore(document.createElement("pre"), nodeAfter);
+          for (var j = Math.max(0, -extra); j > 0; --j)
+            lineDiv.removeChild(nodeAfter ? nodeAfter.previousSibling : lineDiv.lastChild);
+        }
+        var node = lineDiv.childNodes[rec.domStart + off], inSel = sfrom < rec.from && sto >= rec.from;
+        for (var j = rec.from; j < rec.to; ++j) {
+          var ch1 = null, ch2 = null;
+          if (inSel) {
+            ch1 = 0;
+            if (sto == j) {inSel = false; ch2 = sel.to.ch;}
+          }
+          else if (sfrom == j) {
+            if (sto == j) {ch1 = sel.from.ch; ch2 = sel.to.ch;}
+            else {inSel = true; ch1 = sel.from.ch;}
+          }
+          if (badInnerHTML) {
+            scratch.innerHTML = lines[j].getHTML(ch1, ch2, true);
+            lineDiv.insertBefore(scratch.firstChild, nodeAfter);
+          }
+          else {
+            node.innerHTML = lines[j].getHTML(ch1, ch2, false);
+            node.className = lines[j].className || "";
+            node = node.nextSibling;
+          }
+        }
+        off += extra;
+      }
+    }
+
+    function updateGutter() {
+      if (!options.gutter && !options.lineNumbers) return;
+      var hText = mover.offsetHeight, hEditor = wrapper.clientHeight;
+      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
+      var html = [];
+      for (var i = showingFrom; i < showingTo; ++i) {
+        var marker = lines[i].gutterMarker;
+        var text = options.lineNumbers ? i + options.firstLineNumber : null;
+        if (marker && marker.text)
+          text = marker.text.replace("%N%", text != null ? text : "");
+        else if (text == null)
+          text = "\u00a0";
+        html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text, "</pre>");
+      }
+      gutter.style.display = "none";
+      gutterText.innerHTML = html.join("");
+      var minwidth = String(lines.length).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = "";
+      while (val.length + pad.length < minwidth) pad += "\u00a0";
+      if (pad) firstNode.insertBefore(document.createTextNode(pad), firstNode.firstChild);
+      gutter.style.display = "";
+      lineSpace.style.marginLeft = gutter.offsetWidth + "px";
+    }
+    function updateCursor() {
+      var head = sel.inverted ? sel.from : sel.to;
+      var x = charX(head.line, head.ch) + "px", y = (head.line - showingFrom) * lineHeight() + "px";
+      inputDiv.style.top = y; inputDiv.style.left = x;
+      if (posEq(sel.from, sel.to)) {
+        cursor.style.top = y; cursor.style.left = x;
+        cursor.style.display = "";
+      }
+      else cursor.style.display = "none";
+    }
+
+    // Update the selection. Last two args are only used by
+    // updateLines, since they have to be expressed in the line
+    // numbers before the update.
+    function setSelection(from, to, oldFrom, oldTo) {
+      if (posEq(sel.from, from) && posEq(sel.to, to)) return;
+      var sh = shiftSelecting && clipPos(shiftSelecting);
+      if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
+      if (sh) {
+        if (posLess(sh, from)) from = sh;
+        else if (posLess(to, sh)) to = sh;
+      }
+
+      var startEq = posEq(sel.to, to), endEq = posEq(sel.from, from);
+      if (posEq(from, to)) sel.inverted = false;
+      else if (startEq && !endEq) sel.inverted = true;
+      else if (endEq && !startEq) sel.inverted = false;
+
+      // Some ugly logic used to only mark the lines that actually did
+      // see a change in selection as changed, rather than the whole
+      // selected range.
+      if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}
+      if (posEq(from, to)) {
+        if (!posEq(sel.from, sel.to))
+          changes.push({from: oldFrom, to: oldTo + 1});
+      }
+      else if (posEq(sel.from, sel.to)) {
+        changes.push({from: from.line, to: to.line + 1});
+      }
+      else {
+        if (!posEq(from, sel.from)) {
+          if (from.line < oldFrom)
+            changes.push({from: from.line, to: Math.min(to.line, oldFrom) + 1});
+          else
+            changes.push({from: oldFrom, to: Math.min(oldTo, from.line) + 1});
+        }
+        if (!posEq(to, sel.to)) {
+          if (to.line < oldTo)
+            changes.push({from: Math.max(oldFrom, from.line), to: oldTo + 1});
+          else
+            changes.push({from: Math.max(from.line, oldTo), to: to.line + 1});
+        }
+      }
+      sel.from = from; sel.to = to;
+      selectionChanged = true;
+    }
+    function setCursor(line, ch) {
+      var pos = clipPos({line: line, ch: ch || 0});
+      setSelection(pos, pos);
+    }
+
+    function clipLine(n) {return Math.max(0, Math.min(n, lines.length-1));}
+    function clipPos(pos) {
+      if (pos.line < 0) return {line: 0, ch: 0};
+      if (pos.line >= lines.length) return {line: lines.length-1, ch: lines[lines.length-1].text.length};
+      var ch = pos.ch, linelen = lines[pos.line].text.length;
+      if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
+      else if (ch < 0) return {line: pos.line, ch: 0};
+      else return pos;
+    }
+
+    function scrollPage(down) {
+      var linesPerPage = Math.floor(wrapper.clientHeight / lineHeight()), head = sel.inverted ? sel.from : sel.to;
+      setCursor(head.line + (Math.max(linesPerPage - 1, 1) * (down ? 1 : -1)), head.ch);
+    }
+    function scrollEnd(top) {
+      setCursor(top ? 0 : lines.length - 1);
+    }
+    function selectAll() {
+      var endLine = lines.length - 1;
+      setSelection({line: 0, ch: 0}, {line: endLine, ch: lines[endLine].text.length});
+    }
+    function selectWordAt(pos) {
+      var line = lines[pos.line].text;
+      var start = pos.ch, end = pos.ch;
+      while (start > 0 && /\w/.test(line.charAt(start - 1))) --start;
+      while (end < line.length - 1 && /\w/.test(line.charAt(end))) ++end;
+      setSelection({line: pos.line, ch: start}, {line: pos.line, ch: end});
+    }
+    function handleEnter() {
+      replaceSelection("\n", "end");
+      if (options.enterMode != "flat")
+        indentLine(sel.from.line, options.enterMode == "keep" ? "prev" : "smart");
+    }
+    function handleTab(shift) {
+      shiftSelecting = null;
+      switch (options.tabMode) {
+      case "default":
+        return false;
+      case "indent":
+        for (var i = sel.from.line, e = sel.to.line; i <= e; ++i) indentLine(i, "smart");
+        break;
+      case "classic":
+        if (posEq(sel.from, sel.to)) {
+          if (shift) indentLine(sel.from.line, "smart");
+          else replaceSelection("\t", "end");
+          break;
+        }
+      case "shift":
+        for (var i = sel.from.line, e = sel.to.line; i <= e; ++i) indentLine(i, shift ? "subtract" : "add");
+        break;
+      }
+      return true;
+    }
+
+    function indentLine(n, how) {
+      if (how == "smart") {
+        if (!mode.indent) how = "prev";
+        else var state = getStateBefore(n);
+      }
+
+      var line = lines[n], curSpace = line.indentation(), curSpaceString = line.text.match(/^\s*/)[0], indentation;
+      if (how == "prev") {
+        if (n) indentation = lines[n-1].indentation();
+        else indentation = 0;
+      }
+      else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length));
+      else if (how == "add") indentation = curSpace + options.indentUnit;
+      else if (how == "subtract") indentation = curSpace - options.indentUnit;
+      indentation = Math.max(0, indentation);
+      var diff = indentation - curSpace;
+
+      if (!diff) {
+        if (sel.from.line != n && sel.to.line != n) return;
+        var indentString = curSpaceString;
+      }
+      else {
+        var indentString = "", pos = 0;
+        if (options.indentWithTabs)
+          for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
+        while (pos < indentation) {++pos; indentString += " ";}
+      }
+
+      replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
+    }
+
+    function loadMode() {
+      mode = CodeMirror.getMode(options, options.mode);
+      for (var i = 0, l = lines.length; i < l; ++i)
+        lines[i].stateAfter = null;
+      work = [0];
+    }
+    function gutterChanged() {
+      var visible = options.gutter || options.lineNumbers;
+      gutter.style.display = visible ? "" : "none";
+      if (visible) updateGutter();
+      else lineDiv.parentNode.style.marginLeft = 0;
+    }
+
+    function markText(from, to, className) {
+      from = clipPos(from); to = clipPos(to);
+      var accum = [];
+      function add(line, from, to, className) {
+        var line = lines[line], mark = line.addMark(from, to, className);
+        mark.line = line;
+        accum.push(mark);
+      }
+      if (from.line == to.line) add(from.line, from.ch, to.ch, className);
+      else {
+        add(from.line, from.ch, null, className);
+        for (var i = from.line + 1, e = to.line; i < e; ++i)
+          add(i, 0, null, className);
+        add(to.line, 0, to.ch, className);
+      }
+      changes.push({from: from.line, to: to.line + 1});
+      return function() {
+        var start, end;
+        for (var i = 0; i < accum.length; ++i) {
+          var mark = accum[i], found = indexOf(lines, mark.line);
+          mark.line.removeMark(mark);
+          if (found > -1) {
+            if (start == null) start = found;
+            end = found;
+          }
+        }
+        if (start != null) changes.push({from: start, to: end + 1});
+      };
+    }
+
+    function addGutterMarker(line, text, className) {
+      if (typeof line == "number") line = lines[clipLine(line)];
+      line.gutterMarker = {text: text, style: className};
+      updateGutter();
+      return line;
+    }
+    function removeGutterMarker(line) {
+      if (typeof line == "number") line = lines[clipLine(line)];
+      line.gutterMarker = null;
+      updateGutter();
+    }
+    function setLineClass(line, className) {
+      if (typeof line == "number") {
+        var no = line;
+        line = lines[clipLine(line)];
+      }
+      else {
+        var no = indexOf(lines, line);
+        if (no == -1) return null;
+      }
+      line.className = className;
+      changes.push({from: no, to: no + 1});
+      return line;
+    }
+
+    function lineInfo(line) {
+      if (typeof line == "number") {
+        var n = line;
+        line = lines[line];
+        if (!line) return null;
+      }
+      else {
+        var n = indexOf(lines, line);
+        if (n == -1) return null;
+      }
+      var marker = line.gutterMarker;
+      return {line: n, text: line.text, markerText: marker && marker.text, markerClass: marker && marker.style};
+    }
+
+    // These are used to go from pixel positions to character
+    // positions, taking tabs into account.
+    function charX(line, pos) {
+      var text = lines[line].text, span = measure.firstChild;
+      if (text.lastIndexOf("\t", pos) == -1) return pos * charWidth();
+      var old = span.firstChild.nodeValue;
+      try {
+        span.firstChild.nodeValue = text.slice(0, pos);
+        return span.offsetWidth;
+      } finally {span.firstChild.nodeValue = old;}
+    }
+    function charFromX(line, x) {
+      var text = lines[line].text, cw = charWidth();
+      if (x <= 0) return 0;
+      if (text.indexOf("\t") == -1) return Math.min(text.length, Math.round(x / cw));
+      var mspan = measure.firstChild, mtext = mspan.firstChild, old = mtext.nodeValue;
+      try {
+        mtext.nodeValue = text;
+        var from = 0, fromX = 0, to = text.length, toX = mspan.offsetWidth;
+        if (x > toX) return to;
+        for (;;) {
+          if (to - from <= 1) return (toX - x > x - fromX) ? from : to;
+          var middle = Math.ceil((from + to) / 2);
+          mtext.nodeValue = text.slice(0, middle);
+          var curX = mspan.offsetWidth;
+          if (curX > x) {to = middle; toX = curX;}
+          else {from = middle; fromX = curX;}
+        }
+      } finally {mtext.nodeValue = old;}
+    }
+
+    function localCoords(pos, inLineWrap) {
+      var lh = lineHeight(), line = pos.line - (inLineWrap ? showingFrom : 0);
+      return {x: charX(pos.line, pos.ch), y: line * lh, yBot: (line + 1) * lh};
+    }
+    function pageCoords(pos) {
+      var local = localCoords(pos, true), off = eltOffset(lineSpace);
+      return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};
+    }
+
+    function lineHeight() {
+      var nlines = lineDiv.childNodes.length;
+      if (nlines) return lineDiv.offsetHeight / nlines;
+      else return measure.firstChild.offsetHeight || 1;
+    }
+    function charWidth() {return (measure.firstChild.offsetWidth || 320) / 40;}
+    function paddingTop() {return lineSpace.offsetTop;}
+    function paddingLeft() {return lineSpace.offsetLeft;}
+
+    function posFromMouse(e, liberal) {
+      var off = eltOffset(lineSpace),
+          x = e.pageX() - off.left,
+          y = e.pageY() - off.top;
+      if (!liberal && e.target() != lineSpace.parentNode && !(e.target() == wrapper && y > (lines.length * lineHeight())))
+        for (var n = e.target(); n != lineDiv && n != cursor; n = n.parentNode)
+          if (!n || n == wrapper) return null;
+      var line = showingFrom + Math.floor(y / lineHeight());
+      return clipPos({line: line, ch: charFromX(clipLine(line), x)});
+    }
+    function onContextMenu(e) {
+      var pos = posFromMouse(e);
+      if (!pos || window.opera) return; // Opera is difficult.
+      if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
+        setCursor(pos.line, pos.ch);
+
+      var oldCSS = input.style.cssText;
+      input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.pageY() - 1) +
+        "px; left: " + (e.pageX() - 1) + "px; z-index: 1000; background: white; " +
+        "border-width: 0; outline: none; overflow: hidden;";
+      var val = input.value = getSelection();
+      input.focus();
+      setSelRange(input, 0, val.length);
+      if (gecko) e.stop();
+      leaveInputAlone = true;
+      setTimeout(function() {
+        if (input.value != val) operation(replaceSelection)(input.value, "end");
+        input.style.cssText = oldCSS;
+        leaveInputAlone = false;
+        prepareInput();
+        slowPoll();
+      }, 50);
+    }
+
+    // Cursor-blinking
+    function restartBlink() {
+      clearInterval(blinker);
+      var on = true;
+      cursor.style.visibility = "";
+      blinker = setInterval(function() {
+        cursor.style.visibility = (on = !on) ? "" : "hidden";
+      }, 650);
+    }
+
+    var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
+    function matchBrackets(autoclear) {
+      var head = sel.inverted ? sel.from : sel.to, line = lines[head.line], pos = head.ch - 1;
+      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
+      if (!match) return;
+      var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles;
+      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)
+        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}
+
+      var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
+      function scan(line, from, to) {
+        if (!line.text) return;
+        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
+        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
+          var text = st[i];
+          if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}
+          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
+            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
+              var match = matching[cur];
+              if (match.charAt(1) == ">" == forward) stack.push(cur);
+              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
+              else if (!stack.length) return {pos: pos, match: true};
+            }
+          }
+        }
+      }
+      for (var i = head.line, e = forward ? Math.min(i + 50, lines.length) : Math.max(0, i - 50); i != e; i+=d) {
+        var line = lines[i], first = i == head.line;
+        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
+        if (found) {
+          var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
+          var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
+              two = markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
+          var clear = operation(function(){one(); two();});
+          if (autoclear) setTimeout(clear, 800);
+          else bracketHighlighted = clear;
+          break;
+        }
+      }
+    }
+
+    // Finds the line to start with when starting a parse. Tries to
+    // find a line with a stateAfter, so that it can start with a
+    // valid state. If that fails, it returns the line with the
+    // smallest indentation, which tends to need the least context to
+    // parse correctly.
+    function findStartLine(n) {
+      var minindent, minline;
+      for (var search = n, lim = n - 40; search > lim; --search) {
+        if (search == 0) return 0;
+        var line = lines[search-1];
+        if (line.stateAfter) return search;
+        var indented = line.indentation();
+        if (minline == null || minindent > indented) {
+          minline = search;
+          minindent = indented;
+        }
+      }
+      return minline;
+    }
+    function getStateBefore(n) {
+      var start = findStartLine(n), state = start && lines[start-1].stateAfter;
+      if (!state) state = startState(mode);
+      else state = copyState(mode, state);
+      for (var i = start; i < n; ++i) {
+        var line = lines[i];
+        line.highlight(mode, state);
+        line.stateAfter = copyState(mode, state);
+      }
+      if (!lines[n].stateAfter) work.push(n);
+      return state;
+    }
+    function highlightWorker() {
+      var end = +new Date + options.workTime;
+      while (work.length) {
+        if (!lines[showingFrom].stateAfter) var task = showingFrom;
+        else var task = work.pop();
+        if (task >= lines.length) continue;
+        var start = findStartLine(task), state = start && lines[start-1].stateAfter;
+        if (state) state = copyState(mode, state);
+        else state = startState(mode);
+
+        for (var i = start, l = lines.length; i < l; ++i) {
+          var line = lines[i], hadState = line.stateAfter;
+          if (+new Date > end) {
+            work.push(i);
+            startWorker(options.workDelay);
+            changes.push({from: task, to: i});
+            return;
+          }
+          var changed = line.highlight(mode, state);
+          line.stateAfter = copyState(mode, state);
+          if (hadState && !changed && line.text) break;
+        }
+        changes.push({from: task, to: i});
+      }
+    }
+    function startWorker(time) {
+      if (!work.length) return;
+      highlight.set(time, operation(highlightWorker));
+    }
+
+    // Operations are used to wrap changes in such a way that each
+    // change won't have to update the cursor and display (which would
+    // be awkward, slow, and error-prone), but instead updates are
+    // batched and then all combined and executed at once.
+    function startOperation() {
+      updateInput = null; changes = []; textChanged = selectionChanged = false;
+    }
+    function endOperation() {
+      var reScroll = false;
+      if (selectionChanged) reScroll = !scrollCursorIntoView();
+      if (changes.length) updateDisplay(changes);
+      else if (selectionChanged) updateCursor();
+      if (reScroll) scrollCursorIntoView();
+      if (selectionChanged) restartBlink();
+
+      // updateInput can be set to a boolean value to force/prevent an
+      // update.
+      if (!leaveInputAlone && (updateInput === true || (updateInput !== false && selectionChanged)))
+        prepareInput();
+
+      if (selectionChanged && options.onCursorActivity)
+        options.onCursorActivity(instance);
+      if (textChanged && options.onChange)
+        options.onChange(instance);
+      if (selectionChanged && options.matchBrackets)
+        setTimeout(operation(function() {
+          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
+          matchBrackets(false);
+        }), 20);
+    }
+    var nestedOperation = 0;
+    function operation(f) {
+      return function() {
+        if (!nestedOperation++) startOperation();
+        try {var result = f.apply(this, arguments);}
+        finally {if (!--nestedOperation) endOperation();}
+        return result;
+      };
+    }
+
+    function SearchCursor(query, pos, caseFold) {
+      this.atOccurrence = false;
+      if (caseFold == null) caseFold = typeof query == "string" && query == query.toLowerCase();
+
+      if (pos && typeof pos == "object") pos = clipPos(pos);
+      else pos = {line: 0, ch: 0};
+      this.pos = {from: pos, to: pos};
+
+      // The matches method is filled in based on the type of query.
+      // It takes a position and a direction, and returns an object
+      // describing the next occurrence of the query, or null if no
+      // more matches were found.
+      if (typeof query != "string") // Regexp match
+        this.matches = function(reverse, pos) {
+          if (reverse) {
+            var line = lines[pos.line].text.slice(0, pos.ch), match = line.match(query), start = 0;
+            while (match) {
+              var ind = line.indexOf(match[0]);
+              start += ind;
+              line = line.slice(ind + 1);
+              var newmatch = line.match(query);
+              if (newmatch) match = newmatch;
+              else break;
+            }
+          }
+          else {
+            var line = lines[pos.line].text.slice(pos.ch), match = line.match(query),
+                start = match && pos.ch + line.indexOf(match[0]);
+          }
+          if (match)
+            return {from: {line: pos.line, ch: start},
+                    to: {line: pos.line, ch: start + match[0].length},
+                    match: match};
+        };
+      else { // String query
+        if (caseFold) query = query.toLowerCase();
+        var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
+        var target = query.split("\n");
+        // Different methods for single-line and multi-line queries
+        if (target.length == 1)
+          this.matches = function(reverse, pos) {
+            var line = fold(lines[pos.line].text), len = query.length, match;
+            if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
+                        : (match = line.indexOf(query, pos.ch)) != -1)
+              return {from: {line: pos.line, ch: match},
+                      to: {line: pos.line, ch: match + len}};
+          };
+        else
+          this.matches = function(reverse, pos) {
+            var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(lines[ln].text);
+            var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
+            if (reverse ? offsetA >= pos.ch || offsetA != match.length
+                        : offsetA <= pos.ch || offsetA != line.length - match.length)
+              return;
+            for (;;) {
+              if (reverse ? !ln : ln == lines.length - 1) return;
+              line = fold(lines[ln += reverse ? -1 : 1].text);
+              match = target[reverse ? --idx : ++idx];
+              if (idx > 0 && idx < target.length - 1) {
+                if (line != match) return;
+                else continue;
+              }
+              var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
+              if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
+                return;
+              var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};
+              return {from: reverse ? end : start, to: reverse ? start : end};
+            }
+          };
+      }
+    }
+
+    SearchCursor.prototype = {
+      findNext: function() {return this.find(false);},
+      findPrevious: function() {return this.find(true);},
+
+      find: function(reverse) {
+        var self = this, pos = clipPos(reverse ? this.pos.from : this.pos.to);
+        function savePosAndFail(line) {
+          var pos = {line: line, ch: 0};
+          self.pos = {from: pos, to: pos};
+          self.atOccurrence = false;
+          return false;
+        }
+
+        for (;;) {
+          if (this.pos = this.matches(reverse, pos)) {
+            this.atOccurrence = true;
+            return this.pos.match || true;
+          }
+          if (reverse) {
+            if (!pos.line) return savePosAndFail(0);
+            pos = {line: pos.line-1, ch: lines[pos.line-1].text.length};
+          }
+          else {
+            if (pos.line == lines.length - 1) return savePosAndFail(lines.length);
+            pos = {line: pos.line+1, ch: 0};
+          }
+        }
+      },
+
+      from: function() {if (this.atOccurrence) return copyPos(this.pos.from);},
+      to: function() {if (this.atOccurrence) return copyPos(this.pos.to);}
+    };
+
+    return instance;
+  } // (end of function CodeMirror)
+
+  // The default configuration options.
+  CodeMirror.defaults = {
+    value: "",
+    mode: null,
+    indentUnit: 2,
+    indentWithTabs: false,
+    tabMode: "classic",
+    enterMode: "indent",
+    electricChars: true,
+    onKeyEvent: null,
+    lineNumbers: false,
+    gutter: false,
+    firstLineNumber: 1,
+    readOnly: false,
+    onChange: null,
+    onCursorActivity: null,
+    onGutterClick: null,
+    onFocus: null, onBlur: null, onScroll: null,
+    matchBrackets: false,
+    workTime: 100,
+    workDelay: 200,
+    undoDepth: 40,
+    tabindex: null
+  };
+
+  // Known modes, by name and by MIME
+  var modes = {}, mimeModes = {};
+  CodeMirror.defineMode = function(name, mode) {
+    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
+    modes[name] = mode;
+  };
+  CodeMirror.defineMIME = function(mime, spec) {
+    mimeModes[mime] = spec;
+  };
+  CodeMirror.getMode = function(options, spec) {
+    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
+      spec = mimeModes[spec];
+    if (typeof spec == "string")
+      var mname = spec, config = {};
+    else
+      var mname = spec.name, config = spec;
+    var mfactory = modes[mname];
+    if (!mfactory) {
+      if (window.console) console.warn("No mode " + mname + " found, falling back to plain text.");
+      return CodeMirror.getMode(options, "text/plain");
+    }
+    return mfactory(options, config);
+  }
+  CodeMirror.listModes = function() {
+    var list = [];
+    for (var m in modes)
+      if (modes.propertyIsEnumerable(m)) list.push(m);
+    return list;
+  };
+  CodeMirror.listMIMEs = function() {
+    var list = [];
+    for (var m in mimeModes)
+      if (mimeModes.propertyIsEnumerable(m)) list.push(m);
+    return list;
+  };
+
+  CodeMirror.fromTextArea = function(textarea, options) {
+    if (!options) options = {};
+    options.value = textarea.value;
+    if (!options.tabindex && textarea.tabindex)
+      options.tabindex = textarea.tabindex;
+
+    function save() {textarea.value = instance.getValue();}
+    if (textarea.form) {
+      // Deplorable hack to make the submit method do the right thing.
+      var rmSubmit = connect(textarea.form, "submit", save, true);
+      if (typeof textarea.form.submit == "function") {
+        var realSubmit = textarea.form.submit;
+        function wrappedSubmit() {
+          save();
+          textarea.form.submit = realSubmit;
+          textarea.form.submit();
+          textarea.form.submit = wrappedSubmit;
+        }
+        textarea.form.submit = wrappedSubmit;
+      }
+    }
+
+    textarea.style.display = "none";
+    var instance = CodeMirror(function(node) {
+      textarea.parentNode.insertBefore(node, textarea.nextSibling);
+    }, options);
+    instance.save = save;
+    instance.toTextArea = function() {
+      save();
+      textarea.parentNode.removeChild(instance.getWrapperElement());
+      textarea.style.display = "";
+      if (textarea.form) {
+        rmSubmit();
+        if (typeof textarea.form.submit == "function")
+          textarea.form.submit = realSubmit;
+      }
+    };
+    return instance;
+  };
+
+  // Utility functions for working with state. Exported because modes
+  // sometimes need to do this.
+  function copyState(mode, state) {
+    if (state === true) return state;
+    if (mode.copyState) return mode.copyState(state);
+    var nstate = {};
+    for (var n in state) {
+      var val = state[n];
+      if (val instanceof Array) val = val.concat([]);
+      nstate[n] = val;
+    }
+    return nstate;
+  }
+  CodeMirror.startState = startState;
+  function startState(mode, a1, a2) {
+    return mode.startState ? mode.startState(a1, a2) : true;
+  }
+  CodeMirror.copyState = copyState;
+
+  // The character stream used by a mode's parser.
+  function StringStream(string) {
+    this.pos = this.start = 0;
+    this.string = string;
+  }
+  StringStream.prototype = {
+    eol: function() {return this.pos >= this.string.length;},
+    sol: function() {return this.pos == 0;},
+    peek: function() {return this.string.charAt(this.pos);},
+    next: function() {
+      if (this.pos < this.string.length)
+        return this.string.charAt(this.pos++);
+    },
+    eat: function(match) {
+      var ch = this.string.charAt(this.pos);
+      if (typeof match == "string") var ok = ch == match;
+      else var ok = ch && (match.test ? match.test(ch) : match(ch));
+      if (ok) {++this.pos; return ch;}
+    },
+    eatWhile: function(match) {
+      var start = this.start;
+      while (this.eat(match)){}
+      return this.pos > start;
+    },
+    eatSpace: function() {
+      var start = this.pos;
+      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+      return this.pos > start;
+    },
+    skipToEnd: function() {this.pos = this.string.length;},
+    skipTo: function(ch) {
+      var found = this.string.indexOf(ch, this.pos);
+      if (found > -1) {this.pos = found; return true;}
+    },
+    backUp: function(n) {this.pos -= n;},
+    column: function() {return countColumn(this.string, this.start);},
+    indentation: function() {return countColumn(this.string);},
+    match: function(pattern, consume, caseInsensitive) {
+      if (typeof pattern == "string") {
+        function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
+        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+          if (consume !== false) this.pos += pattern.length;
+          return true;
+        }
+      }
+      else {
+        var match = this.string.slice(this.pos).match(pattern);
+        if (match && consume !== false) this.pos += match[0].length;
+        return match;
+      }
+    },
+    current: function(){return this.string.slice(this.start, this.pos);}
+  };
+
+  // Line objects. These hold state related to a line, including
+  // highlighting info (the styles array).
+  function Line(text, styles) {
+    this.styles = styles || [text, null];
+    this.stateAfter = null;
+    this.text = text;
+    this.marked = this.gutterMarker = this.className = null;
+  }
+  Line.prototype = {
+    // Replace a piece of a line, keeping the styles around it intact.
+    replace: function(from, to, text) {
+      var st = [], mk = this.marked;
+      copyStyles(0, from, this.styles, st);
+      if (text) st.push(text, null);
+      copyStyles(to, this.text.length, this.styles, st);
+      this.styles = st;
+      this.text = this.text.slice(0, from) + text + this.text.slice(to);
+      this.stateAfter = null;
+      if (mk) {
+        var diff = text.length - (to - from), end = this.text.length;
+        function fix(n) {return n <= Math.min(to, to + diff) ? n : n + diff;}
+        for (var i = 0; i < mk.length; ++i) {
+          var mark = mk[i], del = false;
+          if (mark.from >= end) del = true;
+          else {mark.from = fix(mark.from); if (mark.to != null) mark.to = fix(mark.to);}
+          if (del || mark.from >= mark.to) {mk.splice(i, 1); i--;}
+        }
+      }
+    },
+    // Split a line in two, again keeping styles intact.
+    split: function(pos, textBefore) {
+      var st = [textBefore, null];
+      copyStyles(pos, this.text.length, this.styles, st);
+      return new Line(textBefore + this.text.slice(pos), st);
+    },
+    addMark: function(from, to, style) {
+      var mk = this.marked, mark = {from: from, to: to, style: style};
+      if (this.marked == null) this.marked = [];
+      this.marked.push(mark);
+      this.marked.sort(function(a, b){return a.from - b.from;});
+      return mark;
+    },
+    removeMark: function(mark) {
+      var mk = this.marked;
+      if (!mk) return;
+      for (var i = 0; i < mk.length; ++i)
+        if (mk[i] == mark) {mk.splice(i, 1); break;}
+    },
+    // Run the given mode's parser over a line, update the styles
+    // array, which contains alternating fragments of text and CSS
+    // classes.
+    highlight: function(mode, state) {
+      var stream = new StringStream(this.text), st = this.styles, pos = 0, changed = false;
+      while (!stream.eol()) {
+        var style = mode.token(stream, state);
+        var substr = this.text.slice(stream.start, stream.pos);
+        stream.start = stream.pos;
+        if (pos && st[pos-1] == style)
+          st[pos-2] += substr;
+        else if (substr) {
+          if (!changed && st[pos] != substr || st[pos+1] != style) changed = true;
+          st[pos++] = substr; st[pos++] = style;
+        }
+        // Give up when line is ridiculously long
+        if (stream.pos > 5000) {
+          st[pos++] = this.text.slice(stream.pos); st[pos++] = null;
+          break;
+        }
+      }
+      if (st.length != pos) {st.length = pos; changed = true;}
+      return changed;
+    },
+    // Fetch the parser token for a given character. Useful for hacks
+    // that want to inspect the mode state (say, for completion).
+    getTokenAt: function(mode, state, ch) {
+      var txt = this.text, stream = new StringStream(txt);
+      while (stream.pos < ch && !stream.eol()) {
+        stream.start = stream.pos;
+        var style = mode.token(stream, state);
+      }
+      return {start: stream.start,
+              end: stream.pos,
+              string: stream.current(),
+              className: style || null,
+              state: state};
+    },
+    indentation: function() {return countColumn(this.text);},
+    // Produces an HTML fragment for the line, taking selection,
+    // marking, and highlighting into account.
+    getHTML: function(sfrom, sto, includePre) {
+      var html = [];
+      if (includePre)
+        html.push(this.className ? '<pre class="' + this.className + '">': "<pre>");
+      function span(text, style) {
+        if (!text) return;
+        if (style) html.push('<span class="', style, '">', htmlEscape(text), "</span>");
+        else html.push(htmlEscape(text));
+      }
+      var st = this.styles, allText = this.text, marked = this.marked;
+      if (sfrom == sto) sfrom = null;
+
+      if (!allText)
+        span(" ", sfrom != null && sto == null ? "CodeMirror-selected" : null);
+      else if (!marked && sfrom == null)
+        for (var i = 0, e = st.length; i < e; i+=2) span(st[i], st[i+1]);
+      else {
+        var pos = 0, i = 0, text = "", style, sg = 0;
+        var markpos = -1, mark = null;
+        function nextMark() {
+          if (marked) {
+            markpos += 1;
+            mark = (markpos < marked.length) ? marked[markpos] : null;
+          }
+        }
+        nextMark();        
+        while (pos < allText.length) {
+          var upto = allText.length;
+          var extraStyle = "";
+          if (sfrom != null) {
+            if (sfrom > pos) upto = sfrom;
+            else if (sto == null || sto > pos) {
+              extraStyle = " CodeMirror-selected";
+              if (sto != null) upto = Math.min(upto, sto);
+            }
+          }
+          while (mark && mark.to != null && mark.to <= pos) nextMark();
+          if (mark) {
+            if (mark.from > pos) upto = Math.min(upto, mark.from);
+            else {
+              extraStyle += " " + mark.style;
+              if (mark.to != null) upto = Math.min(upto, mark.to);
+            }
+          }
+          for (;;) {
+            var end = pos + text.length;
+            var apliedStyle = style;
+            if (extraStyle) apliedStyle = style ? style + extraStyle : extraStyle;
+            span(end > upto ? text.slice(0, upto - pos) : text, apliedStyle);
+            if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
+            pos = end;
+            text = st[i++]; style = st[i++];
+          }
+        }
+        if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
+      }
+      if (includePre) html.push("</pre>");
+      return html.join("");
+    }
+  };
+  // Utility used by replace and split above
+  function copyStyles(from, to, source, dest) {
+    for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {
+      var part = source[i], end = pos + part.length;
+      if (state == 0) {
+        if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
+        if (end >= from) state = 1;
+      }
+      else if (state == 1) {
+        if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
+        else dest.push(part, source[i+1]);
+      }
+      pos = end;
+    }
+  }
+
+  // The history object 'chunks' changes that are made close together
+  // and at almost the same time into bigger undoable units.
+  function History() {
+    this.time = 0;
+    this.done = []; this.undone = [];
+  }
+  History.prototype = {
+    addChange: function(start, added, old) {
+      this.undone.length = 0;
+      var time = +new Date, last = this.done[this.done.length - 1];
+      if (time - this.time > 400 || !last ||
+          last.start > start + added || last.start + last.added < start - last.added + last.old.length)
+        this.done.push({start: start, added: added, old: old});
+      else {
+        var oldoff = 0;
+        if (start < last.start) {
+          for (var i = last.start - start - 1; i >= 0; --i)
+            last.old.unshift(old[i]);
+          last.added += last.start - start;
+          last.start = start;
+        }
+        else if (last.start < start) {
+          oldoff = start - last.start;
+          added += oldoff;
+        }
+        for (var i = last.added - oldoff, e = old.length; i < e; ++i)
+          last.old.push(old[i]);
+        if (last.added < added) last.added = added;
+      }
+      this.time = time;
+    }
+  };
+
+  // Event stopping compatibility wrapper.
+  function stopEvent() {
+    if (this.preventDefault) {this.preventDefault(); this.stopPropagation();}
+    else {this.returnValue = false; this.cancelBubble = true;}
+  }
+  // Ensure an event has a stop method.
+  function addStop(event) {
+    if (!event.stop) event.stop = stopEvent;
+    return event;
+  }
+
+  // Event wrapper, exposing the few operations we need.
+  function Event(orig) {this.e = orig;}
+  Event.prototype = {
+    stop: function() {stopEvent.call(this.e);},
+    target: function() {return this.e.target || this.e.srcElement;},
+    button: function() {
+      if (this.e.which) return this.e.which;
+      else if (this.e.button & 1) return 1;
+      else if (this.e.button & 2) return 3;
+      else if (this.e.button & 4) return 2;
+    },
+    pageX: function() {
+      if (this.e.pageX != null) return this.e.pageX;
+      else return this.e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+    },
+    pageY: function() {
+      if (this.e.pageY != null) return this.e.pageY;
+      else return this.e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+    }
+  };
+
+  // Event handler registration. If disconnect is true, it'll return a
+  // function that unregisters the handler.
+  function connect(node, type, handler, disconnect) {
+    function wrapHandler(event) {handler(new Event(event || window.event));}
+    if (typeof node.addEventListener == "function") {
+      node.addEventListener(type, wrapHandler, false);
+      if (disconnect) return function() {node.removeEventListener(type, wrapHandler, false);};
+    }
+    else {
+      node.attachEvent("on" + type, wrapHandler);
+      if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
+    }
+  }
+
+  function Delayed() {this.id = null;}
+  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
+
+  // Some IE versions don't preserve whitespace when setting the
+  // innerHTML of a PRE tag.
+  var badInnerHTML = (function() {
+    var pre = document.createElement("pre");
+    pre.innerHTML = " "; return !pre.innerHTML;
+  })();
+
+  var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
+
+  var lineSep = "\n";
+  // Feature-detect whether newlines in textareas are converted to \r\n
+  (function () {
+    var te = document.createElement("textarea");
+    te.value = "foo\nbar";
+    if (te.value.indexOf("\r") > -1) lineSep = "\r\n";
+  }());
+
+  var tabSize = 8;
+  var mac = /Mac/.test(navigator.platform);
+  var movementKeys = {};
+  for (var i = 35; i <= 40; ++i)
+    movementKeys[i] = movementKeys["c" + i] = true;
+
+  // Counts the column offset in a string, taking tabs into account.
+  // Used mostly to find indentation.
+  function countColumn(string, end) {
+    if (end == null) {
+      end = string.search(/[^\s\u00a0]/);
+      if (end == -1) end = string.length;
+    }
+    for (var i = 0, n = 0; i < end; ++i) {
+      if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
+      else ++n;
+    }
+    return n;
+  }
+
+  // Find the position of an element by following the offsetParent chain.
+  function eltOffset(node) {
+    var x = 0, y = 0, n2 = node;
+    for (var n = node; n; n = n.offsetParent) {x += n.offsetLeft; y += n.offsetTop;}
+    for (var n = node; n != document.body; n = n.parentNode) {x -= n.scrollLeft; y -= n.scrollTop;}
+    return {left: x, top: y};
+  }
+  // Get a node's text content.
+  function eltText(node) {
+    return node.textContent || node.innerText || node.nodeValue || "";
+  }
+
+  // Operations on {line, ch} objects.
+  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
+  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
+  function copyPos(x) {return {line: x.line, ch: x.ch};}
+
+  function htmlEscape(str) {
+    return str.replace(/[<&]/g, function(str) {return str == "&" ? "&amp;" : "&lt;";});
+  }
+
+  // Used to position the cursor after an undo/redo by finding the
+  // last edited character.
+  function editEnd(from, to) {
+    if (!to) return from ? from.length : 0;
+    if (!from) return to.length;
+    for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)
+      if (from.charAt(i) != to.charAt(j)) break;
+    return j + 1;
+  }
+
+  function indexOf(collection, elt) {
+    if (collection.indexOf) return collection.indexOf(elt);
+    for (var i = 0, e = collection.length; i < e; ++i)
+      if (collection[i] == elt) return i;
+    return -1;
+  }
+
+  // See if "".split is the broken IE version, if so, provide an
+  // alternative way to split lines.
+  if ("\n\nb".split(/\n/).length != 3)
+    var splitLines = function(string) {
+      var pos = 0, nl, result = [];
+      while ((nl = string.indexOf("\n", pos)) > -1) {
+        result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl));
+        pos = nl + 1;
+      }
+      result.push(string.slice(pos));
+      return result;
+    };
+  else
+    var splitLines = function(string){return string.split(/\r?\n/);};
+
+  // Sane model of finding and setting the selection in a textarea
+  if (window.getSelection) {
+    var selRange = function(te) {
+      try {return {start: te.selectionStart, end: te.selectionEnd};}
+      catch(e) {return null;}
+    };
+    var setSelRange = function(te, start, end) {
+      try {te.setSelectionRange(start, end);}
+      catch(e) {} // Fails on Firefox when textarea isn't part of the document
+    };
+  }
+  // IE model. Don't ask.
+  else {
+    var selRange = function(te) {
+      try {var range = document.selection.createRange();}
+      catch(e) {return null;}
+      if (!range || range.parentElement() != te) return null;
+      var val = te.value, len = val.length, localRange = te.createTextRange();
+      localRange.moveToBookmark(range.getBookmark());
+      var endRange = te.createTextRange();
+      endRange.collapse(false);
+
+      if (localRange.compareEndPoints("StartToEnd", endRange) > -1)
+        return {start: len, end: len};
+
+      var start = -localRange.moveStart("character", -len);
+      for (var i = val.indexOf("\r"); i > -1 && i < start; i = val.indexOf("\r", i+1), start++) {}
+
+      if (localRange.compareEndPoints("EndToEnd", endRange) > -1)
+        return {start: start, end: len};
+
+      var end = -localRange.moveEnd("character", -len);
+      for (var i = val.indexOf("\r"); i > -1 && i < end; i = val.indexOf("\r", i+1), end++) {}
+      return {start: start, end: end};
+    };
+    var setSelRange = function(te, start, end) {
+      var range = te.createTextRange();
+      range.collapse(true);
+      var endrange = range.duplicate();
+      var newlines = 0, txt = te.value;
+      for (var pos = txt.indexOf("\n"); pos > -1 && pos < start; pos = txt.indexOf("\n", pos + 1))
+        ++newlines;
+      range.move("character", start - newlines);
+      for (; pos > -1 && pos < end; pos = txt.indexOf("\n", pos + 1))
+        ++newlines;
+      endrange.move("character", end - newlines);
+      range.setEndPoint("EndToEnd", endrange);
+      range.select();
+    };
+  }
+
+  CodeMirror.defineMode("null", function() {
+    return {token: function(stream) {stream.skipToEnd();}};
+  });
+  CodeMirror.defineMIME("text/plain", "null");
+
+  return CodeMirror;
+})();
--- a/rhodecode/public/js/graph.js	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/public/js/graph.js	Fri Oct 07 01:08:50 2011 +0200
@@ -58,10 +58,10 @@
 		this.ctx.fillStyle = s;
 	}
 
-	this.render = function(data) {
+	this.render = function(data,pad) {
 		var idx = 1;
 		var rela = document.getElementById('graph');
-		var pad = 160;
+		var pad = pad;
 		var scale = 22;
 		
 		for (var i in data) {
@@ -75,7 +75,6 @@
 			//	extra = next.outerHeight();
 			//}
 						
-			
 			this.cell[1] += row.clientWidth;
 			this.bg[1] += this.bg_height;
 			
@@ -101,15 +100,14 @@
 				
 				this.setColor(color, 0.0, 0.65);
 				
-				
 				y = row.offsetTop-rela.offsetTop+4;
 				x = pad-((this.cell[0] + this.box_size * start - 1) + this.bg_height-2);
+				
 				this.ctx.lineWidth=this.line_width;
 				this.ctx.beginPath();
 				this.ctx.moveTo(x, y);
-				
-				//i don't know why it's +1 just fixes some drawing graph.
-				y += row.clientHeight+1;
+
+				y += row.offsetHeight;
 				x = pad-((1 + this.box_size * end) + this.bg_height-2);
 				this.ctx.lineTo(x,y+extra,3);
 				this.ctx.stroke();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/public/js/rhodecode.js	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,219 @@
+/**
+RhodeCode JS Files
+**/
+
+if (typeof console == "undefined" || typeof console.log == "undefined"){
+	console = { log: function() {} }
+}
+
+
+function str_repeat(i, m) {
+	for (var o = []; m > 0; o[--m] = i);
+	return o.join('');
+}
+
+/**
+ * INJECT .format function into String
+ * Usage: "My name is {0} {1}".format("Johny","Bravo")
+ * Return "My name is Johny Bravo"
+ * Inspired by https://gist.github.com/1049426
+ */
+String.prototype.format = function() {
+	  
+	  function format() {
+	    var str = this;
+	    var len = arguments.length+1;
+	    var safe = undefined;
+	    var arg = undefined;
+	    
+	    // For each {0} {1} {n...} replace with the argument in that position.  If 
+	    // the argument is an object or an array it will be stringified to JSON.
+	    for (var i=0; i < len; arg = arguments[i++]) {
+	      safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
+	      str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
+	    }
+	    return str;
+	  }
+
+	  // Save a reference of what may already exist under the property native.  
+	  // Allows for doing something like: if("".format.native) { /* use native */ }
+	  format.native = String.prototype.format;
+
+	  // Replace the prototype property
+	  return format;
+
+}();
+
+
+/**
+ * SmartColorGenerator
+ *
+ *usage::
+ *	var CG = new ColorGenerator();
+ *  var col = CG.getColor(key); //returns array of RGB
+ *  'rgb({0})'.format(col.join(',')
+ * 
+ * @returns {ColorGenerator}
+ */
+function ColorGenerator(){
+	this.GOLDEN_RATIO = 0.618033988749895;
+	this.CURRENT_RATIO = 0.22717784590367374 // this can be random
+	this.HSV_1 = 0.75;//saturation
+	this.HSV_2 = 0.95;
+	this.color;
+	this.cacheColorMap = {};
+};
+
+ColorGenerator.prototype = {
+    getColor:function(key){
+    	if(this.cacheColorMap[key] !== undefined){
+    		return this.cacheColorMap[key];
+    	}
+    	else{
+    		this.cacheColorMap[key] = this.generateColor();
+    		return this.cacheColorMap[key];
+    	}
+    },
+    _hsvToRgb:function(h,s,v){
+        if (s == 0.0)
+            return [v, v, v];
+        i = parseInt(h * 6.0)
+        f = (h * 6.0) - i
+        p = v * (1.0 - s)
+        q = v * (1.0 - s * f)
+        t = v * (1.0 - s * (1.0 - f))
+        i = i % 6
+        if (i == 0) 
+            return [v, t, p]
+        if (i == 1) 
+            return [q, v, p]
+        if (i == 2) 
+            return [p, v, t]
+        if (i == 3)
+            return [p, q, v]
+        if (i == 4) 
+            return [t, p, v]
+        if (i == 5)
+            return [v, p, q]            	
+    },
+    generateColor:function(){
+        this.CURRENT_RATIO = this.CURRENT_RATIO+this.GOLDEN_RATIO;
+        this.CURRENT_RATIO = this.CURRENT_RATIO %= 1;
+        HSV_tuple = [this.CURRENT_RATIO, this.HSV_1, this.HSV_2]
+        RGB_tuple = this._hsvToRgb(HSV_tuple[0],HSV_tuple[1],HSV_tuple[2]);
+        function toRgb(v){
+        	return ""+parseInt(v*256)
+        }
+        return [toRgb(RGB_tuple[0]),toRgb(RGB_tuple[1]),toRgb(RGB_tuple[2])];
+        
+    }
+}
+
+
+
+
+
+/**
+ * GLOBAL YUI Shortcuts
+ */
+var YUC = YAHOO.util.Connect;
+var YUD = YAHOO.util.Dom;
+var YUE = YAHOO.util.Event;
+var YUQ = YAHOO.util.Selector.query;
+
+// defines if push state is enabled for this browser ?
+var push_state_enabled = Boolean(
+		window.history && window.history.pushState && window.history.replaceState
+		&& !(   /* disable for versions of iOS before version 4.3 (8F190) */
+				(/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent)
+				/* disable for the mercury iOS browser, or at least older versions of the webkit engine */
+				|| (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent)
+		)
+)
+
+/**
+ * Partial Ajax Implementation
+ * 
+ * @param url: defines url to make partial request
+ * @param container: defines id of container to input partial result
+ * @param s_call: success callback function that takes o as arg
+ *  o.tId
+ *  o.status
+ *  o.statusText
+ *  o.getResponseHeader[ ]
+ *  o.getAllResponseHeaders
+ *  o.responseText
+ *  o.responseXML
+ *  o.argument
+ * @param f_call: failure callback
+ * @param args arguments 
+ */
+function ypjax(url,container,s_call,f_call,args){
+	var method='GET';
+	if(args===undefined){
+		args=null;
+	}
+	
+	// Set special header for partial ajax == HTTP_X_PARTIAL_XHR
+	YUC.initHeader('X-PARTIAL-XHR',true);
+	
+	// wrapper of passed callback
+	var s_wrapper = (function(o){
+		return function(o){
+			YUD.get(container).innerHTML=o.responseText;
+			YUD.setStyle(container,'opacity','1.0');
+    		//execute the given original callback
+    		if (s_call !== undefined){
+    			s_call(o);
+    		}
+		}
+	})()	
+	YUD.setStyle(container,'opacity','0.3');
+	YUC.asyncRequest(method,url,{
+		success:s_wrapper,
+		failure:function(o){
+			//failure
+			window.location = url;
+		}
+	},args);
+	
+}
+
+/**
+ * tooltip activate
+ */
+var tooltip_activate = function(){
+    function toolTipsId(){
+        var ids = [];
+        var tts = YUQ('.tooltip');
+        for (var i = 0; i < tts.length; i++) {
+            // if element doesn't not have and id 
+        	//  autogenerate one for tooltip 
+            if (!tts[i].id){
+                tts[i].id='tt'+((i*100)+tts.length);
+            }
+            ids.push(tts[i].id);
+        }
+        return ids
+    };
+    var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
+        context: [[toolTipsId()],"tl","bl",null,[0,5]],
+        monitorresize:false,
+        xyoffset :[0,0],
+        autodismissdelay:300000,
+        hidedelay:5,
+        showdelay:20,
+    });
+}
+
+/**
+ * show more
+ */
+var show_more_event = function(){
+    YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
+        var el = e.target;
+        YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
+        YUD.setStyle(el.parentNode,'display','none');
+    });
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/public/js/yui.2.9.js	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,104 @@
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var b=arguments,g=null,e,c,f;for(e=0;e<b.length;e=e+1){f=(""+b[e]).split(".");g=YAHOO;for(c=(f[0]=="YAHOO")?1:0;c<f.length;c=c+1){g[f[c]]=g[f[c]]||{};g=g[f[c]];}}return g;};YAHOO.log=function(d,a,c){var b=YAHOO.widget.Logger;if(b&&b.log){return b.log(d,a,c);}else{return false;}};YAHOO.register=function(a,f,e){var k=YAHOO.env.modules,c,j,h,g,d;if(!k[a]){k[a]={versions:[],builds:[]};}c=k[a];j=e.version;h=e.build;g=YAHOO.env.listeners;c.name=a;c.version=j;c.build=h;c.versions.push(j);c.builds.push(h);c.mainClass=f;for(d=0;d<g.length;d=d+1){g[d](c);}if(f){f.VERSION=j;f.BUILD=h;}else{YAHOO.log("mainClass is undefined for module "+a,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(a){return YAHOO.env.modules[a]||null;};YAHOO.env.parseUA=function(d){var e=function(i){var j=0;return parseFloat(i.replace(/\./g,function(){return(j++==1)?"":".";}));},h=navigator,g={ie:0,opera:0,gecko:0,webkit:0,chrome:0,mobile:null,air:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,webos:0,caja:h&&h.cajaVersion,secure:false,os:null},c=d||(navigator&&navigator.userAgent),f=window&&window.location,b=f&&f.href,a;g.secure=b&&(b.toLowerCase().indexOf("https")===0);if(c){if((/windows|win32/i).test(c)){g.os="windows";}else{if((/macintosh/i).test(c)){g.os="macintosh";}else{if((/rhino/i).test(c)){g.os="rhino";}}}if((/KHTML/).test(c)){g.webkit=1;}a=c.match(/AppleWebKit\/([^\s]*)/);if(a&&a[1]){g.webkit=e(a[1]);if(/ Mobile\//.test(c)){g.mobile="Apple";a=c.match(/OS ([^\s]*)/);if(a&&a[1]){a=e(a[1].replace("_","."));}g.ios=a;g.ipad=g.ipod=g.iphone=0;a=c.match(/iPad|iPod|iPhone/);if(a&&a[0]){g[a[0].toLowerCase()]=g.ios;}}else{a=c.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);if(a){g.mobile=a[0];}if(/webOS/.test(c)){g.mobile="WebOS";a=c.match(/webOS\/([^\s]*);/);if(a&&a[1]){g.webos=e(a[1]);}}if(/ Android/.test(c)){g.mobile="Android";a=c.match(/Android ([^\s]*);/);if(a&&a[1]){g.android=e(a[1]);}}}a=c.match(/Chrome\/([^\s]*)/);if(a&&a[1]){g.chrome=e(a[1]);}else{a=c.match(/AdobeAIR\/([^\s]*)/);if(a){g.air=a[0];}}}if(!g.webkit){a=c.match(/Opera[\s\/]([^\s]*)/);if(a&&a[1]){g.opera=e(a[1]);a=c.match(/Version\/([^\s]*)/);if(a&&a[1]){g.opera=e(a[1]);}a=c.match(/Opera Mini[^;]*/);if(a){g.mobile=a[0];}}else{a=c.match(/MSIE\s([^;]*)/);if(a&&a[1]){g.ie=e(a[1]);}else{a=c.match(/Gecko\/([^\s]*)/);if(a){g.gecko=1;a=c.match(/rv:([^\s\)]*)/);if(a&&a[1]){g.gecko=e(a[1]);}}}}}}return g;};YAHOO.env.ua=YAHOO.env.parseUA();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var b=YAHOO_config.listener,a=YAHOO.env.listeners,d=true,c;if(b){for(c=0;c<a.length;c++){if(a[c]==b){d=false;break;}}if(d){a.push(b);}}}})();YAHOO.lang=YAHOO.lang||{};(function(){var f=YAHOO.lang,a=Object.prototype,c="[object Array]",h="[object Function]",i="[object Object]",b=[],g={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;","`":"&#x60;"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j<d.length;j=j+1){n=d[j];m=k[n];if(f.isFunction(m)&&m!=a[n]){l[n]=m;}}}:function(){},escapeHTML:function(j){return j.replace(/[&<>"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l<j.length;l=l+1){n[j[l]]=m[j[l]];}}else{for(o in m){if(k||!(o in n)){n[o]=m[o];}}f._IEEnumFix(n,m);}return n;},augmentProto:function(m,l){if(!l||!m){throw new Error("Augment failed, verify dependencies.");}var j=[m.prototype,l.prototype],k;for(k=2;k<arguments.length;k=k+1){j.push(arguments[k]);}f.augmentObject.apply(this,j);return m;},dump:function(j,p){var l,n,r=[],t="{...}",k="f(){...}",q=", ",m=" => ";if(!f.isObject(j)){return j+"";}else{if(j instanceof Date||("nodeType" in j&&"tagName" in j)){return j;}else{if(f.isFunction(j)){return k;}}}p=(f.isNumber(p))?p:3;if(f.isArray(j)){r.push("[");for(l=0,n=j.length;l<n;l=l+1){if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j;
+}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;m<j;m=m+1){f.augmentObject(n,k[m],true);}return n;},later:function(t,k,u,n,p){t=t||0;k=k||{};var l=u,s=n,q,j;if(f.isString(u)){l=k[u];}if(!l){throw new TypeError("method undefined");}if(!f.isUndefined(n)&&!f.isArray(s)){s=[n];}q=function(){l.apply(k,s||b);};j=(p)?setInterval(q,t):setTimeout(q,t);return{interval:p,cancel:function(){if(this.interval){clearInterval(j);}else{clearTimeout(j);}}};},isValue:function(j){return(f.isObject(j)||f.isString(j)||f.isNumber(j)||f.isBoolean(j));}};f.hasOwnProperty=(a.hasOwnProperty)?function(j,k){return j&&j.hasOwnProperty&&j.hasOwnProperty(k);}:function(j,k){return !f.isUndefined(j[k])&&j.constructor.prototype[k]!==j[k];};e.augmentObject(f,e,true);YAHOO.util.Lang=f;f.augment=f.augmentProto;YAHOO.augment=f.augmentProto;YAHOO.extend=f.extend;})();YAHOO.register("yahoo",YAHOO,{version:"2.9.0",build:"2800"});YAHOO.util.Get=function(){var m={},k=0,r=0,l=false,n=YAHOO.env.ua,s=YAHOO.lang,q,d,e,i=function(x,t,y){var u=y||window,z=u.document,A=z.createElement(x),v;for(v in t){if(t.hasOwnProperty(v)){A.setAttribute(v,t[v]);}}return A;},h=function(u,v,t){var w={id:"yui__dyn_"+(r++),type:"text/css",rel:"stylesheet",href:u};if(t){s.augmentObject(w,t);}return i("link",w,v);},p=function(u,v,t){var w={id:"yui__dyn_"+(r++),type:"text/javascript",src:u};if(t){s.augmentObject(w,t);}return i("script",w,v);},a=function(t,u){return{tId:t.tId,win:t.win,data:t.data,nodes:t.nodes,msg:u,purge:function(){d(this.tId);}};},b=function(t,w){var u=m[w],v=(s.isString(t))?u.win.document.getElementById(t):t;if(!v){q(w,"target node not found: "+t);}return v;},c=function(w){YAHOO.log("Finishing transaction "+w);var u=m[w],v,t;u.finished=true;if(u.aborted){v="transaction "+w+" was aborted";q(w,v);return;}if(u.onSuccess){t=u.scope||u.win;u.onSuccess.call(t,a(u));}},o=function(v){YAHOO.log("Timeout "+v,"info","get");var u=m[v],t;if(u.onTimeout){t=u.scope||u;u.onTimeout.call(t,a(u));}},f=function(v,A){YAHOO.log("_next: "+v+", loaded: "+A,"info","Get");var u=m[v],D=u.win,C=D.document,B=C.getElementsByTagName("head")[0],x,y,t,E,z;if(u.timer){u.timer.cancel();}if(u.aborted){y="transaction "+v+" was aborted";q(v,y);return;}if(A){u.url.shift();if(u.varName){u.varName.shift();}}else{u.url=(s.isString(u.url))?[u.url]:u.url;if(u.varName){u.varName=(s.isString(u.varName))?[u.varName]:u.varName;}}if(u.url.length===0){if(u.type==="script"&&n.webkit&&n.webkit<420&&!u.finalpass&&!u.varName){z=p(null,u.win,u.attributes);z.innerHTML='YAHOO.util.Get._finalize("'+v+'");';u.nodes.push(z);B.appendChild(z);}else{c(v);}return;}t=u.url[0];if(!t){u.url.shift();YAHOO.log("skipping empty url");return f(v);}YAHOO.log("attempting to load "+t,"info","Get");if(u.timeout){u.timer=s.later(u.timeout,u,o,v);}if(u.type==="script"){x=p(t,D,u.attributes);}else{x=h(t,D,u.attributes);}e(u.type,x,v,t,D,u.url.length);u.nodes.push(x);if(u.insertBefore){E=b(u.insertBefore,v);if(E){E.parentNode.insertBefore(x,E);}}else{B.appendChild(x);}YAHOO.log("Appending node: "+t,"info","Get");if((n.webkit||n.gecko)&&u.type==="css"){f(v,t);}},j=function(){if(l){return;}l=true;var t,u;for(t in m){if(m.hasOwnProperty(t)){u=m[t];if(u.autopurge&&u.finished){d(u.tId);delete m[t];}}}l=false;},g=function(u,t,v){var x="q"+(k++),w;v=v||{};if(k%YAHOO.util.Get.PURGE_THRESH===0){j();}m[x]=s.merge(v,{tId:x,type:u,url:t,finished:false,aborted:false,nodes:[]});w=m[x];w.win=w.win||window;w.scope=w.scope||w.win;w.autopurge=("autopurge" in w)?w.autopurge:(u==="script")?true:false;w.attributes=w.attributes||{};w.attributes.charset=v.charset||w.attributes.charset||"utf-8";s.later(0,w,f,x);return{tId:x};};e=function(H,z,x,u,D,E,G){var F=G||f,B,t,I,v,J,A,C,y;if(n.ie){z.onreadystatechange=function(){B=this.readyState;if("loaded"===B||"complete"===B){YAHOO.log(x+" onload "+u,"info","Get");z.onreadystatechange=null;F(x,u);}};}else{if(n.webkit){if(H==="script"){if(n.webkit>=420){z.addEventListener("load",function(){YAHOO.log(x+" DOM2 onload "+u,"info","Get");F(x,u);});}else{t=m[x];if(t.varName){v=YAHOO.util.Get.POLL_FREQ;YAHOO.log("Polling for "+t.varName[0]);t.maxattempts=YAHOO.util.Get.TIMEOUT/v;t.attempts=0;t._cache=t.varName[0].split(".");t.timer=s.later(v,t,function(w){I=this._cache;A=I.length;J=this.win;for(C=0;C<A;C=C+1){J=J[I[C]];if(!J){this.attempts++;if(this.attempts++>this.maxattempts){y="Over retry limit, giving up";t.timer.cancel();q(x,y);}else{YAHOO.log(I[C]+" failed, retrying");}return;}}YAHOO.log("Safari poll complete");t.timer.cancel();F(x,u);},null,true);}else{s.later(YAHOO.util.Get.POLL_FREQ,null,F,[x,u]);}}}}else{z.onload=function(){YAHOO.log(x+" onload "+u,"info","Get");F(x,u);};}}};q=function(w,v){YAHOO.log("get failure: "+v,"warn","Get");var u=m[w],t;if(u.onFailure){t=u.scope||u.win;u.onFailure.call(t,a(u,v));}};d=function(z){if(m[z]){var t=m[z],u=t.nodes,x=u.length,C=t.win.document,A=C.getElementsByTagName("head")[0],v,y,w,B;if(t.insertBefore){v=b(t.insertBefore,z);if(v){A=v.parentNode;}}for(y=0;y<x;y=y+1){w=u[y];if(w.clearAttributes){w.clearAttributes();}else{for(B in w){if(w.hasOwnProperty(B)){delete w[B];}}}A.removeChild(w);}t.nodes=[];}};return{POLL_FREQ:10,PURGE_THRESH:20,TIMEOUT:2000,_finalize:function(t){YAHOO.log(t+" finalized ","info","Get");s.later(0,null,c,t);},abort:function(u){var v=(s.isString(u))?u:u.tId,t=m[v];if(t){YAHOO.log("Aborting "+v,"info","Get");t.aborted=true;}},script:function(t,u){return g("script",t,u);},css:function(t,u){return g("css",t,u);}};}();YAHOO.register("get",YAHOO.util.Get,{version:"2.9.0",build:"2800"});(function(){var Y=YAHOO,util=Y.util,lang=Y.lang,env=Y.env,PROV="_provides",SUPER="_supersedes",REQ="expanded",AFTER="_after",VERSION="2.9.0";var YUI={dupsAllowed:{"yahoo":true,"get":true},info:{"root":VERSION+"/build/","base":"http://yui.yahooapis.com/"+VERSION+"/build/","comboBase":"http://yui.yahooapis.com/combo?","skin":{"defaultSkin":"sam","base":"assets/skins/","path":"skin.css","after":["reset","fonts","grids","base"],"rollup":3},dupsAllowed:["yahoo","get"],"moduleInfo":{"animation":{"type":"js","path":"animation/animation-min.js","requires":["dom","event"]},"autocomplete":{"type":"js","path":"autocomplete/autocomplete-min.js","requires":["dom","event","datasource"],"optional":["connection","animation"],"skinnable":true},"base":{"type":"css","path":"base/base-min.css","after":["reset","fonts","grids"]},"button":{"type":"js","path":"button/button-min.js","requires":["element"],"optional":["menu"],"skinnable":true},"calendar":{"type":"js","path":"calendar/calendar-min.js","requires":["event","dom"],supersedes:["datemath"],"skinnable":true},"carousel":{"type":"js","path":"carousel/carousel-min.js","requires":["element"],"optional":["animation"],"skinnable":true},"charts":{"type":"js","path":"charts/charts-min.js","requires":["element","json","datasource","swf"]},"colorpicker":{"type":"js","path":"colorpicker/colorpicker-min.js","requires":["slider","element"],"optional":["animation"],"skinnable":true},"connection":{"type":"js","path":"connection/connection-min.js","requires":["event"],"supersedes":["connectioncore"]},"connectioncore":{"type":"js","path":"connection/connection_core-min.js","requires":["event"],"pkg":"connection"},"container":{"type":"js","path":"container/container-min.js","requires":["dom","event"],"optional":["dragdrop","animation","connection"],"supersedes":["containercore"],"skinnable":true},"containercore":{"type":"js","path":"container/container_core-min.js","requires":["dom","event"],"pkg":"container"},"cookie":{"type":"js","path":"cookie/cookie-min.js","requires":["yahoo"]},"datasource":{"type":"js","path":"datasource/datasource-min.js","requires":["event"],"optional":["connection"]},"datatable":{"type":"js","path":"datatable/datatable-min.js","requires":["element","datasource"],"optional":["calendar","dragdrop","paginator"],"skinnable":true},datemath:{"type":"js","path":"datemath/datemath-min.js","requires":["yahoo"]},"dom":{"type":"js","path":"dom/dom-min.js","requires":["yahoo"]},"dragdrop":{"type":"js","path":"dragdrop/dragdrop-min.js","requires":["dom","event"]},"editor":{"type":"js","path":"editor/editor-min.js","requires":["menu","element","button"],"optional":["animation","dragdrop"],"supersedes":["simpleeditor"],"skinnable":true},"element":{"type":"js","path":"element/element-min.js","requires":["dom","event"],"optional":["event-mouseenter","event-delegate"]},"element-delegate":{"type":"js","path":"element-delegate/element-delegate-min.js","requires":["element"]},"event":{"type":"js","path":"event/event-min.js","requires":["yahoo"]},"event-simulate":{"type":"js","path":"event-simulate/event-simulate-min.js","requires":["event"]},"event-delegate":{"type":"js","path":"event-delegate/event-delegate-min.js","requires":["event"],"optional":["selector"]},"event-mouseenter":{"type":"js","path":"event-mouseenter/event-mouseenter-min.js","requires":["dom","event"]},"fonts":{"type":"css","path":"fonts/fonts-min.css"},"get":{"type":"js","path":"get/get-min.js","requires":["yahoo"]},"grids":{"type":"css","path":"grids/grids-min.css","requires":["fonts"],"optional":["reset"]},"history":{"type":"js","path":"history/history-min.js","requires":["event"]},"imagecropper":{"type":"js","path":"imagecropper/imagecropper-min.js","requires":["dragdrop","element","resize"],"skinnable":true},"imageloader":{"type":"js","path":"imageloader/imageloader-min.js","requires":["event","dom"]},"json":{"type":"js","path":"json/json-min.js","requires":["yahoo"]},"layout":{"type":"js","path":"layout/layout-min.js","requires":["element"],"optional":["animation","dragdrop","resize","selector"],"skinnable":true},"logger":{"type":"js","path":"logger/logger-min.js","requires":["event","dom"],"optional":["dragdrop"],"skinnable":true},"menu":{"type":"js","path":"menu/menu-min.js","requires":["containercore"],"skinnable":true},"paginator":{"type":"js","path":"paginator/paginator-min.js","requires":["element"],"skinnable":true},"profiler":{"type":"js","path":"profiler/profiler-min.js","requires":["yahoo"]},"profilerviewer":{"type":"js","path":"profilerviewer/profilerviewer-min.js","requires":["profiler","yuiloader","element"],"skinnable":true},"progressbar":{"type":"js","path":"progressbar/progressbar-min.js","requires":["element"],"optional":["animation"],"skinnable":true},"reset":{"type":"css","path":"reset/reset-min.css"},"reset-fonts-grids":{"type":"css","path":"reset-fonts-grids/reset-fonts-grids.css","supersedes":["reset","fonts","grids","reset-fonts"],"rollup":4},"reset-fonts":{"type":"css","path":"reset-fonts/reset-fonts.css","supersedes":["reset","fonts"],"rollup":2},"resize":{"type":"js","path":"resize/resize-min.js","requires":["dragdrop","element"],"optional":["animation"],"skinnable":true},"selector":{"type":"js","path":"selector/selector-min.js","requires":["yahoo","dom"]},"simpleeditor":{"type":"js","path":"editor/simpleeditor-min.js","requires":["element"],"optional":["containercore","menu","button","animation","dragdrop"],"skinnable":true,"pkg":"editor"},"slider":{"type":"js","path":"slider/slider-min.js","requires":["dragdrop"],"optional":["animation"],"skinnable":true},"storage":{"type":"js","path":"storage/storage-min.js","requires":["yahoo","event","cookie"],"optional":["swfstore"]},"stylesheet":{"type":"js","path":"stylesheet/stylesheet-min.js","requires":["yahoo"]},"swf":{"type":"js","path":"swf/swf-min.js","requires":["element"],"supersedes":["swfdetect"]},"swfdetect":{"type":"js","path":"swfdetect/swfdetect-min.js","requires":["yahoo"]},"swfstore":{"type":"js","path":"swfstore/swfstore-min.js","requires":["element","cookie","swf"]},"tabview":{"type":"js","path":"tabview/tabview-min.js","requires":["element"],"optional":["connection"],"skinnable":true},"treeview":{"type":"js","path":"treeview/treeview-min.js","requires":["event","dom"],"optional":["json","animation","calendar"],"skinnable":true},"uploader":{"type":"js","path":"uploader/uploader-min.js","requires":["element"]},"utilities":{"type":"js","path":"utilities/utilities.js","supersedes":["yahoo","event","dragdrop","animation","dom","connection","element","yahoo-dom-event","get","yuiloader","yuiloader-dom-event"],"rollup":8},"yahoo":{"type":"js","path":"yahoo/yahoo-min.js"},"yahoo-dom-event":{"type":"js","path":"yahoo-dom-event/yahoo-dom-event.js","supersedes":["yahoo","event","dom"],"rollup":3},"yuiloader":{"type":"js","path":"yuiloader/yuiloader-min.js","supersedes":["yahoo","get"]},"yuiloader-dom-event":{"type":"js","path":"yuiloader-dom-event/yuiloader-dom-event.js","supersedes":["yahoo","dom","event","get","yuiloader","yahoo-dom-event"],"rollup":5},"yuitest":{"type":"js","path":"yuitest/yuitest-min.js","requires":["logger"],"optional":["event-simulate"],"skinnable":true}}},ObjectUtil:{appendArray:function(o,a){if(a){for(var i=0;
+i<a.length;i=i+1){o[a[i]]=true;}}},keys:function(o,ordered){var a=[],i;for(i in o){if(lang.hasOwnProperty(o,i)){a.push(i);}}return a;}},ArrayUtil:{appendArray:function(a1,a2){Array.prototype.push.apply(a1,a2);},indexOf:function(a,val){for(var i=0;i<a.length;i=i+1){if(a[i]===val){return i;}}return -1;},toObject:function(a){var o={};for(var i=0;i<a.length;i=i+1){o[a[i]]=true;}return o;},uniq:function(a){return YUI.ObjectUtil.keys(YUI.ArrayUtil.toObject(a));}}};YAHOO.util.YUILoader=function(o){this._internalCallback=null;this._useYahooListener=false;this.onSuccess=null;this.onFailure=Y.log;this.onProgress=null;this.onTimeout=null;this.scope=this;this.data=null;this.insertBefore=null;this.charset=null;this.varName=null;this.base=YUI.info.base;this.comboBase=YUI.info.comboBase;this.combine=false;this.root=YUI.info.root;this.timeout=0;this.ignore=null;this.force=null;this.allowRollup=true;this.filter=null;this.required={};this.moduleInfo=lang.merge(YUI.info.moduleInfo);this.rollups=null;this.loadOptional=false;this.sorted=[];this.loaded={};this.dirty=true;this.inserted={};var self=this;env.listeners.push(function(m){if(self._useYahooListener){self.loadNext(m.name);}});this.skin=lang.merge(YUI.info.skin);this._config(o);};Y.util.YUILoader.prototype={FILTERS:{RAW:{"searchExp":"-min\\.js","replaceStr":".js"},DEBUG:{"searchExp":"-min\\.js","replaceStr":"-debug.js"}},SKIN_PREFIX:"skin-",_config:function(o){if(o){for(var i in o){if(lang.hasOwnProperty(o,i)){if(i=="require"){this.require(o[i]);}else{this[i]=o[i];}}}}var f=this.filter;if(lang.isString(f)){f=f.toUpperCase();if(f==="DEBUG"){this.require("logger");}if(!Y.widget.LogWriter){Y.widget.LogWriter=function(){return Y;};}this.filter=this.FILTERS[f];}},addModule:function(o){if(!o||!o.name||!o.type||(!o.path&&!o.fullpath)){return false;}o.ext=("ext" in o)?o.ext:true;o.requires=o.requires||[];this.moduleInfo[o.name]=o;this.dirty=true;return true;},require:function(what){var a=(typeof what==="string")?arguments:what;this.dirty=true;YUI.ObjectUtil.appendArray(this.required,a);},_addSkin:function(skin,mod){var name=this.formatSkin(skin),info=this.moduleInfo,sinf=this.skin,ext=info[mod]&&info[mod].ext;if(!info[name]){this.addModule({"name":name,"type":"css","path":sinf.base+skin+"/"+sinf.path,"after":sinf.after,"rollup":sinf.rollup,"ext":ext});}if(mod){name=this.formatSkin(skin,mod);if(!info[name]){var mdef=info[mod],pkg=mdef.pkg||mod;this.addModule({"name":name,"type":"css","after":sinf.after,"path":pkg+"/"+sinf.base+skin+"/"+mod+".css","ext":ext});}}return name;},getRequires:function(mod){if(!mod){return[];}if(!this.dirty&&mod.expanded){return mod.expanded;}mod.requires=mod.requires||[];var i,d=[],r=mod.requires,o=mod.optional,info=this.moduleInfo,m;for(i=0;i<r.length;i=i+1){d.push(r[i]);m=info[r[i]];YUI.ArrayUtil.appendArray(d,this.getRequires(m));}if(o&&this.loadOptional){for(i=0;i<o.length;i=i+1){d.push(o[i]);YUI.ArrayUtil.appendArray(d,this.getRequires(info[o[i]]));}}mod.expanded=YUI.ArrayUtil.uniq(d);return mod.expanded;},getProvides:function(name,notMe){var addMe=!(notMe),ckey=(addMe)?PROV:SUPER,m=this.moduleInfo[name],o={};if(!m){return o;}if(m[ckey]){return m[ckey];}var s=m.supersedes,done={},me=this;var add=function(mm){if(!done[mm]){done[mm]=true;lang.augmentObject(o,me.getProvides(mm));}};if(s){for(var i=0;i<s.length;i=i+1){add(s[i]);}}m[SUPER]=o;m[PROV]=lang.merge(o);m[PROV][name]=true;return m[ckey];},calculate:function(o){if(o||this.dirty){this._config(o);this._setup();this._explode();if(this.allowRollup){this._rollup();}this._reduce();this._sort();this.dirty=false;}},_setup:function(){var info=this.moduleInfo,name,i,j;for(name in info){if(lang.hasOwnProperty(info,name)){var m=info[name];if(m&&m.skinnable){var o=this.skin.overrides,smod;if(o&&o[name]){for(i=0;i<o[name].length;i=i+1){smod=this._addSkin(o[name][i],name);}}else{smod=this._addSkin(this.skin.defaultSkin,name);}if(YUI.ArrayUtil.indexOf(m.requires,smod)==-1){m.requires.push(smod);}}}}var l=lang.merge(this.inserted);if(!this._sandbox){l=lang.merge(l,env.modules);}if(this.ignore){YUI.ObjectUtil.appendArray(l,this.ignore);}if(this.force){for(i=0;i<this.force.length;i=i+1){if(this.force[i] in l){delete l[this.force[i]];}}}for(j in l){if(lang.hasOwnProperty(l,j)){lang.augmentObject(l,this.getProvides(j));}}this.loaded=l;},_explode:function(){var r=this.required,i,mod;for(i in r){if(lang.hasOwnProperty(r,i)){mod=this.moduleInfo[i];if(mod){var req=this.getRequires(mod);if(req){YUI.ObjectUtil.appendArray(r,req);}}}}},_skin:function(){},formatSkin:function(skin,mod){var s=this.SKIN_PREFIX+skin;if(mod){s=s+"-"+mod;}return s;},parseSkin:function(mod){if(mod.indexOf(this.SKIN_PREFIX)===0){var a=mod.split("-");return{skin:a[1],module:a[2]};}return null;},_rollup:function(){var i,j,m,s,rollups={},r=this.required,roll,info=this.moduleInfo;if(this.dirty||!this.rollups){for(i in info){if(lang.hasOwnProperty(info,i)){m=info[i];if(m&&m.rollup){rollups[i]=m;}}}this.rollups=rollups;}for(;;){var rolled=false;for(i in rollups){if(!r[i]&&!this.loaded[i]){m=info[i];s=m.supersedes;roll=false;if(!m.rollup){continue;}var skin=(m.ext)?false:this.parseSkin(i),c=0;if(skin){for(j in r){if(lang.hasOwnProperty(r,j)){if(i!==j&&this.parseSkin(j)){c++;roll=(c>=m.rollup);if(roll){break;}}}}}else{for(j=0;j<s.length;j=j+1){if(this.loaded[s[j]]&&(!YUI.dupsAllowed[s[j]])){roll=false;break;}else{if(r[s[j]]){c++;roll=(c>=m.rollup);if(roll){break;}}}}}if(roll){r[i]=true;rolled=true;this.getRequires(m);}}}if(!rolled){break;}}},_reduce:function(){var i,j,s,m,r=this.required;for(i in r){if(i in this.loaded){delete r[i];}else{var skinDef=this.parseSkin(i);if(skinDef){if(!skinDef.module){var skin_pre=this.SKIN_PREFIX+skinDef.skin;for(j in r){if(lang.hasOwnProperty(r,j)){m=this.moduleInfo[j];var ext=m&&m.ext;if(!ext&&j!==i&&j.indexOf(skin_pre)>-1){delete r[j];}}}}}else{m=this.moduleInfo[i];s=m&&m.supersedes;if(s){for(j=0;j<s.length;j=j+1){if(s[j] in r){delete r[s[j]];}}}}}}},_onFailure:function(msg){YAHOO.log("Failure","info","loader");
+var f=this.onFailure;if(f){f.call(this.scope,{msg:"failure: "+msg,data:this.data,success:false});}},_onTimeout:function(){YAHOO.log("Timeout","info","loader");var f=this.onTimeout;if(f){f.call(this.scope,{msg:"timeout",data:this.data,success:false});}},_sort:function(){var s=[],info=this.moduleInfo,loaded=this.loaded,checkOptional=!this.loadOptional,me=this;var requires=function(aa,bb){var mm=info[aa];if(loaded[bb]||!mm){return false;}var ii,rr=mm.expanded,after=mm.after,other=info[bb],optional=mm.optional;if(rr&&YUI.ArrayUtil.indexOf(rr,bb)>-1){return true;}if(after&&YUI.ArrayUtil.indexOf(after,bb)>-1){return true;}if(checkOptional&&optional&&YUI.ArrayUtil.indexOf(optional,bb)>-1){return true;}var ss=info[bb]&&info[bb].supersedes;if(ss){for(ii=0;ii<ss.length;ii=ii+1){if(requires(aa,ss[ii])){return true;}}}if(mm.ext&&mm.type=="css"&&!other.ext&&other.type=="css"){return true;}return false;};for(var i in this.required){if(lang.hasOwnProperty(this.required,i)){s.push(i);}}var p=0;for(;;){var l=s.length,a,b,j,k,moved=false;for(j=p;j<l;j=j+1){a=s[j];for(k=j+1;k<l;k=k+1){if(requires(a,s[k])){b=s.splice(k,1);s.splice(j,0,b[0]);moved=true;break;}}if(moved){break;}else{p=p+1;}}if(!moved){break;}}this.sorted=s;},toString:function(){var o={type:"YUILoader",base:this.base,filter:this.filter,required:this.required,loaded:this.loaded,inserted:this.inserted};lang.dump(o,1);},_combine:function(){this._combining=[];var self=this,s=this.sorted,len=s.length,js=this.comboBase,css=this.comboBase,target,startLen=js.length,i,m,type=this.loadType;YAHOO.log("type "+type);for(i=0;i<len;i=i+1){m=this.moduleInfo[s[i]];if(m&&!m.ext&&(!type||type===m.type)){target=this.root+m.path;target+="&";if(m.type=="js"){js+=target;}else{css+=target;}this._combining.push(s[i]);}}if(this._combining.length){YAHOO.log("Attempting to combine: "+this._combining,"info","loader");var callback=function(o){var c=this._combining,len=c.length,i,m;for(i=0;i<len;i=i+1){this.inserted[c[i]]=true;}this.loadNext(o.data);},loadScript=function(){if(js.length>startLen){YAHOO.util.Get.script(self._filter(js),{data:self._loading,onSuccess:callback,onFailure:self._onFailure,onTimeout:self._onTimeout,insertBefore:self.insertBefore,charset:self.charset,timeout:self.timeout,scope:self});}else{this.loadNext();}};if(css.length>startLen){YAHOO.util.Get.css(this._filter(css),{data:this._loading,onSuccess:loadScript,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,scope:self});}else{loadScript();}return;}else{this.loadNext(this._loading);}},insert:function(o,type){this.calculate(o);this._loading=true;this.loadType=type;if(this.combine){return this._combine();}if(!type){var self=this;this._internalCallback=function(){self._internalCallback=null;self.insert(null,"js");};this.insert(null,"css");return;}this.loadNext();},sandbox:function(o,type){var self=this,success=function(o){var idx=o.argument[0],name=o.argument[2];self._scriptText[idx]=o.responseText;if(self.onProgress){self.onProgress.call(self.scope,{name:name,scriptText:o.responseText,xhrResponse:o,data:self.data});}self._loadCount++;if(self._loadCount>=self._stopCount){var v=self.varName||"YAHOO";var t="(function() {\n";var b="\nreturn "+v+";\n})();";var ref=eval(t+self._scriptText.join("\n")+b);self._pushEvents(ref);if(ref){self.onSuccess.call(self.scope,{reference:ref,data:self.data});}else{self._onFailure.call(self.varName+" reference failure");}}},failure=function(o){self.onFailure.call(self.scope,{msg:"XHR failure",xhrResponse:o,data:self.data});};self._config(o);if(!self.onSuccess){throw new Error("You must supply an onSuccess handler for your sandbox");}self._sandbox=true;if(!type||type!=="js"){self._internalCallback=function(){self._internalCallback=null;self.sandbox(null,"js");};self.insert(null,"css");return;}if(!util.Connect){var ld=new YAHOO.util.YUILoader();ld.insert({base:self.base,filter:self.filter,require:"connection",insertBefore:self.insertBefore,charset:self.charset,onSuccess:function(){self.sandbox(null,"js");},scope:self},"js");return;}self._scriptText=[];self._loadCount=0;self._stopCount=self.sorted.length;self._xhr=[];self.calculate();var s=self.sorted,l=s.length,i,m,url;for(i=0;i<l;i=i+1){m=self.moduleInfo[s[i]];if(!m){self._onFailure("undefined module "+m);for(var j=0;j<self._xhr.length;j=j+1){self._xhr[j].abort();}return;}if(m.type!=="js"){self._loadCount++;continue;}url=m.fullpath;url=(url)?self._filter(url):self._url(m.path);var xhrData={success:success,failure:failure,scope:self,argument:[i,url,s[i]]};self._xhr.push(util.Connect.asyncRequest("GET",url,xhrData));}},loadNext:function(mname){if(!this._loading){return;}var self=this,donext=function(o){self.loadNext(o.data);},successfn,s=this.sorted,len=s.length,i,fn,m,url;if(mname){if(mname!==this._loading){return;}this.inserted[mname]=true;if(this.onProgress){this.onProgress.call(this.scope,{name:mname,data:this.data});}}for(i=0;i<len;i=i+1){if(s[i] in this.inserted){continue;}if(s[i]===this._loading){return;}m=this.moduleInfo[s[i]];if(!m){this.onFailure.call(this.scope,{msg:"undefined module "+m,data:this.data});return;}if(!this.loadType||this.loadType===m.type){successfn=donext;this._loading=s[i];fn=(m.type==="css")?util.Get.css:util.Get.script;url=m.fullpath;url=(url)?this._filter(url):this._url(m.path);if(env.ua.webkit&&env.ua.webkit<420&&m.type==="js"&&!m.varName){successfn=null;this._useYahooListener=true;}fn(url,{data:s[i],onSuccess:successfn,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,varName:m.varName,scope:self});return;}}this._loading=null;if(this._internalCallback){var f=this._internalCallback;this._internalCallback=null;f.call(this);}else{if(this.onSuccess){this._pushEvents();this.onSuccess.call(this.scope,{data:this.data});}}},_pushEvents:function(ref){var r=ref||YAHOO;if(r.util&&r.util.Event){r.util.Event._load();}},_filter:function(str){var f=this.filter;return(f)?str.replace(new RegExp(f.searchExp,"g"),f.replaceStr):str;
+},_url:function(path){return this._filter((this.base||"")+path);}};})();YAHOO.register("yuiloader",YAHOO.util.YUILoader,{version:"2.9.0",build:"2800"});(function(){YAHOO.env._id_counter=YAHOO.env._id_counter||0;var e=YAHOO.util,k=YAHOO.lang,L=YAHOO.env.ua,a=YAHOO.lang.trim,B={},F={},m=/^t(?:able|d|h)$/i,w=/color$/i,j=window.document,v=j.documentElement,C="ownerDocument",M="defaultView",U="documentElement",S="compatMode",z="offsetLeft",o="offsetTop",T="offsetParent",x="parentNode",K="nodeType",c="tagName",n="scrollLeft",H="scrollTop",p="getBoundingClientRect",V="getComputedStyle",y="currentStyle",l="CSS1Compat",A="BackCompat",E="class",f="className",i="",b=" ",R="(?:^|\\s)",J="(?= |$)",t="g",O="position",D="fixed",u="relative",I="left",N="top",Q="medium",P="borderLeftWidth",q="borderTopWidth",d=L.opera,h=L.webkit,g=L.gecko,s=L.ie;e.Dom={CUSTOM_ATTRIBUTES:(!v.hasAttribute)?{"for":"htmlFor","class":f}:{"htmlFor":"for","className":E},DOT_ATTRIBUTES:{checked:true},get:function(aa){var ac,X,ab,Z,W,G,Y=null;if(aa){if(typeof aa=="string"||typeof aa=="number"){ac=aa+"";aa=j.getElementById(aa);G=(aa)?aa.attributes:null;if(aa&&G&&G.id&&G.id.value===ac){return aa;}else{if(aa&&j.all){aa=null;X=j.all[ac];if(X&&X.length){for(Z=0,W=X.length;Z<W;++Z){if(X[Z].id===ac){return X[Z];}}}}}}else{if(e.Element&&aa instanceof e.Element){aa=aa.get("element");}else{if(!aa.nodeType&&"length" in aa){ab=[];for(Z=0,W=aa.length;Z<W;++Z){ab[ab.length]=e.Dom.get(aa[Z]);}aa=ab;}}}Y=aa;}return Y;},getComputedStyle:function(G,W){if(window[V]){return G[C][M][V](G,null)[W];}else{if(G[y]){return e.Dom.IE_ComputedStyle.get(G,W);}}},getStyle:function(G,W){return e.Dom.batch(G,e.Dom._getStyle,W);},_getStyle:function(){if(window[V]){return function(G,Y){Y=(Y==="float")?Y="cssFloat":e.Dom._toCamel(Y);var X=G.style[Y],W;if(!X){W=G[C][M][V](G,null);if(W){X=W[Y];}}return X;};}else{if(v[y]){return function(G,Y){var X;switch(Y){case"opacity":X=100;try{X=G.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(Z){try{X=G.filters("alpha").opacity;}catch(W){}}return X/100;case"float":Y="styleFloat";default:Y=e.Dom._toCamel(Y);X=G[y]?G[y][Y]:null;return(G.style[Y]||X);}};}}}(),setStyle:function(G,W,X){e.Dom.batch(G,e.Dom._setStyle,{prop:W,val:X});},_setStyle:function(){if(!window.getComputedStyle&&j.documentElement.currentStyle){return function(W,G){var X=e.Dom._toCamel(G.prop),Y=G.val;if(W){switch(X){case"opacity":if(Y===""||Y===null||Y===1){W.style.removeAttribute("filter");}else{if(k.isString(W.style.filter)){W.style.filter="alpha(opacity="+Y*100+")";if(!W[y]||!W[y].hasLayout){W.style.zoom=1;}}}break;case"float":X="styleFloat";default:W.style[X]=Y;}}else{}};}else{return function(W,G){var X=e.Dom._toCamel(G.prop),Y=G.val;if(W){if(X=="float"){X="cssFloat";}W.style[X]=Y;}else{}};}}(),getXY:function(G){return e.Dom.batch(G,e.Dom._getXY);},_canPosition:function(G){return(e.Dom._getStyle(G,"display")!=="none"&&e.Dom._inDoc(G));},_getXY:function(W){var X,G,Z,ab,Y,aa,ac=Math.round,ad=false;if(e.Dom._canPosition(W)){Z=W[p]();ab=W[C];X=e.Dom.getDocumentScrollLeft(ab);G=e.Dom.getDocumentScrollTop(ab);ad=[Z[I],Z[N]];if(Y||aa){ad[0]-=aa;ad[1]-=Y;}if((G||X)){ad[0]+=X;ad[1]+=G;}ad[0]=ac(ad[0]);ad[1]=ac(ad[1]);}else{}return ad;},getX:function(G){var W=function(X){return e.Dom.getXY(X)[0];};return e.Dom.batch(G,W,e.Dom,true);},getY:function(G){var W=function(X){return e.Dom.getXY(X)[1];};return e.Dom.batch(G,W,e.Dom,true);},setXY:function(G,X,W){e.Dom.batch(G,e.Dom._setXY,{pos:X,noRetry:W});},_setXY:function(G,Z){var aa=e.Dom._getStyle(G,O),Y=e.Dom.setStyle,ad=Z.pos,W=Z.noRetry,ab=[parseInt(e.Dom.getComputedStyle(G,I),10),parseInt(e.Dom.getComputedStyle(G,N),10)],ac,X;ac=e.Dom._getXY(G);if(!ad||ac===false){return false;}if(aa=="static"){aa=u;Y(G,O,aa);}if(isNaN(ab[0])){ab[0]=(aa==u)?0:G[z];}if(isNaN(ab[1])){ab[1]=(aa==u)?0:G[o];}if(ad[0]!==null){Y(G,I,ad[0]-ac[0]+ab[0]+"px");}if(ad[1]!==null){Y(G,N,ad[1]-ac[1]+ab[1]+"px");}if(!W){X=e.Dom._getXY(G);if((ad[0]!==null&&X[0]!=ad[0])||(ad[1]!==null&&X[1]!=ad[1])){e.Dom._setXY(G,{pos:ad,noRetry:true});}}},setX:function(W,G){e.Dom.setXY(W,[G,null]);},setY:function(G,W){e.Dom.setXY(G,[null,W]);},getRegion:function(G){var W=function(X){var Y=false;if(e.Dom._canPosition(X)){Y=e.Region.getRegion(X);}else{}return Y;};return e.Dom.batch(G,W,e.Dom,true);},getClientWidth:function(){return e.Dom.getViewportWidth();},getClientHeight:function(){return e.Dom.getViewportHeight();},getElementsByClassName:function(ab,af,ac,ae,X,ad){af=af||"*";ac=(ac)?e.Dom.get(ac):null||j;if(!ac){return[];}var W=[],G=ac.getElementsByTagName(af),Z=e.Dom.hasClass;for(var Y=0,aa=G.length;Y<aa;++Y){if(Z(G[Y],ab)){W[W.length]=G[Y];}}if(ae){e.Dom.batch(W,ae,X,ad);}return W;},hasClass:function(W,G){return e.Dom.batch(W,e.Dom._hasClass,G);},_hasClass:function(X,W){var G=false,Y;if(X&&W){Y=e.Dom._getAttribute(X,f)||i;if(Y){Y=Y.replace(/\s+/g,b);}if(W.exec){G=W.test(Y);}else{G=W&&(b+Y+b).indexOf(b+W+b)>-1;}}else{}return G;},addClass:function(W,G){return e.Dom.batch(W,e.Dom._addClass,G);},_addClass:function(X,W){var G=false,Y;if(X&&W){Y=e.Dom._getAttribute(X,f)||i;if(!e.Dom._hasClass(X,W)){e.Dom.setAttribute(X,f,a(Y+b+W));G=true;}}else{}return G;},removeClass:function(W,G){return e.Dom.batch(W,e.Dom._removeClass,G);},_removeClass:function(Y,X){var W=false,aa,Z,G;if(Y&&X){aa=e.Dom._getAttribute(Y,f)||i;e.Dom.setAttribute(Y,f,aa.replace(e.Dom._getClassRegex(X),i));Z=e.Dom._getAttribute(Y,f);if(aa!==Z){e.Dom.setAttribute(Y,f,a(Z));W=true;if(e.Dom._getAttribute(Y,f)===""){G=(Y.hasAttribute&&Y.hasAttribute(E))?E:f;Y.removeAttribute(G);}}}else{}return W;},replaceClass:function(X,W,G){return e.Dom.batch(X,e.Dom._replaceClass,{from:W,to:G});},_replaceClass:function(Y,X){var W,ab,aa,G=false,Z;if(Y&&X){ab=X.from;aa=X.to;if(!aa){G=false;}else{if(!ab){G=e.Dom._addClass(Y,X.to);}else{if(ab!==aa){Z=e.Dom._getAttribute(Y,f)||i;W=(b+Z.replace(e.Dom._getClassRegex(ab),b+aa).replace(/\s+/g,b)).split(e.Dom._getClassRegex(aa));W.splice(1,0,b+aa);e.Dom.setAttribute(Y,f,a(W.join(i)));G=true;}}}}else{}return G;},generateId:function(G,X){X=X||"yui-gen";var W=function(Y){if(Y&&Y.id){return Y.id;}var Z=X+YAHOO.env._id_counter++;
+if(Y){if(Y[C]&&Y[C].getElementById(Z)){return e.Dom.generateId(Y,Z+X);}Y.id=Z;}return Z;};return e.Dom.batch(G,W,e.Dom,true)||W.apply(e.Dom,arguments);},isAncestor:function(W,X){W=e.Dom.get(W);X=e.Dom.get(X);var G=false;if((W&&X)&&(W[K]&&X[K])){if(W.contains&&W!==X){G=W.contains(X);}else{if(W.compareDocumentPosition){G=!!(W.compareDocumentPosition(X)&16);}}}else{}return G;},inDocument:function(G,W){return e.Dom._inDoc(e.Dom.get(G),W);},_inDoc:function(W,X){var G=false;if(W&&W[c]){X=X||W[C];G=e.Dom.isAncestor(X[U],W);}else{}return G;},getElementsBy:function(W,af,ab,ad,X,ac,ae){af=af||"*";ab=(ab)?e.Dom.get(ab):null||j;var aa=(ae)?null:[],G;if(ab){G=ab.getElementsByTagName(af);for(var Y=0,Z=G.length;Y<Z;++Y){if(W(G[Y])){if(ae){aa=G[Y];break;}else{aa[aa.length]=G[Y];}}}if(ad){e.Dom.batch(aa,ad,X,ac);}}return aa;},getElementBy:function(X,G,W){return e.Dom.getElementsBy(X,G,W,null,null,null,true);},batch:function(X,ab,aa,Z){var Y=[],W=(Z)?aa:null;X=(X&&(X[c]||X.item))?X:e.Dom.get(X);if(X&&ab){if(X[c]||X.length===undefined){return ab.call(W,X,aa);}for(var G=0;G<X.length;++G){Y[Y.length]=ab.call(W||X[G],X[G],aa);}}else{return false;}return Y;},getDocumentHeight:function(){var W=(j[S]!=l||h)?j.body.scrollHeight:v.scrollHeight,G=Math.max(W,e.Dom.getViewportHeight());return G;},getDocumentWidth:function(){var W=(j[S]!=l||h)?j.body.scrollWidth:v.scrollWidth,G=Math.max(W,e.Dom.getViewportWidth());return G;},getViewportHeight:function(){var G=self.innerHeight,W=j[S];if((W||s)&&!d){G=(W==l)?v.clientHeight:j.body.clientHeight;}return G;},getViewportWidth:function(){var G=self.innerWidth,W=j[S];if(W||s){G=(W==l)?v.clientWidth:j.body.clientWidth;}return G;},getAncestorBy:function(G,W){while((G=G[x])){if(e.Dom._testElement(G,W)){return G;}}return null;},getAncestorByClassName:function(W,G){W=e.Dom.get(W);if(!W){return null;}var X=function(Y){return e.Dom.hasClass(Y,G);};return e.Dom.getAncestorBy(W,X);},getAncestorByTagName:function(W,G){W=e.Dom.get(W);if(!W){return null;}var X=function(Y){return Y[c]&&Y[c].toUpperCase()==G.toUpperCase();};return e.Dom.getAncestorBy(W,X);},getPreviousSiblingBy:function(G,W){while(G){G=G.previousSibling;if(e.Dom._testElement(G,W)){return G;}}return null;},getPreviousSibling:function(G){G=e.Dom.get(G);if(!G){return null;}return e.Dom.getPreviousSiblingBy(G);},getNextSiblingBy:function(G,W){while(G){G=G.nextSibling;if(e.Dom._testElement(G,W)){return G;}}return null;},getNextSibling:function(G){G=e.Dom.get(G);if(!G){return null;}return e.Dom.getNextSiblingBy(G);},getFirstChildBy:function(G,X){var W=(e.Dom._testElement(G.firstChild,X))?G.firstChild:null;return W||e.Dom.getNextSiblingBy(G.firstChild,X);},getFirstChild:function(G,W){G=e.Dom.get(G);if(!G){return null;}return e.Dom.getFirstChildBy(G);},getLastChildBy:function(G,X){if(!G){return null;}var W=(e.Dom._testElement(G.lastChild,X))?G.lastChild:null;return W||e.Dom.getPreviousSiblingBy(G.lastChild,X);},getLastChild:function(G){G=e.Dom.get(G);return e.Dom.getLastChildBy(G);},getChildrenBy:function(W,Y){var X=e.Dom.getFirstChildBy(W,Y),G=X?[X]:[];e.Dom.getNextSiblingBy(X,function(Z){if(!Y||Y(Z)){G[G.length]=Z;}return false;});return G;},getChildren:function(G){G=e.Dom.get(G);if(!G){}return e.Dom.getChildrenBy(G);},getDocumentScrollLeft:function(G){G=G||j;return Math.max(G[U].scrollLeft,G.body.scrollLeft);},getDocumentScrollTop:function(G){G=G||j;return Math.max(G[U].scrollTop,G.body.scrollTop);},insertBefore:function(W,G){W=e.Dom.get(W);G=e.Dom.get(G);if(!W||!G||!G[x]){return null;}return G[x].insertBefore(W,G);},insertAfter:function(W,G){W=e.Dom.get(W);G=e.Dom.get(G);if(!W||!G||!G[x]){return null;}if(G.nextSibling){return G[x].insertBefore(W,G.nextSibling);}else{return G[x].appendChild(W);}},getClientRegion:function(){var X=e.Dom.getDocumentScrollTop(),W=e.Dom.getDocumentScrollLeft(),Y=e.Dom.getViewportWidth()+W,G=e.Dom.getViewportHeight()+X;return new e.Region(X,Y,G,W);},setAttribute:function(W,G,X){e.Dom.batch(W,e.Dom._setAttribute,{attr:G,val:X});},_setAttribute:function(X,W){var G=e.Dom._toCamel(W.attr),Y=W.val;if(X&&X.setAttribute){if(e.Dom.DOT_ATTRIBUTES[G]&&X.tagName&&X.tagName!="BUTTON"){X[G]=Y;}else{G=e.Dom.CUSTOM_ATTRIBUTES[G]||G;X.setAttribute(G,Y);}}else{}},getAttribute:function(W,G){return e.Dom.batch(W,e.Dom._getAttribute,G);},_getAttribute:function(W,G){var X;G=e.Dom.CUSTOM_ATTRIBUTES[G]||G;if(e.Dom.DOT_ATTRIBUTES[G]){X=W[G];}else{if(W&&"getAttribute" in W){if(/^(?:href|src)$/.test(G)){X=W.getAttribute(G,2);}else{X=W.getAttribute(G);}}else{}}return X;},_toCamel:function(W){var X=B;function G(Y,Z){return Z.toUpperCase();}return X[W]||(X[W]=W.indexOf("-")===-1?W:W.replace(/-([a-z])/gi,G));},_getClassRegex:function(W){var G;if(W!==undefined){if(W.exec){G=W;}else{G=F[W];if(!G){W=W.replace(e.Dom._patterns.CLASS_RE_TOKENS,"\\$1");W=W.replace(/\s+/g,b);G=F[W]=new RegExp(R+W+J,t);}}}return G;},_patterns:{ROOT_TAG:/^body|html$/i,CLASS_RE_TOKENS:/([\.\(\)\^\$\*\+\?\|\[\]\{\}\\])/g},_testElement:function(G,W){return G&&G[K]==1&&(!W||W(G));},_calcBorders:function(X,Y){var W=parseInt(e.Dom[V](X,q),10)||0,G=parseInt(e.Dom[V](X,P),10)||0;if(g){if(m.test(X[c])){W=0;G=0;}}Y[0]+=G;Y[1]+=W;return Y;}};var r=e.Dom[V];if(L.opera){e.Dom[V]=function(W,G){var X=r(W,G);if(w.test(G)){X=e.Dom.Color.toRGB(X);}return X;};}if(L.webkit){e.Dom[V]=function(W,G){var X=r(W,G);if(X==="rgba(0, 0, 0, 0)"){X="transparent";}return X;};}if(L.ie&&L.ie>=8){e.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(d,e,a,c){this.top=d;this.y=d;this[1]=d;this.right=e;this.bottom=a;this.left=c;this.x=c;this[0]=c;this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(a){return(a.left>=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(f){var d=Math.max(this.top,f.top),e=Math.min(this.right,f.right),a=Math.min(this.bottom,f.bottom),c=Math.max(this.left,f.left);
+if(a>=d&&e>=c){return new YAHOO.util.Region(d,e,a,c);}else{return null;}};YAHOO.util.Region.prototype.union=function(f){var d=Math.min(this.top,f.top),e=Math.max(this.right,f.right),a=Math.max(this.bottom,f.bottom),c=Math.min(this.left,f.left);return new YAHOO.util.Region(d,e,a,c);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(e){var g=YAHOO.util.Dom.getXY(e),d=g[1],f=g[0]+e.offsetWidth,a=g[1]+e.offsetHeight,c=g[0];return new YAHOO.util.Region(d,f,a,c);};YAHOO.util.Point=function(a,b){if(YAHOO.lang.isArray(a)){b=a[1];a=a[0];}YAHOO.util.Point.superclass.constructor.call(this,b,a,b,a);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var b=YAHOO.util,a="clientTop",f="clientLeft",j="parentNode",k="right",w="hasLayout",i="px",u="opacity",l="auto",d="borderLeftWidth",g="borderTopWidth",p="borderRightWidth",v="borderBottomWidth",s="visible",q="transparent",n="height",e="width",h="style",t="currentStyle",r=/^width|height$/,o=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,m={get:function(x,z){var y="",A=x[t][z];if(z===u){y=b.Dom.getStyle(x,u);}else{if(!A||(A.indexOf&&A.indexOf(i)>-1)){y=A;}else{if(b.Dom.IE_COMPUTED[z]){y=b.Dom.IE_COMPUTED[z](x,z);}else{if(o.test(A)){y=b.Dom.IE.ComputedStyle.getPixel(x,z);}else{y=A;}}}}return y;},getOffset:function(z,E){var B=z[t][E],x=E.charAt(0).toUpperCase()+E.substr(1),C="offset"+x,y="pixel"+x,A="",D;if(B==l){D=z[C];if(D===undefined){A=0;}A=D;if(r.test(E)){z[h][E]=D;if(z[C]>D){A=D-(z[C]-D);}z[h][E]=l;}}else{if(!z[h][y]&&!z[h][E]){z[h][E]=B;}A=z[h][y];}return A+i;},getBorderWidth:function(x,z){var y=null;if(!x[t][w]){x[h].zoom=1;}switch(z){case g:y=x[a];break;case v:y=x.offsetHeight-x.clientHeight-x[a];break;case d:y=x[f];break;case p:y=x.offsetWidth-x.clientWidth-x[f];break;}return y+i;},getPixel:function(y,x){var A=null,B=y[t][k],z=y[t][x];y[h][k]=z;A=y[h].pixelRight;y[h][k]=B;return A+i;},getMargin:function(y,x){var z;if(y[t][x]==l){z=0+i;}else{z=b.Dom.IE.ComputedStyle.getPixel(y,x);}return z;},getVisibility:function(y,x){var z;while((z=y[t])&&z[x]=="inherit"){y=y[j];}return(z)?z[x]:s;},getColor:function(y,x){return b.Dom.Color.toRGB(y[t][x])||q;},getBorderColor:function(y,x){var z=y[t],A=z[x]||z.color;return b.Dom.Color.toRGB(b.Dom.Color.toHex(A));}},c={};c.top=c.right=c.bottom=c.left=c[e]=c[n]=m.getOffset;c.color=m.getColor;c[g]=c[p]=c[v]=c[d]=m.getBorderWidth;c.marginTop=c.marginRight=c.marginBottom=c.marginLeft=m.getMargin;c.visibility=m.getVisibility;c.borderColor=c.borderTopColor=c.borderRightColor=c.borderBottomColor=c.borderLeftColor=m.getBorderColor;b.Dom.IE_COMPUTED=c;b.Dom.IE_ComputedStyle=m;})();(function(){var c="toString",a=parseInt,b=RegExp,d=YAHOO.util;d.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(e){if(!d.Dom.Color.re_RGB.test(e)){e=d.Dom.Color.toHex(e);}if(d.Dom.Color.re_hex.exec(e)){e="rgb("+[a(b.$1,16),a(b.$2,16),a(b.$3,16)].join(", ")+")";}return e;},toHex:function(f){f=d.Dom.Color.KEYWORDS[f]||f;if(d.Dom.Color.re_RGB.exec(f)){f=[Number(b.$1).toString(16),Number(b.$2).toString(16),Number(b.$3).toString(16)];for(var e=0;e<f.length;e++){if(f[e].length<2){f[e]="0"+f[e];}}f=f.join("");}if(f.length<6){f=f.replace(d.Dom.Color.re_hex3,"$1$1");}if(f!=="transparent"&&f.indexOf("#")<0){f="#"+f;}return f.toUpperCase();}};}());YAHOO.register("dom",YAHOO.util.Dom,{version:"2.9.0",build:"2800"});YAHOO.util.CustomEvent=function(d,c,b,a,e){this.type=d;this.scope=c||window;this.silent=b;this.fireOnce=e;this.fired=false;this.firedWith=null;this.signature=a||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var f="_YUICEOnSubscribe";if(d!==f){this.subscribeEvent=new YAHOO.util.CustomEvent(f,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(b,c,d){if(!b){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(b,c,d);}var a=new YAHOO.util.Subscriber(b,c,d);if(this.fireOnce&&this.fired){this.notify(a,this.firedWith);}else{this.subscribers.push(a);}},unsubscribe:function(d,f){if(!d){return this.unsubscribeAll();}var e=false;for(var b=0,a=this.subscribers.length;b<a;++b){var c=this.subscribers[b];if(c&&c.contains(d,f)){this._delete(b);e=true;}}return e;},fire:function(){this.lastError=null;var h=[],a=this.subscribers.length;var d=[].slice.call(arguments,0),c=true,f,b=false;if(this.fireOnce){if(this.fired){return true;}else{this.firedWith=d;}}this.fired=true;if(!a&&this.silent){return true;}if(!this.silent){}var e=this.subscribers.slice();for(f=0;f<a;++f){var g=e[f];if(!g||!g.fn){b=true;}else{c=this.notify(g,d);if(false===c){if(!this.silent){}break;}}}return(c!==false);},notify:function(g,c){var b,i=null,f=g.getScope(this.scope),a=YAHOO.util.Event.throwErrors;if(!this.silent){}if(this.signature==YAHOO.util.CustomEvent.FLAT){if(c.length>0){i=c[0];}try{b=g.fn.call(f,i,g.obj);}catch(h){this.lastError=h;if(a){throw h;}}}else{try{b=g.fn.call(f,this.type,c,g.obj);}catch(d){this.lastError=d;if(a){throw d;}}}return b;},unsubscribeAll:function(){var a=this.subscribers.length,b;for(b=a-1;b>-1;b--){this._delete(b);}this.subscribers=[];return a;},_delete:function(a){var b=this.subscribers[a];if(b){delete b.fn;delete b.obj;}this.subscribers.splice(a,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(a,b,c){this.fn=a;this.obj=YAHOO.lang.isUndefined(b)?null:b;this.overrideContext=c;};YAHOO.util.Subscriber.prototype.getScope=function(a){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return a;};YAHOO.util.Subscriber.prototype.contains=function(a,b){if(b){return(this.fn==a&&this.obj==b);}else{return(this.fn==a);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var g=false,h=[],j=[],a=0,e=[],b=0,c={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},d=YAHOO.env.ua.ie,f="focusin",i="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:d,_interval:null,_dri:null,_specialTypes:{focusin:(d?"focusin":"focus"),focusout:(d?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(q,m,o,p,n){var k=(YAHOO.lang.isString(q))?[q]:q;for(var l=0;l<k.length;l=l+1){e.push({id:k[l],fn:m,obj:o,overrideContext:p,checkReady:n});}a=this.POLL_RETRYS;this.startInterval();},onContentReady:function(n,k,l,m){this.onAvailable(n,k,l,m,true);},onDOMReady:function(){this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent,arguments);},_addListener:function(m,k,v,p,t,y){if(!v||!v.call){return false;}if(this._isValidCollection(m)){var w=true;for(var q=0,s=m.length;q<s;++q){w=this.on(m[q],k,v,p,t)&&w;}return w;}else{if(YAHOO.lang.isString(m)){var o=this.getEl(m);if(o){m=o;}else{this.onAvailable(m,function(){YAHOO.util.Event._addListener(m,k,v,p,t,y);});return true;}}}if(!m){return false;}if("unload"==k&&p!==this){j[j.length]=[m,k,v,p,t];return true;}var l=m;if(t){if(t===true){l=p;}else{l=t;}}var n=function(z){return v.call(l,YAHOO.util.Event.getEvent(z,m),p);};var x=[m,k,v,n,l,p,t,y];var r=h.length;h[r]=x;try{this._simpleAdd(m,k,n,y);}catch(u){this.lastError=u;this.removeListener(m,k,v);return false;}return true;},_getType:function(k){return this._specialTypes[k]||k;},addListener:function(m,p,l,n,o){var k=((p==f||p==i)&&!YAHOO.env.ua.ie)?true:false;return this._addListener(m,this._getType(p),l,n,o,k);},addFocusListener:function(l,k,m,n){return this.on(l,f,k,m,n);},removeFocusListener:function(l,k){return this.removeListener(l,f,k);},addBlurListener:function(l,k,m,n){return this.on(l,i,k,m,n);},removeBlurListener:function(l,k){return this.removeListener(l,i,k);},removeListener:function(l,k,r){var m,p,u;k=this._getType(k);if(typeof l=="string"){l=this.getEl(l);}else{if(this._isValidCollection(l)){var s=true;for(m=l.length-1;m>-1;m--){s=(this.removeListener(l[m],k,r)&&s);}return s;}}if(!r||!r.call){return this.purgeElement(l,false,k);}if("unload"==k){for(m=j.length-1;m>-1;m--){u=j[m];if(u&&u[0]==l&&u[1]==k&&u[2]==r){j.splice(m,1);return true;}}return false;}var n=null;var o=arguments[3];if("undefined"===typeof o){o=this._getCacheIndex(h,l,k,r);}if(o>=0){n=h[o];}if(!l||!n){return false;}var t=n[this.CAPTURE]===true?true:false;try{this._simpleRemove(l,k,n[this.WFN],t);}catch(q){this.lastError=q;return false;}delete h[o][this.WFN];delete h[o][this.FN];h.splice(o,1);return true;},getTarget:function(m,l){var k=m.target||m.srcElement;return this.resolveTextNode(k);},resolveTextNode:function(l){try{if(l&&3==l.nodeType){return l.parentNode;}}catch(k){return null;}return l;},getPageX:function(l){var k=l.pageX;if(!k&&0!==k){k=l.clientX||0;if(this.isIE){k+=this._getScrollLeft();}}return k;},getPageY:function(k){var l=k.pageY;if(!l&&0!==l){l=k.clientY||0;if(this.isIE){l+=this._getScrollTop();}}return l;},getXY:function(k){return[this.getPageX(k),this.getPageY(k)];},getRelatedTarget:function(l){var k=l.relatedTarget;
+if(!k){if(l.type=="mouseout"){k=l.toElement;}else{if(l.type=="mouseover"){k=l.fromElement;}}}return this.resolveTextNode(k);},getTime:function(m){if(!m.time){var l=new Date().getTime();try{m.time=l;}catch(k){this.lastError=k;return l;}}return m.time;},stopEvent:function(k){this.stopPropagation(k);this.preventDefault(k);},stopPropagation:function(k){if(k.stopPropagation){k.stopPropagation();}else{k.cancelBubble=true;}},preventDefault:function(k){if(k.preventDefault){k.preventDefault();}else{k.returnValue=false;}},getEvent:function(m,k){var l=m||window.event;if(!l){var n=this.getEvent.caller;while(n){l=n.arguments[0];if(l&&Event==l.constructor){break;}n=n.caller;}}return l;},getCharCode:function(l){var k=l.keyCode||l.charCode||0;if(YAHOO.env.ua.webkit&&(k in c)){k=c[k];}return k;},_getCacheIndex:function(n,q,r,p){for(var o=0,m=n.length;o<m;o=o+1){var k=n[o];if(k&&k[this.FN]==p&&k[this.EL]==q&&k[this.TYPE]==r){return o;}}return -1;},generateId:function(k){var l=k.id;if(!l){l="yuievtautoid-"+b;++b;k.id=l;}return l;},_isValidCollection:function(l){try{return(l&&typeof l!=="string"&&l.length&&!l.tagName&&!l.alert&&typeof l[0]!=="undefined");}catch(k){return false;}},elCache:{},getEl:function(k){return(typeof k==="string")?document.getElementById(k):k;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",YAHOO,0,0,1),_load:function(l){if(!g){g=true;var k=YAHOO.util.Event;k._ready();k._tryPreloadAttach();}},_ready:function(l){var k=YAHOO.util.Event;if(!k.DOMReady){k.DOMReady=true;k.DOMReadyEvent.fire();k._simpleRemove(document,"DOMContentLoaded",k._ready);}},_tryPreloadAttach:function(){if(e.length===0){a=0;if(this._interval){this._interval.cancel();this._interval=null;}return;}if(this.locked){return;}if(this.isIE){if(!this.DOMReady){this.startInterval();return;}}this.locked=true;var q=!g;if(!q){q=(a>0&&e.length>0);}var p=[];var r=function(t,u){var s=t;if(u.overrideContext){if(u.overrideContext===true){s=u.obj;}else{s=u.overrideContext;}}u.fn.call(s,u.obj);};var l,k,o,n,m=[];for(l=0,k=e.length;l<k;l=l+1){o=e[l];if(o){n=this.getEl(o.id);if(n){if(o.checkReady){if(g||n.nextSibling||!q){m.push(o);e[l]=null;}}else{r(n,o);e[l]=null;}}else{p.push(o);}}}for(l=0,k=m.length;l<k;l=l+1){o=m[l];r(this.getEl(o.id),o);}a--;if(q){for(l=e.length-1;l>-1;l--){o=e[l];if(!o||!o.id){e.splice(l,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(p,q,s){var n=(YAHOO.lang.isString(p))?this.getEl(p):p;var r=this.getListeners(n,s),o,k;if(r){for(o=r.length-1;o>-1;o--){var m=r[o];this.removeListener(n,m.type,m.fn);}}if(q&&n&&n.childNodes){for(o=0,k=n.childNodes.length;o<k;++o){this.purgeElement(n.childNodes[o],q,s);}}},getListeners:function(n,k){var q=[],m;if(!k){m=[h,j];}else{if(k==="unload"){m=[j];}else{k=this._getType(k);m=[h];}}var s=(YAHOO.lang.isString(n))?this.getEl(n):n;for(var p=0;p<m.length;p=p+1){var u=m[p];if(u){for(var r=0,t=u.length;r<t;++r){var o=u[r];if(o&&o[this.EL]===s&&(!k||k===o[this.TYPE])){q.push({type:o[this.TYPE],fn:o[this.FN],obj:o[this.OBJ],adjust:o[this.OVERRIDE],scope:o[this.ADJ_SCOPE],index:r});}}}}return(q.length)?q:null;},_unload:function(s){var m=YAHOO.util.Event,p,o,n,r,q,t=j.slice(),k;for(p=0,r=j.length;p<r;++p){n=t[p];if(n){try{k=window;if(n[m.ADJ_SCOPE]){if(n[m.ADJ_SCOPE]===true){k=n[m.UNLOAD_OBJ];}else{k=n[m.ADJ_SCOPE];}}n[m.FN].call(k,m.getEvent(s,n[m.EL]),n[m.UNLOAD_OBJ]);}catch(w){}t[p]=null;}}n=null;k=null;j=null;if(h){for(o=h.length-1;o>-1;o--){n=h[o];if(n){try{m.removeListener(n[m.EL],n[m.TYPE],n[m.FN],o);}catch(v){}}}n=null;}try{m._simpleRemove(window,"unload",m._unload);m._simpleRemove(window,"load",m._load);}catch(u){}},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var k=document.documentElement,l=document.body;if(k&&(k.scrollTop||k.scrollLeft)){return[k.scrollTop,k.scrollLeft];}else{if(l){return[l.scrollTop,l.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(m,n,l,k){m.addEventListener(n,l,(k));};}else{if(window.attachEvent){return function(m,n,l,k){m.attachEvent("on"+n,l);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(m,n,l,k){m.removeEventListener(n,l,(k));};}else{if(window.detachEvent){return function(l,m,k){l.detachEvent("on"+m,k);};}else{return function(){};}}}()};}();(function(){var a=YAHOO.util.Event;a.on=a.addListener;a.onFocus=a.addFocusListener;a.onBlur=a.addBlurListener;
+/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
+if(a.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;a._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var b=document.createElement("p");a._dri=setInterval(function(){try{b.doScroll("left");clearInterval(a._dri);a._dri=null;a._ready();b=null;}catch(c){}},a.POLL_INTERVAL);}}else{if(a.webkit&&a.webkit<525){a._dri=setInterval(function(){var c=document.readyState;if("loaded"==c||"complete"==c){clearInterval(a._dri);a._dri=null;a._ready();}},a.POLL_INTERVAL);}else{a._simpleAdd(document,"DOMContentLoaded",a._ready);}}a._simpleAdd(window,"load",a._load);a._simpleAdd(window,"unload",a._unload);a._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(a,c,f,e){this.__yui_events=this.__yui_events||{};var d=this.__yui_events[a];if(d){d.subscribe(c,f,e);}else{this.__yui_subscribers=this.__yui_subscribers||{};var b=this.__yui_subscribers;if(!b[a]){b[a]=[];}b[a].push({fn:c,obj:f,overrideContext:e});}},unsubscribe:function(c,e,g){this.__yui_events=this.__yui_events||{};var a=this.__yui_events;if(c){var f=a[c];if(f){return f.unsubscribe(e,g);}}else{var b=true;for(var d in a){if(YAHOO.lang.hasOwnProperty(a,d)){b=b&&a[d].unsubscribe(e,g);
+}}return b;}return false;},unsubscribeAll:function(a){return this.unsubscribe(a);},createEvent:function(b,g){this.__yui_events=this.__yui_events||{};var e=g||{},d=this.__yui_events,f;if(d[b]){}else{f=new YAHOO.util.CustomEvent(b,e.scope||this,e.silent,YAHOO.util.CustomEvent.FLAT,e.fireOnce);d[b]=f;if(e.onSubscribeCallback){f.subscribeEvent.subscribe(e.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var a=this.__yui_subscribers[b];if(a){for(var c=0;c<a.length;++c){f.subscribe(a[c].fn,a[c].obj,a[c].overrideContext);}}}return d[b];},fireEvent:function(b){this.__yui_events=this.__yui_events||{};var d=this.__yui_events[b];if(!d){return null;}var a=[];for(var c=1;c<arguments.length;++c){a.push(arguments[c]);}return d.fire.apply(d,a);},hasEvent:function(a){if(this.__yui_events){if(this.__yui_events[a]){return true;}}return false;}};(function(){var a=YAHOO.util.Event,c=YAHOO.lang;YAHOO.util.KeyListener=function(d,i,e,f){if(!d){}else{if(!i){}else{if(!e){}}}if(!f){f=YAHOO.util.KeyListener.KEYDOWN;}var g=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(c.isString(d)){d=document.getElementById(d);}if(c.isFunction(e)){g.subscribe(e);}else{g.subscribe(e.fn,e.scope,e.correctScope);}function h(o,n){if(!i.shift){i.shift=false;}if(!i.alt){i.alt=false;}if(!i.ctrl){i.ctrl=false;}if(o.shiftKey==i.shift&&o.altKey==i.alt&&o.ctrlKey==i.ctrl){var j,m=i.keys,l;if(YAHOO.lang.isArray(m)){for(var k=0;k<m.length;k++){j=m[k];l=a.getCharCode(o);if(j==l){g.fire(l,o);break;}}}else{l=a.getCharCode(o);if(m==l){g.fire(l,o);}}}}this.enable=function(){if(!this.enabled){a.on(d,f,h);this.enabledEvent.fire(i);}this.enabled=true;};this.disable=function(){if(this.enabled){a.removeListener(d,f,h);this.disabledEvent.fire(i);}this.enabled=false;};this.toString=function(){return"KeyListener ["+i.keys+"] "+d.tagName+(d.id?"["+d.id+"]":"");};};var b=YAHOO.util.KeyListener;b.KEYDOWN="keydown";b.KEYUP="keyup";b.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};})();YAHOO.register("event",YAHOO.util.Event,{version:"2.9.0",build:"2800"});YAHOO.util.Connect={_msxml_progid:["Microsoft.XMLHTTP","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP"],_http_headers:{},_has_http_headers:false,_use_default_post_header:true,_default_post_header:"application/x-www-form-urlencoded; charset=UTF-8",_default_form_header:"application/x-www-form-urlencoded",_use_default_xhr_header:true,_default_xhr_header:"XMLHttpRequest",_has_default_headers:true,_isFormSubmit:false,_default_headers:{},_poll:{},_timeOut:{},_polling_interval:50,_transaction_id:0,startEvent:new YAHOO.util.CustomEvent("start"),completeEvent:new YAHOO.util.CustomEvent("complete"),successEvent:new YAHOO.util.CustomEvent("success"),failureEvent:new YAHOO.util.CustomEvent("failure"),abortEvent:new YAHOO.util.CustomEvent("abort"),_customEvents:{onStart:["startEvent","start"],onComplete:["completeEvent","complete"],onSuccess:["successEvent","success"],onFailure:["failureEvent","failure"],onUpload:["uploadEvent","upload"],onAbort:["abortEvent","abort"]},setProgId:function(a){this._msxml_progid.unshift(a);},setDefaultPostHeader:function(a){if(typeof a=="string"){this._default_post_header=a;this._use_default_post_header=true;}else{if(typeof a=="boolean"){this._use_default_post_header=a;}}},setDefaultXhrHeader:function(a){if(typeof a=="string"){this._default_xhr_header=a;}else{this._use_default_xhr_header=a;}},setPollingInterval:function(a){if(typeof a=="number"&&isFinite(a)){this._polling_interval=a;}},createXhrObject:function(g){var d,a,b;try{a=new XMLHttpRequest();d={conn:a,tId:g,xhr:true};}catch(c){for(b=0;b<this._msxml_progid.length;++b){try{a=new ActiveXObject(this._msxml_progid[b]);d={conn:a,tId:g,xhr:true};break;}catch(f){}}}finally{return d;}},getConnectionObject:function(a){var c,d=this._transaction_id;try{if(!a){c=this.createXhrObject(d);}else{c={tId:d};if(a==="xdr"){c.conn=this._transport;c.xdr=true;}else{if(a==="upload"){c.upload=true;}}}if(c){this._transaction_id++;}}catch(b){}return c;},asyncRequest:function(h,d,g,a){var b=g&&g.argument?g.argument:null,e=this,f,c;if(this._isFileUpload){c="upload";}else{if(g&&g.xdr){c="xdr";}}f=this.getConnectionObject(c);if(!f){return null;}else{if(g&&g.customevents){this.initCustomEvents(f,g);}if(this._isFormSubmit){if(this._isFileUpload){window.setTimeout(function(){e.uploadFile(f,g,d,a);},10);return f;}if(h.toUpperCase()=="GET"){if(this._sFormData.length!==0){d+=((d.indexOf("?")==-1)?"?":"&")+this._sFormData;}}else{if(h.toUpperCase()=="POST"){a=a?this._sFormData+"&"+a:this._sFormData;}}}if(h.toUpperCase()=="GET"&&(g&&g.cache===false)){d+=((d.indexOf("?")==-1)?"?":"&")+"rnd="+new Date().valueOf().toString();}if(this._use_default_xhr_header){if(!this._default_headers["X-Requested-With"]){this.initHeader("X-Requested-With",this._default_xhr_header,true);}}if((h.toUpperCase()==="POST"&&this._use_default_post_header)&&this._isFormSubmit===false){this.initHeader("Content-Type",this._default_post_header);}if(f.xdr){this.xdr(f,h,d,g,a);return f;}f.conn.open(h,d,true);if(this._has_default_headers||this._has_http_headers){this.setHeader(f);}this.handleReadyState(f,g);f.conn.send(a||"");if(this._isFormSubmit===true){this.resetFormState();}this.startEvent.fire(f,b);if(f.startEvent){f.startEvent.fire(f,b);}return f;}},initCustomEvents:function(a,c){var b;for(b in c.customevents){if(this._customEvents[b][0]){a[this._customEvents[b][0]]=new YAHOO.util.CustomEvent(this._customEvents[b][1],(c.scope)?c.scope:null);a[this._customEvents[b][0]].subscribe(c.customevents[b]);}}},handleReadyState:function(c,d){var b=this,a=(d&&d.argument)?d.argument:null;if(d&&d.timeout){this._timeOut[c.tId]=window.setTimeout(function(){b.abort(c,d,true);},d.timeout);}this._poll[c.tId]=window.setInterval(function(){if(c.conn&&c.conn.readyState===4){window.clearInterval(b._poll[c.tId]);delete b._poll[c.tId];if(d&&d.timeout){window.clearTimeout(b._timeOut[c.tId]);delete b._timeOut[c.tId];}b.completeEvent.fire(c,a);if(c.completeEvent){c.completeEvent.fire(c,a);}b.handleTransactionResponse(c,d);}},this._polling_interval);},handleTransactionResponse:function(b,j,d){var f,a,h=(j&&j.argument)?j.argument:null,c=(b.r&&b.r.statusText==="xdr:success")?true:false,i=(b.r&&b.r.statusText==="xdr:failure")?true:false,k=d;try{if((b.conn.status!==undefined&&b.conn.status!==0)||c){f=b.conn.status;}else{if(i&&!k){f=0;}else{f=13030;}}}catch(g){f=13030;}if((f>=200&&f<300)||f===1223||c){a=b.xdr?b.r:this.createResponseObject(b,h);if(j&&j.success){if(!j.scope){j.success(a);}else{j.success.apply(j.scope,[a]);}}this.successEvent.fire(a);if(b.successEvent){b.successEvent.fire(a);}}else{switch(f){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:a=this.createExceptionObject(b.tId,h,(d?d:false));if(j&&j.failure){if(!j.scope){j.failure(a);}else{j.failure.apply(j.scope,[a]);}}break;default:a=(b.xdr)?b.response:this.createResponseObject(b,h);if(j&&j.failure){if(!j.scope){j.failure(a);}else{j.failure.apply(j.scope,[a]);}}}this.failureEvent.fire(a);if(b.failureEvent){b.failureEvent.fire(a);}}this.releaseObject(b);a=null;},createResponseObject:function(a,h){var d={},k={},f,c,g,b;try{c=a.conn.getAllResponseHeaders();g=c.split("\n");for(f=0;f<g.length;f++){b=g[f].indexOf(":");if(b!=-1){k[g[f].substring(0,b)]=YAHOO.lang.trim(g[f].substring(b+2));}}}catch(j){}d.tId=a.tId;d.status=(a.conn.status==1223)?204:a.conn.status;d.statusText=(a.conn.status==1223)?"No Content":a.conn.statusText;d.getResponseHeader=k;d.getAllResponseHeaders=c;d.responseText=a.conn.responseText;d.responseXML=a.conn.responseXML;if(h){d.argument=h;}return d;},createExceptionObject:function(h,d,a){var f=0,g="communication failure",c=-1,b="transaction aborted",e={};e.tId=h;if(a){e.status=c;e.statusText=b;}else{e.status=f;e.statusText=g;}if(d){e.argument=d;}return e;},initHeader:function(a,d,c){var b=(c)?this._default_headers:this._http_headers;b[a]=d;if(c){this._has_default_headers=true;}else{this._has_http_headers=true;}},setHeader:function(a){var b;if(this._has_default_headers){for(b in this._default_headers){if(YAHOO.lang.hasOwnProperty(this._default_headers,b)){a.conn.setRequestHeader(b,this._default_headers[b]);
+}}}if(this._has_http_headers){for(b in this._http_headers){if(YAHOO.lang.hasOwnProperty(this._http_headers,b)){a.conn.setRequestHeader(b,this._http_headers[b]);}}this._http_headers={};this._has_http_headers=false;}},resetDefaultHeaders:function(){this._default_headers={};this._has_default_headers=false;},abort:function(e,g,a){var d,b=(g&&g.argument)?g.argument:null;e=e||{};if(e.conn){if(e.xhr){if(this.isCallInProgress(e)){e.conn.abort();window.clearInterval(this._poll[e.tId]);delete this._poll[e.tId];if(a){window.clearTimeout(this._timeOut[e.tId]);delete this._timeOut[e.tId];}d=true;}}else{if(e.xdr){e.conn.abort(e.tId);d=true;}}}else{if(e.upload){var c="yuiIO"+e.tId;var f=document.getElementById(c);if(f){YAHOO.util.Event.removeListener(f,"load");document.body.removeChild(f);if(a){window.clearTimeout(this._timeOut[e.tId]);delete this._timeOut[e.tId];}d=true;}}else{d=false;}}if(d===true){this.abortEvent.fire(e,b);if(e.abortEvent){e.abortEvent.fire(e,b);}this.handleTransactionResponse(e,g,true);}return d;},isCallInProgress:function(a){a=a||{};if(a.xhr&&a.conn){return a.conn.readyState!==4&&a.conn.readyState!==0;}else{if(a.xdr&&a.conn){return a.conn.isCallInProgress(a.tId);}else{if(a.upload===true){return document.getElementById("yuiIO"+a.tId)?true:false;}else{return false;}}}},releaseObject:function(a){if(a&&a.conn){a.conn=null;a=null;}}};(function(){var g=YAHOO.util.Connect,h={};function d(i){var j='<object id="YUIConnectionSwf" type="application/x-shockwave-flash" data="'+i+'" width="0" height="0">'+'<param name="movie" value="'+i+'">'+'<param name="allowScriptAccess" value="always">'+"</object>",k=document.createElement("div");document.body.appendChild(k);k.innerHTML=j;}function b(l,i,j,n,k){h[parseInt(l.tId)]={"o":l,"c":n};if(k){n.method=i;n.data=k;}l.conn.send(j,n,l.tId);}function e(i){d(i);g._transport=document.getElementById("YUIConnectionSwf");}function c(){g.xdrReadyEvent.fire();}function a(j,i){if(j){g.startEvent.fire(j,i.argument);if(j.startEvent){j.startEvent.fire(j,i.argument);}}}function f(j){var k=h[j.tId].o,i=h[j.tId].c;if(j.statusText==="xdr:start"){a(k,i);return;}j.responseText=decodeURI(j.responseText);k.r=j;if(i.argument){k.r.argument=i.argument;}this.handleTransactionResponse(k,i,j.statusText==="xdr:abort"?true:false);delete h[j.tId];}g.xdr=b;g.swf=d;g.transport=e;g.xdrReadyEvent=new YAHOO.util.CustomEvent("xdrReady");g.xdrReady=c;g.handleXdrResponse=f;})();(function(){var e=YAHOO.util.Connect,g=YAHOO.util.Event,a=document.documentMode?document.documentMode:false;e._isFileUpload=false;e._formNode=null;e._sFormData=null;e._submitElementValue=null;e.uploadEvent=new YAHOO.util.CustomEvent("upload");e._hasSubmitListener=function(){if(g){g.addListener(document,"click",function(k){var j=g.getTarget(k),i=j.nodeName.toLowerCase();if((i==="input"||i==="button")&&(j.type&&j.type.toLowerCase()=="submit")){e._submitElementValue=encodeURIComponent(j.name)+"="+encodeURIComponent(j.value);}});return true;}return false;}();function h(w,r,m){var v,l,u,s,z,t=false,p=[],y=0,o,q,n,x,k;this.resetFormState();if(typeof w=="string"){v=(document.getElementById(w)||document.forms[w]);}else{if(typeof w=="object"){v=w;}else{return;}}if(r){this.createFrame(m?m:null);this._isFormSubmit=true;this._isFileUpload=true;this._formNode=v;return;}for(o=0,q=v.elements.length;o<q;++o){l=v.elements[o];z=l.disabled;u=l.name;if(!z&&u){u=encodeURIComponent(u)+"=";s=encodeURIComponent(l.value);switch(l.type){case"select-one":if(l.selectedIndex>-1){k=l.options[l.selectedIndex];p[y++]=u+encodeURIComponent((k.attributes.value&&k.attributes.value.specified)?k.value:k.text);}break;case"select-multiple":if(l.selectedIndex>-1){for(n=l.selectedIndex,x=l.options.length;n<x;++n){k=l.options[n];if(k.selected){p[y++]=u+encodeURIComponent((k.attributes.value&&k.attributes.value.specified)?k.value:k.text);}}}break;case"radio":case"checkbox":if(l.checked){p[y++]=u+s;}break;case"file":case undefined:case"reset":case"button":break;case"submit":if(t===false){if(this._hasSubmitListener&&this._submitElementValue){p[y++]=this._submitElementValue;}t=true;}break;default:p[y++]=u+s;}}}this._isFormSubmit=true;this._sFormData=p.join("&");this.initHeader("Content-Type",this._default_form_header);return this._sFormData;}function d(){this._isFormSubmit=false;this._isFileUpload=false;this._formNode=null;this._sFormData="";}function c(i){var j="yuiIO"+this._transaction_id,l=(a===9)?true:false,k;if(YAHOO.env.ua.ie&&!l){k=document.createElement('<iframe id="'+j+'" name="'+j+'" />');if(typeof i=="boolean"){k.src="javascript:false";}}else{k=document.createElement("iframe");k.id=j;k.name=j;}k.style.position="absolute";k.style.top="-1000px";k.style.left="-1000px";document.body.appendChild(k);}function f(j){var m=[],k=j.split("&"),l,n;for(l=0;l<k.length;l++){n=k[l].indexOf("=");if(n!=-1){m[l]=document.createElement("input");m[l].type="hidden";m[l].name=decodeURIComponent(k[l].substring(0,n));m[l].value=decodeURIComponent(k[l].substring(n+1));this._formNode.appendChild(m[l]);}}return m;}function b(m,y,n,l){var t="yuiIO"+m.tId,u="multipart/form-data",w=document.getElementById(t),p=(a>=8)?true:false,z=this,v=(y&&y.argument)?y.argument:null,x,s,k,r,j,q;j={action:this._formNode.getAttribute("action"),method:this._formNode.getAttribute("method"),target:this._formNode.getAttribute("target")};this._formNode.setAttribute("action",n);this._formNode.setAttribute("method","POST");this._formNode.setAttribute("target",t);if(YAHOO.env.ua.ie&&!p){this._formNode.setAttribute("encoding",u);}else{this._formNode.setAttribute("enctype",u);}if(l){x=this.appendPostData(l);}this._formNode.submit();this.startEvent.fire(m,v);if(m.startEvent){m.startEvent.fire(m,v);}if(y&&y.timeout){this._timeOut[m.tId]=window.setTimeout(function(){z.abort(m,y,true);},y.timeout);}if(x&&x.length>0){for(s=0;s<x.length;s++){this._formNode.removeChild(x[s]);}}for(k in j){if(YAHOO.lang.hasOwnProperty(j,k)){if(j[k]){this._formNode.setAttribute(k,j[k]);}else{this._formNode.removeAttribute(k);}}}this.resetFormState();
+q=function(){var i,A,B;if(y&&y.timeout){window.clearTimeout(z._timeOut[m.tId]);delete z._timeOut[m.tId];}z.completeEvent.fire(m,v);if(m.completeEvent){m.completeEvent.fire(m,v);}r={tId:m.tId,argument:v};try{i=w.contentWindow.document.getElementsByTagName("body")[0];A=w.contentWindow.document.getElementsByTagName("pre")[0];if(i){if(A){B=A.textContent?A.textContent:A.innerText;}else{B=i.textContent?i.textContent:i.innerText;}}r.responseText=B;r.responseXML=w.contentWindow.document.XMLDocument?w.contentWindow.document.XMLDocument:w.contentWindow.document;}catch(o){}if(y&&y.upload){if(!y.scope){y.upload(r);}else{y.upload.apply(y.scope,[r]);}}z.uploadEvent.fire(r);if(m.uploadEvent){m.uploadEvent.fire(r);}g.removeListener(w,"load",q);setTimeout(function(){document.body.removeChild(w);z.releaseObject(m);},100);};g.addListener(w,"load",q);}e.setForm=h;e.resetFormState=d;e.createFrame=c;e.appendPostData=f;e.uploadFile=b;})();YAHOO.register("connection",YAHOO.util.Connect,{version:"2.9.0",build:"2800"});(function(){var b=YAHOO.util;var a=function(d,c,e,f){if(!d){}this.init(d,c,e,f);};a.NAME="Anim";a.prototype={toString:function(){var c=this.getEl()||{};var d=c.id||c.tagName;return(this.constructor.NAME+": "+d);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(c,e,d){return this.method(this.currentFrame,e,d-e,this.totalFrames);},setAttribute:function(c,f,e){var d=this.getEl();if(this.patterns.noNegatives.test(c)){f=(f>0)?f:0;}if(c in d&&!("style" in d&&c in d.style)){d[c]=f;}else{b.Dom.setStyle(d,c,f+e);}},getAttribute:function(c){var e=this.getEl();var g=b.Dom.getStyle(e,c);if(g!=="auto"&&!this.patterns.offsetUnit.test(g)){return parseFloat(g);}var d=this.patterns.offsetAttribute.exec(c)||[];var h=!!(d[3]);var f=!!(d[2]);if("style" in e){if(f||(b.Dom.getStyle(e,"position")=="absolute"&&h)){g=e["offset"+d[0].charAt(0).toUpperCase()+d[0].substr(1)];}else{g=0;}}else{if(c in e){g=e[c];}}return g;},getDefaultUnit:function(c){if(this.patterns.defaultUnit.test(c)){return"px";}return"";},setRuntimeAttribute:function(d){var j;var e;var f=this.attributes;this.runtimeAttributes[d]={};var h=function(i){return(typeof i!=="undefined");};if(!h(f[d]["to"])&&!h(f[d]["by"])){return false;}j=(h(f[d]["from"]))?f[d]["from"]:this.getAttribute(d);if(h(f[d]["to"])){e=f[d]["to"];}else{if(h(f[d]["by"])){if(j.constructor==Array){e=[];for(var g=0,c=j.length;g<c;++g){e[g]=j[g]+f[d]["by"][g]*1;}}else{e=j+f[d]["by"]*1;}}}this.runtimeAttributes[d].start=j;this.runtimeAttributes[d].end=e;this.runtimeAttributes[d].unit=(h(f[d].unit))?f[d]["unit"]:this.getDefaultUnit(d);return true;},init:function(f,c,h,i){var d=false;var e=null;var g=0;f=b.Dom.get(f);this.attributes=c||{};this.duration=!YAHOO.lang.isUndefined(h)?h:1;this.method=i||b.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=b.AnimMgr.fps;this.setEl=function(j){f=b.Dom.get(j);};this.getEl=function(){return f;};this.isAnimated=function(){return d;};this.getStartTime=function(){return e;};this.runtimeAttributes={};this.animate=function(){if(this.isAnimated()){return false;}this.currentFrame=0;this.totalFrames=(this.useSeconds)?Math.ceil(b.AnimMgr.fps*this.duration):this.duration;if(this.duration===0&&this.useSeconds){this.totalFrames=1;}b.AnimMgr.registerElement(this);return true;};this.stop=function(j){if(!this.isAnimated()){return false;}if(j){this.currentFrame=this.totalFrames;this._onTween.fire();}b.AnimMgr.stop(this);};this._handleStart=function(){this.onStart.fire();this.runtimeAttributes={};for(var j in this.attributes){if(this.attributes.hasOwnProperty(j)){this.setRuntimeAttribute(j);}}d=true;g=0;e=new Date();};this._handleTween=function(){var l={duration:new Date()-this.getStartTime(),currentFrame:this.currentFrame};l.toString=function(){return("duration: "+l.duration+", currentFrame: "+l.currentFrame);};this.onTween.fire(l);var k=this.runtimeAttributes;for(var j in k){if(k.hasOwnProperty(j)){this.setAttribute(j,this.doMethod(j,k[j].start,k[j].end),k[j].unit);}}this.afterTween.fire(l);g+=1;};this._handleComplete=function(){var j=(new Date()-e)/1000;var k={duration:j,frames:g,fps:g/j};k.toString=function(){return("duration: "+k.duration+", frames: "+k.frames+", fps: "+k.fps);};d=false;g=0;this.onComplete.fire(k);};this._onStart=new b.CustomEvent("_start",this,true);this.onStart=new b.CustomEvent("start",this);this.onTween=new b.CustomEvent("tween",this);this.afterTween=new b.CustomEvent("afterTween",this);this._onTween=new b.CustomEvent("_tween",this,true);this.onComplete=new b.CustomEvent("complete",this);this._onComplete=new b.CustomEvent("_complete",this,true);this._onStart.subscribe(this._handleStart);this._onTween.subscribe(this._handleTween);this._onComplete.subscribe(this._handleComplete);}};b.Anim=a;})();YAHOO.util.AnimMgr=new function(){var e=null;var c=[];var g=0;this.fps=1000;this.delay=20;this.registerElement=function(j){c[c.length]=j;g+=1;j._onStart.fire();this.start();};var f=[];var d=false;var h=function(){var j=f.shift();b.apply(YAHOO.util.AnimMgr,j);if(f.length){arguments.callee();}};var b=function(k,j){j=j||a(k);if(!k.isAnimated()||j===-1){return false;}k._onComplete.fire();c.splice(j,1);g-=1;if(g<=0){this.stop();}return true;};this.unRegister=function(){f.push(arguments);if(!d){d=true;h();d=false;}};this.start=function(){if(e===null){e=setInterval(this.run,this.delay);}};this.stop=function(l){if(!l){clearInterval(e);for(var k=0,j=c.length;k<j;++k){this.unRegister(c[0],0);}c=[];e=null;g=0;}else{this.unRegister(l);}};this.run=function(){for(var l=0,j=c.length;l<j;++l){var k=c[l];if(!k||!k.isAnimated()){continue;}if(k.currentFrame<k.totalFrames||k.totalFrames===null){k.currentFrame+=1;if(k.useSeconds){i(k);}k._onTween.fire();}else{YAHOO.util.AnimMgr.stop(k,l);}}};var a=function(l){for(var k=0,j=c.length;k<j;++k){if(c[k]===l){return k;}}return -1;};var i=function(k){var n=k.totalFrames;var m=k.currentFrame;var l=(k.currentFrame*k.duration*1000/k.totalFrames);var j=(new Date()-k.getStartTime());var o=0;if(j<k.duration*1000){o=Math.round((j/l-1)*k.currentFrame);}else{o=n-(m+1);}if(o>0&&isFinite(o)){if(k.currentFrame+o>=n){o=n-(m+1);}k.currentFrame+=o;}};this._queue=c;this._getIndex=a;};YAHOO.util.Bezier=new function(){this.getPosition=function(e,d){var f=e.length;var c=[];for(var b=0;b<f;++b){c[b]=[e[b][0],e[b][1]];}for(var a=1;a<f;++a){for(b=0;b<f-a;++b){c[b][0]=(1-d)*c[b][0]+d*c[parseInt(b+1,10)][0];c[b][1]=(1-d)*c[b][1]+d*c[parseInt(b+1,10)][1];}}return[c[0][0],c[0][1]];};};(function(){var a=function(f,e,g,h){a.superclass.constructor.call(this,f,e,g,h);};a.NAME="ColorAnim";a.DEFAULT_BGCOLOR="#fff";var c=YAHOO.util;YAHOO.extend(a,c.Anim);var d=a.superclass;var b=a.prototype;b.patterns.color=/color$/i;b.patterns.rgb=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;b.patterns.hex=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;b.patterns.hex3=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
+b.patterns.transparent=/^transparent|rgba\(0, 0, 0, 0\)$/;b.parseColor=function(e){if(e.length==3){return e;}var f=this.patterns.hex.exec(e);if(f&&f.length==4){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)];}f=this.patterns.rgb.exec(e);if(f&&f.length==4){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)];}f=this.patterns.hex3.exec(e);if(f&&f.length==4){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)];}return null;};b.getAttribute=function(e){var g=this.getEl();if(this.patterns.color.test(e)){var i=YAHOO.util.Dom.getStyle(g,e);var h=this;if(this.patterns.transparent.test(i)){var f=YAHOO.util.Dom.getAncestorBy(g,function(j){return !h.patterns.transparent.test(i);});if(f){i=c.Dom.getStyle(f,e);}else{i=a.DEFAULT_BGCOLOR;}}}else{i=d.getAttribute.call(this,e);}return i;};b.doMethod=function(f,k,g){var j;if(this.patterns.color.test(f)){j=[];for(var h=0,e=k.length;h<e;++h){j[h]=d.doMethod.call(this,f,k[h],g[h]);}j="rgb("+Math.floor(j[0])+","+Math.floor(j[1])+","+Math.floor(j[2])+")";}else{j=d.doMethod.call(this,f,k,g);}return j;};b.setRuntimeAttribute=function(f){d.setRuntimeAttribute.call(this,f);if(this.patterns.color.test(f)){var h=this.attributes;var k=this.parseColor(this.runtimeAttributes[f].start);var g=this.parseColor(this.runtimeAttributes[f].end);if(typeof h[f]["to"]==="undefined"&&typeof h[f]["by"]!=="undefined"){g=this.parseColor(h[f].by);for(var j=0,e=k.length;j<e;++j){g[j]=k[j]+g[j];}}this.runtimeAttributes[f].start=k;this.runtimeAttributes[f].end=g;}};c.ColorAnim=a;})();
+/*!
+TERMS OF USE - EASING EQUATIONS
+Open source under the BSD License.
+Copyright 2001 Robert Penner All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+YAHOO.util.Easing={easeNone:function(e,a,g,f){return g*e/f+a;},easeIn:function(e,a,g,f){return g*(e/=f)*e+a;},easeOut:function(e,a,g,f){return -g*(e/=f)*(e-2)+a;},easeBoth:function(e,a,g,f){if((e/=f/2)<1){return g/2*e*e+a;}return -g/2*((--e)*(e-2)-1)+a;},easeInStrong:function(e,a,g,f){return g*(e/=f)*e*e*e+a;},easeOutStrong:function(e,a,g,f){return -g*((e=e/f-1)*e*e*e-1)+a;},easeBothStrong:function(e,a,g,f){if((e/=f/2)<1){return g/2*e*e*e*e+a;}return -g/2*((e-=2)*e*e*e-2)+a;},elasticIn:function(g,e,k,j,f,i){if(g==0){return e;}if((g/=j)==1){return e+k;}if(!i){i=j*0.3;}if(!f||f<Math.abs(k)){f=k;var h=i/4;}else{var h=i/(2*Math.PI)*Math.asin(k/f);}return -(f*Math.pow(2,10*(g-=1))*Math.sin((g*j-h)*(2*Math.PI)/i))+e;},elasticOut:function(g,e,k,j,f,i){if(g==0){return e;}if((g/=j)==1){return e+k;}if(!i){i=j*0.3;}if(!f||f<Math.abs(k)){f=k;var h=i/4;}else{var h=i/(2*Math.PI)*Math.asin(k/f);}return f*Math.pow(2,-10*g)*Math.sin((g*j-h)*(2*Math.PI)/i)+k+e;},elasticBoth:function(g,e,k,j,f,i){if(g==0){return e;}if((g/=j/2)==2){return e+k;}if(!i){i=j*(0.3*1.5);}if(!f||f<Math.abs(k)){f=k;var h=i/4;}else{var h=i/(2*Math.PI)*Math.asin(k/f);}if(g<1){return -0.5*(f*Math.pow(2,10*(g-=1))*Math.sin((g*j-h)*(2*Math.PI)/i))+e;}return f*Math.pow(2,-10*(g-=1))*Math.sin((g*j-h)*(2*Math.PI)/i)*0.5+k+e;},backIn:function(e,a,h,g,f){if(typeof f=="undefined"){f=1.70158;}return h*(e/=g)*e*((f+1)*e-f)+a;},backOut:function(e,a,h,g,f){if(typeof f=="undefined"){f=1.70158;}return h*((e=e/g-1)*e*((f+1)*e+f)+1)+a;},backBoth:function(e,a,h,g,f){if(typeof f=="undefined"){f=1.70158;}if((e/=g/2)<1){return h/2*(e*e*(((f*=(1.525))+1)*e-f))+a;}return h/2*((e-=2)*e*(((f*=(1.525))+1)*e+f)+2)+a;},bounceIn:function(e,a,g,f){return g-YAHOO.util.Easing.bounceOut(f-e,0,g,f)+a;},bounceOut:function(e,a,g,f){if((e/=f)<(1/2.75)){return g*(7.5625*e*e)+a;}else{if(e<(2/2.75)){return g*(7.5625*(e-=(1.5/2.75))*e+0.75)+a;}else{if(e<(2.5/2.75)){return g*(7.5625*(e-=(2.25/2.75))*e+0.9375)+a;}}}return g*(7.5625*(e-=(2.625/2.75))*e+0.984375)+a;},bounceBoth:function(e,a,g,f){if(e<f/2){return YAHOO.util.Easing.bounceIn(e*2,0,g,f)*0.5+a;}return YAHOO.util.Easing.bounceOut(e*2-f,0,g,f)*0.5+g*0.5+a;}};(function(){var a=function(h,g,i,j){if(h){a.superclass.constructor.call(this,h,g,i,j);}};a.NAME="Motion";var e=YAHOO.util;YAHOO.extend(a,e.ColorAnim);var f=a.superclass;var c=a.prototype;c.patterns.points=/^points$/i;c.setAttribute=function(g,i,h){if(this.patterns.points.test(g)){h=h||"px";f.setAttribute.call(this,"left",i[0],h);f.setAttribute.call(this,"top",i[1],h);}else{f.setAttribute.call(this,g,i,h);}};c.getAttribute=function(g){if(this.patterns.points.test(g)){var h=[f.getAttribute.call(this,"left"),f.getAttribute.call(this,"top")];}else{h=f.getAttribute.call(this,g);}return h;};c.doMethod=function(g,k,h){var j=null;if(this.patterns.points.test(g)){var i=this.method(this.currentFrame,0,100,this.totalFrames)/100;j=e.Bezier.getPosition(this.runtimeAttributes[g],i);
+}else{j=f.doMethod.call(this,g,k,h);}return j;};c.setRuntimeAttribute=function(q){if(this.patterns.points.test(q)){var h=this.getEl();var k=this.attributes;var g;var m=k["points"]["control"]||[];var j;var n,p;if(m.length>0&&!(m[0] instanceof Array)){m=[m];}else{var l=[];for(n=0,p=m.length;n<p;++n){l[n]=m[n];}m=l;}if(e.Dom.getStyle(h,"position")=="static"){e.Dom.setStyle(h,"position","relative");}if(d(k["points"]["from"])){e.Dom.setXY(h,k["points"]["from"]);}else{e.Dom.setXY(h,e.Dom.getXY(h));}g=this.getAttribute("points");if(d(k["points"]["to"])){j=b.call(this,k["points"]["to"],g);var o=e.Dom.getXY(this.getEl());for(n=0,p=m.length;n<p;++n){m[n]=b.call(this,m[n],g);}}else{if(d(k["points"]["by"])){j=[g[0]+k["points"]["by"][0],g[1]+k["points"]["by"][1]];for(n=0,p=m.length;n<p;++n){m[n]=[g[0]+m[n][0],g[1]+m[n][1]];}}}this.runtimeAttributes[q]=[g];if(m.length>0){this.runtimeAttributes[q]=this.runtimeAttributes[q].concat(m);}this.runtimeAttributes[q][this.runtimeAttributes[q].length]=j;}else{f.setRuntimeAttribute.call(this,q);}};var b=function(g,i){var h=e.Dom.getXY(this.getEl());g=[g[0]-h[0]+i[0],g[1]-h[1]+i[1]];return g;};var d=function(g){return(typeof g!=="undefined");};e.Motion=a;})();(function(){var d=function(f,e,g,h){if(f){d.superclass.constructor.call(this,f,e,g,h);}};d.NAME="Scroll";var b=YAHOO.util;YAHOO.extend(d,b.ColorAnim);var c=d.superclass;var a=d.prototype;a.doMethod=function(e,h,f){var g=null;if(e=="scroll"){g=[this.method(this.currentFrame,h[0],f[0]-h[0],this.totalFrames),this.method(this.currentFrame,h[1],f[1]-h[1],this.totalFrames)];}else{g=c.doMethod.call(this,e,h,f);}return g;};a.getAttribute=function(e){var g=null;var f=this.getEl();if(e=="scroll"){g=[f.scrollLeft,f.scrollTop];}else{g=c.getAttribute.call(this,e);}return g;};a.setAttribute=function(e,h,g){var f=this.getEl();if(e=="scroll"){f.scrollLeft=h[0];f.scrollTop=h[1];}else{c.setAttribute.call(this,e,h,g);}};b.Scroll=d;})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.9.0",build:"2800"});if(!YAHOO.util.DragDropMgr){YAHOO.util.DragDropMgr=function(){var A=YAHOO.util.Event,B=YAHOO.util.Dom;return{useShim:false,_shimActive:false,_shimState:false,_debugShim:false,_createShim:function(){var C=document.createElement("div");C.id="yui-ddm-shim";if(document.body.firstChild){document.body.insertBefore(C,document.body.firstChild);}else{document.body.appendChild(C);}C.style.display="none";C.style.backgroundColor="red";C.style.position="absolute";C.style.zIndex="99999";B.setStyle(C,"opacity","0");this._shim=C;A.on(C,"mouseup",this.handleMouseUp,this,true);A.on(C,"mousemove",this.handleMouseMove,this,true);A.on(window,"scroll",this._sizeShim,this,true);},_sizeShim:function(){if(this._shimActive){var C=this._shim;C.style.height=B.getDocumentHeight()+"px";C.style.width=B.getDocumentWidth()+"px";C.style.top="0";C.style.left="0";}},_activateShim:function(){if(this.useShim){if(!this._shim){this._createShim();}this._shimActive=true;var C=this._shim,D="0";if(this._debugShim){D=".5";}B.setStyle(C,"opacity",D);this._sizeShim();C.style.display="block";}},_deactivateShim:function(){this._shim.style.display="none";this._shimActive=false;},_shim:null,ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,interactionInfo:null,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,STRICT_INTERSECT:2,mode:0,_execOnAll:function(E,D){for(var F in this.ids){for(var C in this.ids[F]){var G=this.ids[F][C];if(!this.isTypeOfDD(G)){continue;}G[E].apply(G,D);}}},_onLoad:function(){this.init();A.on(document,"mouseup",this.handleMouseUp,this,true);A.on(document,"mousemove",this.handleMouseMove,this,true);A.on(window,"unload",this._onUnload,this,true);A.on(window,"resize",this._onResize,this,true);},_onResize:function(C){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:1000,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,fromTimeout:false,regDragDrop:function(D,C){if(!this.initialized){this.init();}if(!this.ids[C]){this.ids[C]={};}this.ids[C][D.id]=D;},removeDDFromGroup:function(E,C){if(!this.ids[C]){this.ids[C]={};}var D=this.ids[C];if(D&&D[E.id]){delete D[E.id];}},_remove:function(E){for(var D in E.groups){if(D){var C=this.ids[D];if(C&&C[E.id]){delete C[E.id];}}}delete this.handleIds[E.id];},regHandle:function(D,C){if(!this.handleIds[D]){this.handleIds[D]={};}this.handleIds[D][C]=C;},isDragDrop:function(C){return(this.getDDById(C))?true:false;},getRelated:function(H,D){var G=[];for(var F in H.groups){for(var E in this.ids[F]){var C=this.ids[F][E];if(!this.isTypeOfDD(C)){continue;}if(!D||C.isTarget){G[G.length]=C;}}}return G;},isLegalTarget:function(G,F){var D=this.getRelated(G,true);for(var E=0,C=D.length;E<C;++E){if(D[E].id==F.id){return true;}}return false;},isTypeOfDD:function(C){return(C&&C.__ygDragDrop);},isHandle:function(D,C){return(this.handleIds[D]&&this.handleIds[D][C]);},getDDById:function(D){for(var C in this.ids){if(this.ids[C][D]){return this.ids[C][D];}}return null;},handleMouseDown:function(E,D){this.currentTarget=YAHOO.util.Event.getTarget(E);this.dragCurrent=D;var C=D.getEl();this.startX=YAHOO.util.Event.getPageX(E);this.startY=YAHOO.util.Event.getPageY(E);this.deltaX=this.startX-C.offsetLeft;this.deltaY=this.startY-C.offsetTop;this.dragThreshMet=false;this.clickTimeout=setTimeout(function(){var F=YAHOO.util.DDM;F.startDrag(F.startX,F.startY);F.fromTimeout=true;},this.clickTimeThresh);},startDrag:function(C,E){if(this.dragCurrent&&this.dragCurrent.useShim){this._shimState=this.useShim;this.useShim=true;}this._activateShim();clearTimeout(this.clickTimeout);var D=this.dragCurrent;if(D&&D.events.b4StartDrag){D.b4StartDrag(C,E);D.fireEvent("b4StartDragEvent",{x:C,y:E});}if(D&&D.events.startDrag){D.startDrag(C,E);D.fireEvent("startDragEvent",{x:C,y:E});}this.dragThreshMet=true;},handleMouseUp:function(C){if(this.dragCurrent){clearTimeout(this.clickTimeout);if(this.dragThreshMet){if(this.fromTimeout){this.fromTimeout=false;this.handleMouseMove(C);}this.fromTimeout=false;this.fireEvents(C,true);}else{}this.stopDrag(C);this.stopEvent(C);}},stopEvent:function(C){if(this.stopPropagation){YAHOO.util.Event.stopPropagation(C);}if(this.preventDefault){YAHOO.util.Event.preventDefault(C);}},stopDrag:function(E,D){var C=this.dragCurrent;if(C&&!D){if(this.dragThreshMet){if(C.events.b4EndDrag){C.b4EndDrag(E);C.fireEvent("b4EndDragEvent",{e:E});}if(C.events.endDrag){C.endDrag(E);C.fireEvent("endDragEvent",{e:E});}}if(C.events.mouseUp){C.onMouseUp(E);C.fireEvent("mouseUpEvent",{e:E});}}if(this._shimActive){this._deactivateShim();if(this.dragCurrent&&this.dragCurrent.useShim){this.useShim=this._shimState;this._shimState=false;}}this.dragCurrent=null;this.dragOvers={};},handleMouseMove:function(F){var C=this.dragCurrent;if(C){if(YAHOO.env.ua.ie&&(YAHOO.env.ua.ie<9)&&!F.button){this.stopEvent(F);return this.handleMouseUp(F);}else{if(F.clientX<0||F.clientY<0){}}if(!this.dragThreshMet){var E=Math.abs(this.startX-YAHOO.util.Event.getPageX(F));var D=Math.abs(this.startY-YAHOO.util.Event.getPageY(F));if(E>this.clickPixelThresh||D>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}if(this.dragThreshMet){if(C&&C.events.b4Drag){C.b4Drag(F);C.fireEvent("b4DragEvent",{e:F});}if(C&&C.events.drag){C.onDrag(F);C.fireEvent("dragEvent",{e:F});}if(C){this.fireEvents(F,false);}}this.stopEvent(F);}},fireEvents:function(W,M){var c=this.dragCurrent;if(!c||c.isLocked()||c.dragOnly){return;}var O=YAHOO.util.Event.getPageX(W),N=YAHOO.util.Event.getPageY(W),Q=new YAHOO.util.Point(O,N),K=c.getTargetCoord(Q.x,Q.y),F=c.getDragEl(),E=["out","over","drop","enter"],V=new YAHOO.util.Region(K.y,K.x+F.offsetWidth,K.y+F.offsetHeight,K.x),I=[],D={},L={},R=[],d={outEvts:[],overEvts:[],dropEvts:[],enterEvts:[]};for(var T in this.dragOvers){var f=this.dragOvers[T];if(!this.isTypeOfDD(f)){continue;
+}if(!this.isOverTarget(Q,f,this.mode,V)){d.outEvts.push(f);}I[T]=true;delete this.dragOvers[T];}for(var S in c.groups){if("string"!=typeof S){continue;}for(T in this.ids[S]){var G=this.ids[S][T];if(!this.isTypeOfDD(G)){continue;}if(G.isTarget&&!G.isLocked()&&G!=c){if(this.isOverTarget(Q,G,this.mode,V)){D[S]=true;if(M){d.dropEvts.push(G);}else{if(!I[G.id]){d.enterEvts.push(G);}else{d.overEvts.push(G);}this.dragOvers[G.id]=G;}}}}}this.interactionInfo={out:d.outEvts,enter:d.enterEvts,over:d.overEvts,drop:d.dropEvts,point:Q,draggedRegion:V,sourceRegion:this.locationCache[c.id],validDrop:M};for(var C in D){R.push(C);}if(M&&!d.dropEvts.length){this.interactionInfo.validDrop=false;if(c.events.invalidDrop){c.onInvalidDrop(W);c.fireEvent("invalidDropEvent",{e:W});}}for(T=0;T<E.length;T++){var Z=null;if(d[E[T]+"Evts"]){Z=d[E[T]+"Evts"];}if(Z&&Z.length){var H=E[T].charAt(0).toUpperCase()+E[T].substr(1),Y="onDrag"+H,J="b4Drag"+H,P="drag"+H+"Event",X="drag"+H;if(this.mode){if(c.events[J]){c[J](W,Z,R);L[Y]=c.fireEvent(J+"Event",{event:W,info:Z,group:R});}if(c.events[X]&&(L[Y]!==false)){c[Y](W,Z,R);c.fireEvent(P,{event:W,info:Z,group:R});}}else{for(var a=0,U=Z.length;a<U;++a){if(c.events[J]){c[J](W,Z[a].id,R[0]);L[Y]=c.fireEvent(J+"Event",{event:W,info:Z[a].id,group:R[0]});}if(c.events[X]&&(L[Y]!==false)){c[Y](W,Z[a].id,R[0]);c.fireEvent(P,{event:W,info:Z[a].id,group:R[0]});}}}}}},getBestMatch:function(E){var G=null;var D=E.length;if(D==1){G=E[0];}else{for(var F=0;F<D;++F){var C=E[F];if(this.mode==this.INTERSECT&&C.cursorIsOver){G=C;break;}else{if(!G||!G.overlap||(C.overlap&&G.overlap.getArea()<C.overlap.getArea())){G=C;}}}}return G;},refreshCache:function(D){var F=D||this.ids;for(var C in F){if("string"!=typeof C){continue;}for(var E in this.ids[C]){var G=this.ids[C][E];if(this.isTypeOfDD(G)){var H=this.getLocation(G);if(H){this.locationCache[G.id]=H;}else{delete this.locationCache[G.id];}}}}},verifyEl:function(D){try{if(D){var C=D.offsetParent;if(C){return true;}}}catch(E){}return false;},getLocation:function(H){if(!this.isTypeOfDD(H)){return null;}var F=H.getEl(),K,E,D,M,L,N,C,J,G;try{K=YAHOO.util.Dom.getXY(F);}catch(I){}if(!K){return null;}E=K[0];D=E+F.offsetWidth;M=K[1];L=M+F.offsetHeight;N=M-H.padding[0];C=D+H.padding[1];J=L+H.padding[2];G=E-H.padding[3];return new YAHOO.util.Region(N,C,J,G);},isOverTarget:function(K,C,E,F){var G=this.locationCache[C.id];if(!G||!this.useCache){G=this.getLocation(C);this.locationCache[C.id]=G;}if(!G){return false;}C.cursorIsOver=G.contains(K);var J=this.dragCurrent;if(!J||(!E&&!J.constrainX&&!J.constrainY)){return C.cursorIsOver;}C.overlap=null;if(!F){var H=J.getTargetCoord(K.x,K.y);var D=J.getDragEl();F=new YAHOO.util.Region(H.y,H.x+D.offsetWidth,H.y+D.offsetHeight,H.x);}var I=F.intersect(G);if(I){C.overlap=I;return(E)?true:C.cursorIsOver;}else{return false;}},_onUnload:function(D,C){this.unregAll();},unregAll:function(){if(this.dragCurrent){this.stopDrag();this.dragCurrent=null;}this._execOnAll("unreg",[]);this.ids={};},elementCache:{},getElWrapper:function(D){var C=this.elementCache[D];if(!C||!C.el){C=this.elementCache[D]=new this.ElementWrapper(YAHOO.util.Dom.get(D));}return C;},getElement:function(C){return YAHOO.util.Dom.get(C);},getCss:function(D){var C=YAHOO.util.Dom.get(D);return(C)?C.style:null;},ElementWrapper:function(C){this.el=C||null;this.id=this.el&&C.id;this.css=this.el&&C.style;},getPosX:function(C){return YAHOO.util.Dom.getX(C);},getPosY:function(C){return YAHOO.util.Dom.getY(C);},swapNode:function(E,C){if(E.swapNode){E.swapNode(C);}else{var F=C.parentNode;var D=C.nextSibling;if(D==E){F.insertBefore(E,C);}else{if(C==E.nextSibling){F.insertBefore(C,E);}else{E.parentNode.replaceChild(C,E);F.insertBefore(E,D);}}}},getScroll:function(){var E,C,F=document.documentElement,D=document.body;if(F&&(F.scrollTop||F.scrollLeft)){E=F.scrollTop;C=F.scrollLeft;}else{if(D){E=D.scrollTop;C=D.scrollLeft;}else{}}return{top:E,left:C};},getStyle:function(D,C){return YAHOO.util.Dom.getStyle(D,C);},getScrollTop:function(){return this.getScroll().top;},getScrollLeft:function(){return this.getScroll().left;},moveToEl:function(C,E){var D=YAHOO.util.Dom.getXY(E);YAHOO.util.Dom.setXY(C,D);},getClientHeight:function(){return YAHOO.util.Dom.getViewportHeight();},getClientWidth:function(){return YAHOO.util.Dom.getViewportWidth();},numericSort:function(D,C){return(D-C);},_timeoutCount:0,_addListeners:function(){var C=YAHOO.util.DDM;if(YAHOO.util.Event&&document){C._onLoad();}else{if(C._timeoutCount>2000){}else{setTimeout(C._addListeners,10);if(document&&document.body){C._timeoutCount+=1;}}}},handleWasClicked:function(C,E){if(this.isHandle(E,C.id)){return true;}else{var D=C.parentNode;while(D){if(this.isHandle(E,D.id)){return true;}else{D=D.parentNode;}}}return false;}};}();YAHOO.util.DDM=YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function(){var A=YAHOO.util.Event;var B=YAHOO.util.Dom;YAHOO.util.DragDrop=function(E,C,D){if(E){this.init(E,C,D);}};YAHOO.util.DragDrop.prototype={events:null,on:function(){this.subscribe.apply(this,arguments);},id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isTarget:true,padding:null,dragOnly:false,useShim:false,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,deltaX:0,deltaY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,cursorIsOver:false,overlap:null,b4StartDrag:function(C,D){},startDrag:function(C,D){},b4Drag:function(C){},onDrag:function(C){},onDragEnter:function(C,D){},b4DragOver:function(C){},onDragOver:function(C,D){},b4DragOut:function(C){},onDragOut:function(C,D){},b4DragDrop:function(C){},onDragDrop:function(C,D){},onInvalidDrop:function(C){},b4EndDrag:function(C){},endDrag:function(C){},b4MouseDown:function(C){},onMouseDown:function(C){},onMouseUp:function(C){},onAvailable:function(){},getEl:function(){if(!this._domRef){this._domRef=B.get(this.id);
+}return this._domRef;},getDragEl:function(){return B.get(this.dragElId);},init:function(F,C,D){this.initTarget(F,C,D);A.on(this._domRef||this.id,"mousedown",this.handleMouseDown,this,true);for(var E in this.events){this.createEvent(E+"Event");}},initTarget:function(E,C,D){this.config=D||{};this.events={};this.DDM=YAHOO.util.DDM;this.groups={};if(typeof E!=="string"){this._domRef=E;E=B.generateId(E);}this.id=E;this.addToGroup((C)?C:"default");this.handleElId=E;A.onAvailable(E,this.handleOnAvailable,this,true);this.setDragElId(E);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();},applyConfig:function(){this.events={mouseDown:true,b4MouseDown:true,mouseUp:true,b4StartDrag:true,startDrag:true,b4EndDrag:true,endDrag:true,drag:true,b4Drag:true,invalidDrop:true,b4DragOut:true,dragOut:true,dragEnter:true,b4DragOver:true,dragOver:true,b4DragDrop:true,dragDrop:true};if(this.config.events){for(var C in this.config.events){if(this.config.events[C]===false){this.events[C]=false;}}}this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);this.dragOnly=((this.config.dragOnly===true)?true:false);this.useShim=((this.config.useShim===true)?true:false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(E,C,F,D){if(!C&&0!==C){this.padding=[E,E,E,E];}else{if(!F&&0!==F){this.padding=[E,C,E,C];}else{this.padding=[E,C,F,D];}}},setInitPosition:function(F,E){var G=this.getEl();if(!this.DDM.verifyEl(G)){if(G&&G.style&&(G.style.display=="none")){}else{}return;}var D=F||0;var C=E||0;var H=B.getXY(G);this.initPageX=H[0]-D;this.initPageY=H[1]-C;this.lastPageX=H[0];this.lastPageY=H[1];this.setStartPosition(H);},setStartPosition:function(D){var C=D||B.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=C[0];this.startPageY=C[1];},addToGroup:function(C){this.groups[C]=true;this.DDM.regDragDrop(this,C);},removeFromGroup:function(C){if(this.groups[C]){delete this.groups[C];}this.DDM.removeDDFromGroup(this,C);},setDragElId:function(C){this.dragElId=C;},setHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.handleElId=C;this.DDM.regHandle(this.id,C);},setOuterHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}A.on(C,"mousedown",this.handleMouseDown,this,true);this.setHandleElId(C);this.hasOuterHandles=true;},unreg:function(){A.removeListener(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(J,I){var D=J.which||J.button;if(this.primaryButtonOnly&&D>1){return;}if(this.isLocked()){return;}var C=this.b4MouseDown(J),F=true;if(this.events.b4MouseDown){F=this.fireEvent("b4MouseDownEvent",J);}var E=this.onMouseDown(J),H=true;if(this.events.mouseDown){if(E===false){H=false;}else{H=this.fireEvent("mouseDownEvent",J);}}if((C===false)||(E===false)||(F===false)||(H===false)){return;}this.DDM.refreshCache(this.groups);var G=new YAHOO.util.Point(A.getPageX(J),A.getPageY(J));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(G,this)){}else{if(this.clickValidator(J)){this.setStartPosition();this.DDM.handleMouseDown(J,this);this.DDM.stopEvent(J);}else{}}},clickValidator:function(D){var C=YAHOO.util.Event.getTarget(D);return(this.isValidHandleChild(C)&&(this.id==this.handleElId||this.DDM.handleWasClicked(C,this.id)));},getTargetCoord:function(E,D){var C=E-this.deltaX;var F=D-this.deltaY;if(this.constrainX){if(C<this.minX){C=this.minX;}if(C>this.maxX){C=this.maxX;}}if(this.constrainY){if(F<this.minY){F=this.minY;}if(F>this.maxY){F=this.maxY;}}C=this.getTick(C,this.xTicks);F=this.getTick(F,this.yTicks);return{x:C,y:F};},addInvalidHandleType:function(C){var D=C.toUpperCase();this.invalidHandleTypes[D]=D;},addInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.invalidHandleIds[C]=C;},addInvalidHandleClass:function(C){this.invalidHandleClasses.push(C);},removeInvalidHandleType:function(C){var D=C.toUpperCase();delete this.invalidHandleTypes[D];},removeInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}delete this.invalidHandleIds[C];},removeInvalidHandleClass:function(D){for(var E=0,C=this.invalidHandleClasses.length;E<C;++E){if(this.invalidHandleClasses[E]==D){delete this.invalidHandleClasses[E];}}},isValidHandleChild:function(F){var E=true;var H;try{H=F.nodeName.toUpperCase();}catch(G){H=F.nodeName;}E=E&&!this.invalidHandleTypes[H];E=E&&!this.invalidHandleIds[F.id];for(var D=0,C=this.invalidHandleClasses.length;E&&D<C;++D){E=!B.hasClass(F,this.invalidHandleClasses[D]);}return E;},setXTicks:function(F,C){this.xTicks=[];this.xTickSize=C;var E={};for(var D=this.initPageX;D>=this.minX;D=D-C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}for(D=this.initPageX;D<=this.maxX;D=D+C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(F,C){this.yTicks=[];this.yTickSize=C;var E={};for(var D=this.initPageY;D>=this.minY;D=D-C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}for(D=this.initPageY;D<=this.maxY;D=D+C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(E,D,C){this.leftConstraint=parseInt(E,10);this.rightConstraint=parseInt(D,10);this.minX=this.initPageX-this.leftConstraint;this.maxX=this.initPageX+this.rightConstraint;if(C){this.setXTicks(this.initPageX,C);}this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(C,E,D){this.topConstraint=parseInt(C,10);this.bottomConstraint=parseInt(E,10);this.minY=this.initPageY-this.topConstraint;this.maxY=this.initPageY+this.bottomConstraint;
+if(D){this.setYTicks(this.initPageY,D);}this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var D=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var C=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(D,C);}else{this.setInitPosition();}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(I,F){if(!F){return I;}else{if(F[0]>=I){return F[0];}else{for(var D=0,C=F.length;D<C;++D){var E=D+1;if(F[E]&&F[E]>=I){var H=I-F[D];var G=F[E]-I;return(G>H)?F[D]:F[E];}}return F[F.length-1];}}},toString:function(){return("DragDrop "+this.id);}};YAHOO.augment(YAHOO.util.DragDrop,YAHOO.util.EventProvider);})();YAHOO.util.DD=function(C,A,B){if(C){this.init(C,A,B);}};YAHOO.extend(YAHOO.util.DD,YAHOO.util.DragDrop,{scroll:true,autoOffset:function(C,B){var A=C-this.startPageX;var D=B-this.startPageY;this.setDelta(A,D);},setDelta:function(B,A){this.deltaX=B;this.deltaY=A;},setDragElPos:function(C,B){var A=this.getDragEl();this.alignElWithMouse(A,C,B);},alignElWithMouse:function(C,G,F){var E=this.getTargetCoord(G,F);if(!this.deltaSetXY){var H=[E.x,E.y];YAHOO.util.Dom.setXY(C,H);var D=parseInt(YAHOO.util.Dom.getStyle(C,"left"),10);var B=parseInt(YAHOO.util.Dom.getStyle(C,"top"),10);this.deltaSetXY=[D-E.x,B-E.y];}else{YAHOO.util.Dom.setStyle(C,"left",(E.x+this.deltaSetXY[0])+"px");YAHOO.util.Dom.setStyle(C,"top",(E.y+this.deltaSetXY[1])+"px");}this.cachePosition(E.x,E.y);var A=this;setTimeout(function(){A.autoScroll.call(A,E.x,E.y,C.offsetHeight,C.offsetWidth);},0);},cachePosition:function(B,A){if(B){this.lastPageX=B;this.lastPageY=A;}else{var C=YAHOO.util.Dom.getXY(this.getEl());this.lastPageX=C[0];this.lastPageY=C[1];}},autoScroll:function(J,I,E,K){if(this.scroll){var L=this.DDM.getClientHeight();var B=this.DDM.getClientWidth();var N=this.DDM.getScrollTop();var D=this.DDM.getScrollLeft();var H=E+I;var M=K+J;var G=(L+N-I-this.deltaY);var F=(B+D-J-this.deltaX);var C=40;var A=(document.all)?80:30;if(H>L&&G<C){window.scrollTo(D,N+A);}if(I<N&&N>0&&I-N<C){window.scrollTo(D,N-A);}if(M>B&&F<C){window.scrollTo(D+A,N);}if(J<D&&D>0&&J-D<C){window.scrollTo(D-A,N);}}},applyConfig:function(){YAHOO.util.DD.superclass.applyConfig.call(this);this.scroll=(this.config.scroll!==false);},b4MouseDown:function(A){this.setStartPosition();this.autoOffset(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},b4Drag:function(A){this.setDragElPos(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},toString:function(){return("DD "+this.id);}});YAHOO.util.DDProxy=function(C,A,B){if(C){this.init(C,A,B);this.initFrame();}};YAHOO.util.DDProxy.dragElId="ygddfdiv";YAHOO.extend(YAHOO.util.DDProxy,YAHOO.util.DD,{resizeFrame:true,centerFrame:false,createFrame:function(){var B=this,A=document.body;if(!A||!A.firstChild){setTimeout(function(){B.createFrame();},50);return;}var F=this.getDragEl(),E=YAHOO.util.Dom;if(!F){F=document.createElement("div");F.id=this.dragElId;var D=F.style;D.position="absolute";D.visibility="hidden";D.cursor="move";D.border="2px solid #aaa";D.zIndex=999;D.height="25px";D.width="25px";var C=document.createElement("div");E.setStyle(C,"height","100%");E.setStyle(C,"width","100%");E.setStyle(C,"background-color","#ccc");E.setStyle(C,"opacity","0");F.appendChild(C);A.insertBefore(F,A.firstChild);}},initFrame:function(){this.createFrame();},applyConfig:function(){YAHOO.util.DDProxy.superclass.applyConfig.call(this);this.resizeFrame=(this.config.resizeFrame!==false);this.centerFrame=(this.config.centerFrame);this.setDragElId(this.config.dragElId||YAHOO.util.DDProxy.dragElId);},showFrame:function(E,D){var C=this.getEl();var A=this.getDragEl();var B=A.style;this._resizeProxy();if(this.centerFrame){this.setDelta(Math.round(parseInt(B.width,10)/2),Math.round(parseInt(B.height,10)/2));}this.setDragElPos(E,D);YAHOO.util.Dom.setStyle(A,"visibility","visible");},_resizeProxy:function(){if(this.resizeFrame){var H=YAHOO.util.Dom;var B=this.getEl();var C=this.getDragEl();var G=parseInt(H.getStyle(C,"borderTopWidth"),10);var I=parseInt(H.getStyle(C,"borderRightWidth"),10);var F=parseInt(H.getStyle(C,"borderBottomWidth"),10);var D=parseInt(H.getStyle(C,"borderLeftWidth"),10);if(isNaN(G)){G=0;}if(isNaN(I)){I=0;}if(isNaN(F)){F=0;}if(isNaN(D)){D=0;}var E=Math.max(0,B.offsetWidth-I-D);var A=Math.max(0,B.offsetHeight-G-F);H.setStyle(C,"width",E+"px");H.setStyle(C,"height",A+"px");}},b4MouseDown:function(B){this.setStartPosition();var A=YAHOO.util.Event.getPageX(B);var C=YAHOO.util.Event.getPageY(B);this.autoOffset(A,C);},b4StartDrag:function(A,B){this.showFrame(A,B);},b4EndDrag:function(A){YAHOO.util.Dom.setStyle(this.getDragEl(),"visibility","hidden");},endDrag:function(D){var C=YAHOO.util.Dom;var B=this.getEl();var A=this.getDragEl();C.setStyle(A,"visibility","");C.setStyle(B,"visibility","hidden");YAHOO.util.DDM.moveToEl(B,A);C.setStyle(A,"visibility","hidden");C.setStyle(B,"visibility","");},toString:function(){return("DDProxy "+this.id);}});YAHOO.util.DDTarget=function(C,A,B){if(C){this.initTarget(C,A,B);}};YAHOO.extend(YAHOO.util.DDTarget,YAHOO.util.DragDrop,{toString:function(){return("DDTarget "+this.id);}});YAHOO.register("dragdrop",YAHOO.util.DragDropMgr,{version:"2.9.0",build:"2800"});YAHOO.util.Attribute=function(b,a){if(a){this.owner=a;this.configure(b,true);}};YAHOO.util.Attribute.INVALID_VALUE={};YAHOO.util.Attribute.prototype={name:undefined,value:null,owner:null,readOnly:false,writeOnce:false,_initialConfig:null,_written:false,method:null,setter:null,getter:null,validator:null,getValue:function(){var a=this.value;if(this.getter){a=this.getter.call(this.owner,this.name,a);}return a;},setValue:function(f,b){var e,a=this.owner,c=this.name,g=YAHOO.util.Attribute.INVALID_VALUE,d={type:c,prevValue:this.getValue(),newValue:f};if(this.readOnly||(this.writeOnce&&this._written)){return false;}if(this.validator&&!this.validator.call(a,f)){return false;}if(!b){e=a.fireBeforeChangeEvent(d);if(e===false){return false;}}if(this.setter){f=this.setter.call(a,f,this.name);if(f===undefined){}if(f===g){return false;}}if(this.method){if(this.method.call(a,f,this.name)===g){return false;}}this.value=f;this._written=true;d.type=c;if(!b){this.owner.fireChangeEvent(d);}return true;},configure:function(b,c){b=b||{};if(c){this._written=false;}this._initialConfig=this._initialConfig||{};for(var a in b){if(b.hasOwnProperty(a)){this[a]=b[a];if(c){this._initialConfig[a]=b[a];}}}},resetValue:function(){return this.setValue(this._initialConfig.value);},resetConfig:function(){this.configure(this._initialConfig,true);},refresh:function(a){this.setValue(this.value,a);}};(function(){var a=YAHOO.util.Lang;YAHOO.util.AttributeProvider=function(){};YAHOO.util.AttributeProvider.prototype={_configs:null,get:function(c){this._configs=this._configs||{};var b=this._configs[c];if(!b||!this._configs.hasOwnProperty(c)){return null;}return b.getValue();},set:function(d,e,b){this._configs=this._configs||{};var c=this._configs[d];if(!c){return false;}return c.setValue(e,b);},getAttributeKeys:function(){this._configs=this._configs;var c=[],b;for(b in this._configs){if(a.hasOwnProperty(this._configs,b)&&!a.isUndefined(this._configs[b])){c[c.length]=b;}}return c;},setAttributes:function(d,b){for(var c in d){if(a.hasOwnProperty(d,c)){this.set(c,d[c],b);}}},resetValue:function(c,b){this._configs=this._configs||{};if(this._configs[c]){this.set(c,this._configs[c]._initialConfig.value,b);return true;}return false;},refresh:function(e,c){this._configs=this._configs||{};var f=this._configs;e=((a.isString(e))?[e]:e)||this.getAttributeKeys();for(var d=0,b=e.length;d<b;++d){if(f.hasOwnProperty(e[d])){this._configs[e[d]].refresh(c);}}},register:function(b,c){this.setAttributeConfig(b,c);},getAttributeConfig:function(c){this._configs=this._configs||{};var b=this._configs[c]||{};var d={};for(c in b){if(a.hasOwnProperty(b,c)){d[c]=b[c];}}return d;},setAttributeConfig:function(b,c,d){this._configs=this._configs||{};c=c||{};if(!this._configs[b]){c.name=b;this._configs[b]=this.createAttribute(c);}else{this._configs[b].configure(c,d);}},configureAttribute:function(b,c,d){this.setAttributeConfig(b,c,d);},resetAttributeConfig:function(b){this._configs=this._configs||{};this._configs[b].resetConfig();},subscribe:function(b,c){this._events=this._events||{};if(!(b in this._events)){this._events[b]=this.createEvent(b);}YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){this.subscribe.apply(this,arguments);},addListener:function(){this.subscribe.apply(this,arguments);},fireBeforeChangeEvent:function(c){var b="before";b+=c.type.charAt(0).toUpperCase()+c.type.substr(1)+"Change";c.type=b;return this.fireEvent(c.type,c);},fireChangeEvent:function(b){b.type+="Change";return this.fireEvent(b.type,b);},createAttribute:function(b){return new YAHOO.util.Attribute(b,this);}};YAHOO.augment(YAHOO.util.AttributeProvider,YAHOO.util.EventProvider);})();(function(){var b=YAHOO.util.Dom,d=YAHOO.util.AttributeProvider,c={mouseenter:true,mouseleave:true};var a=function(e,f){this.init.apply(this,arguments);};a.DOM_EVENTS={"click":true,"dblclick":true,"keydown":true,"keypress":true,"keyup":true,"mousedown":true,"mousemove":true,"mouseout":true,"mouseover":true,"mouseup":true,"mouseenter":true,"mouseleave":true,"focus":true,"blur":true,"submit":true,"change":true};a.prototype={DOM_EVENTS:null,DEFAULT_HTML_SETTER:function(g,e){var f=this.get("element");if(f){f[e]=g;}return g;},DEFAULT_HTML_GETTER:function(e){var f=this.get("element"),g;if(f){g=f[e];}return g;},appendChild:function(e){e=e.get?e.get("element"):e;return this.get("element").appendChild(e);},getElementsByTagName:function(e){return this.get("element").getElementsByTagName(e);},hasChildNodes:function(){return this.get("element").hasChildNodes();},insertBefore:function(e,f){e=e.get?e.get("element"):e;f=(f&&f.get)?f.get("element"):f;return this.get("element").insertBefore(e,f);},removeChild:function(e){e=e.get?e.get("element"):e;return this.get("element").removeChild(e);},replaceChild:function(e,f){e=e.get?e.get("element"):e;f=f.get?f.get("element"):f;return this.get("element").replaceChild(e,f);},initAttributes:function(e){},addListener:function(j,i,k,h){h=h||this;var e=YAHOO.util.Event,g=this.get("element")||this.get("id"),f=this;if(c[j]&&!e._createMouseDelegate){return false;}if(!this._events[j]){if(g&&this.DOM_EVENTS[j]){e.on(g,j,function(m,l){if(m.srcElement&&!m.target){m.target=m.srcElement;}if((m.toElement&&!m.relatedTarget)||(m.fromElement&&!m.relatedTarget)){m.relatedTarget=e.getRelatedTarget(m);}if(!m.currentTarget){m.currentTarget=g;}f.fireEvent(j,m,l);},k,h);}this.createEvent(j,{scope:this});}return YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){return this.addListener.apply(this,arguments);},subscribe:function(){return this.addListener.apply(this,arguments);},removeListener:function(f,e){return this.unsubscribe.apply(this,arguments);},addClass:function(e){b.addClass(this.get("element"),e);},getElementsByClassName:function(f,e){return b.getElementsByClassName(f,e,this.get("element"));},hasClass:function(e){return b.hasClass(this.get("element"),e);},removeClass:function(e){return b.removeClass(this.get("element"),e);},replaceClass:function(f,e){return b.replaceClass(this.get("element"),f,e);
+},setStyle:function(f,e){return b.setStyle(this.get("element"),f,e);},getStyle:function(e){return b.getStyle(this.get("element"),e);},fireQueue:function(){var f=this._queue;for(var g=0,e=f.length;g<e;++g){this[f[g][0]].apply(this,f[g][1]);}},appendTo:function(f,g){f=(f.get)?f.get("element"):b.get(f);this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:f});g=(g&&g.get)?g.get("element"):b.get(g);var e=this.get("element");if(!e){return false;}if(!f){return false;}if(e.parent!=f){if(g){f.insertBefore(e,g);}else{f.appendChild(e);}}this.fireEvent("appendTo",{type:"appendTo",target:f});return e;},get:function(e){var g=this._configs||{},f=g.element;if(f&&!g[e]&&!YAHOO.lang.isUndefined(f.value[e])){this._setHTMLAttrConfig(e);}return d.prototype.get.call(this,e);},setAttributes:function(l,h){var f={},j=this._configOrder;for(var k=0,e=j.length;k<e;++k){if(l[j[k]]!==undefined){f[j[k]]=true;this.set(j[k],l[j[k]],h);}}for(var g in l){if(l.hasOwnProperty(g)&&!f[g]){this.set(g,l[g],h);}}},set:function(f,h,e){var g=this.get("element");if(!g){this._queue[this._queue.length]=["set",arguments];if(this._configs[f]){this._configs[f].value=h;}return;}if(!this._configs[f]&&!YAHOO.lang.isUndefined(g[f])){this._setHTMLAttrConfig(f);}return d.prototype.set.apply(this,arguments);},setAttributeConfig:function(e,f,g){this._configOrder.push(e);d.prototype.setAttributeConfig.apply(this,arguments);},createEvent:function(f,e){this._events[f]=true;return d.prototype.createEvent.apply(this,arguments);},init:function(f,e){this._initElement(f,e);},destroy:function(){var e=this.get("element");YAHOO.util.Event.purgeElement(e,true);this.unsubscribeAll();if(e&&e.parentNode){e.parentNode.removeChild(e);}this._queue=[];this._events={};this._configs={};this._configOrder=[];},_initElement:function(g,f){this._queue=this._queue||[];this._events=this._events||{};this._configs=this._configs||{};this._configOrder=[];f=f||{};f.element=f.element||g||null;var i=false;var e=a.DOM_EVENTS;this.DOM_EVENTS=this.DOM_EVENTS||{};for(var h in e){if(e.hasOwnProperty(h)){this.DOM_EVENTS[h]=e[h];}}if(typeof f.element==="string"){this._setHTMLAttrConfig("id",{value:f.element});}if(b.get(f.element)){i=true;this._initHTMLElement(f);this._initContent(f);}YAHOO.util.Event.onAvailable(f.element,function(){if(!i){this._initHTMLElement(f);}this.fireEvent("available",{type:"available",target:b.get(f.element)});},this,true);YAHOO.util.Event.onContentReady(f.element,function(){if(!i){this._initContent(f);}this.fireEvent("contentReady",{type:"contentReady",target:b.get(f.element)});},this,true);},_initHTMLElement:function(e){this.setAttributeConfig("element",{value:b.get(e.element),readOnly:true});},_initContent:function(e){this.initAttributes(e);this.setAttributes(e,true);this.fireQueue();},_setHTMLAttrConfig:function(e,g){var f=this.get("element");g=g||{};g.name=e;g.setter=g.setter||this.DEFAULT_HTML_SETTER;g.getter=g.getter||this.DEFAULT_HTML_GETTER;g.value=g.value||f[e];this._configs[e]=new YAHOO.util.Attribute(g,this);}};YAHOO.augment(a,d);YAHOO.util.Element=a;})();YAHOO.register("element",YAHOO.util.Element,{version:"2.9.0",build:"2800"});YAHOO.register("utilities", YAHOO, {version: "2.9.0", build: "2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+(function(){var lang=YAHOO.lang,util=YAHOO.util,Ev=util.Event;util.DataSourceBase=function(oLiveData,oConfigs){if(oLiveData===null||oLiveData===undefined){return;}this.liveData=oLiveData;this._oQueue={interval:null,conn:null,requests:[]};this.responseSchema={};if(oConfigs&&(oConfigs.constructor==Object)){for(var sConfig in oConfigs){if(sConfig){this[sConfig]=oConfigs[sConfig];}}}var maxCacheEntries=this.maxCacheEntries;if(!lang.isNumber(maxCacheEntries)||(maxCacheEntries<0)){maxCacheEntries=0;}this._aIntervals=[];this.createEvent("cacheRequestEvent");this.createEvent("cacheResponseEvent");this.createEvent("requestEvent");this.createEvent("responseEvent");this.createEvent("responseParseEvent");this.createEvent("responseCacheEvent");this.createEvent("dataErrorEvent");this.createEvent("cacheFlushEvent");var DS=util.DataSourceBase;this._sName="DataSource instance"+DS._nIndex;DS._nIndex++;};var DS=util.DataSourceBase;lang.augmentObject(DS,{TYPE_UNKNOWN:-1,TYPE_JSARRAY:0,TYPE_JSFUNCTION:1,TYPE_XHR:2,TYPE_JSON:3,TYPE_XML:4,TYPE_TEXT:5,TYPE_HTMLTABLE:6,TYPE_SCRIPTNODE:7,TYPE_LOCAL:8,ERROR_DATAINVALID:"Invalid data",ERROR_DATANULL:"Null data",_nIndex:0,_nTransactionId:0,_cloneObject:function(o){if(!lang.isValue(o)){return o;}var copy={};if(Object.prototype.toString.apply(o)==="[object RegExp]"){copy=o;}else{if(lang.isFunction(o)){copy=o;}else{if(lang.isArray(o)){var array=[];for(var i=0,len=o.length;i<len;i++){array[i]=DS._cloneObject(o[i]);}copy=array;}else{if(lang.isObject(o)){for(var x in o){if(lang.hasOwnProperty(o,x)){if(lang.isValue(o[x])&&lang.isObject(o[x])||lang.isArray(o[x])){copy[x]=DS._cloneObject(o[x]);}else{copy[x]=o[x];}}}}else{copy=o;}}}}return copy;},_getLocationValue:function(field,context){var locator=field.locator||field.key||field,xmldoc=context.ownerDocument||context,result,res,value=null;try{if(!lang.isUndefined(xmldoc.evaluate)){result=xmldoc.evaluate(locator,context,xmldoc.createNSResolver(!context.ownerDocument?context.documentElement:context.ownerDocument.documentElement),0,null);while(res=result.iterateNext()){value=res.textContent;}}else{xmldoc.setProperty("SelectionLanguage","XPath");result=context.selectNodes(locator)[0];value=result.value||result.text||null;}return value;}catch(e){}},issueCallback:function(callback,params,error,scope){if(lang.isFunction(callback)){callback.apply(scope,params);}else{if(lang.isObject(callback)){scope=callback.scope||scope||window;var callbackFunc=callback.success;if(error){callbackFunc=callback.failure;}if(callbackFunc){callbackFunc.apply(scope,params.concat([callback.argument]));}}}},parseString:function(oData){if(!lang.isValue(oData)){return null;}var string=oData+"";if(lang.isString(string)){return string;}else{return null;}},parseNumber:function(oData){if(!lang.isValue(oData)||(oData==="")){return null;}var number=oData*1;if(lang.isNumber(number)){return number;}else{return null;}},convertNumber:function(oData){return DS.parseNumber(oData);},parseDate:function(oData){var date=null;if(lang.isValue(oData)&&!(oData instanceof Date)){date=new Date(oData);}else{return oData;}if(date instanceof Date){return date;}else{return null;}},convertDate:function(oData){return DS.parseDate(oData);}});DS.Parser={string:DS.parseString,number:DS.parseNumber,date:DS.parseDate};DS.prototype={_sName:null,_aCache:null,_oQueue:null,_aIntervals:null,maxCacheEntries:0,liveData:null,dataType:DS.TYPE_UNKNOWN,responseType:DS.TYPE_UNKNOWN,responseSchema:null,useXPath:false,cloneBeforeCaching:false,toString:function(){return this._sName;},getCachedResponse:function(oRequest,oCallback,oCaller){var aCache=this._aCache;if(this.maxCacheEntries>0){if(!aCache){this._aCache=[];}else{var nCacheLength=aCache.length;if(nCacheLength>0){var oResponse=null;this.fireEvent("cacheRequestEvent",{request:oRequest,callback:oCallback,caller:oCaller});for(var i=nCacheLength-1;i>=0;i--){var oCacheElem=aCache[i];if(this.isCacheHit(oRequest,oCacheElem.request)){oResponse=oCacheElem.response;this.fireEvent("cacheResponseEvent",{request:oRequest,response:oResponse,callback:oCallback,caller:oCaller});if(i<nCacheLength-1){aCache.splice(i,1);this.addToCache(oRequest,oResponse);}oResponse.cached=true;break;}}return oResponse;}}}else{if(aCache){this._aCache=null;}}return null;},isCacheHit:function(oRequest,oCachedRequest){return(oRequest===oCachedRequest);},addToCache:function(oRequest,oResponse){var aCache=this._aCache;if(!aCache){return;}while(aCache.length>=this.maxCacheEntries){aCache.shift();}oResponse=(this.cloneBeforeCaching)?DS._cloneObject(oResponse):oResponse;var oCacheElem={request:oRequest,response:oResponse};aCache[aCache.length]=oCacheElem;this.fireEvent("responseCacheEvent",{request:oRequest,response:oResponse});},flushCache:function(){if(this._aCache){this._aCache=[];this.fireEvent("cacheFlushEvent");}},setInterval:function(nMsec,oRequest,oCallback,oCaller){if(lang.isNumber(nMsec)&&(nMsec>=0)){var oSelf=this;var nId=setInterval(function(){oSelf.makeConnection(oRequest,oCallback,oCaller);},nMsec);this._aIntervals.push(nId);return nId;}else{}},clearInterval:function(nId){var tracker=this._aIntervals||[];for(var i=tracker.length-1;i>-1;i--){if(tracker[i]===nId){tracker.splice(i,1);clearInterval(nId);}}},clearAllIntervals:function(){var tracker=this._aIntervals||[];for(var i=tracker.length-1;i>-1;i--){clearInterval(tracker[i]);}tracker=[];},sendRequest:function(oRequest,oCallback,oCaller){var oCachedResponse=this.getCachedResponse(oRequest,oCallback,oCaller);if(oCachedResponse){DS.issueCallback(oCallback,[oRequest,oCachedResponse],false,oCaller);return null;}return this.makeConnection(oRequest,oCallback,oCaller);},makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oRawResponse=this.liveData;this.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);return tId;},handleResponse:function(oRequest,oRawResponse,oCallback,oCaller,tId){this.fireEvent("responseEvent",{tId:tId,request:oRequest,response:oRawResponse,callback:oCallback,caller:oCaller});
+var xhr=(this.dataType==DS.TYPE_XHR)?true:false;var oParsedResponse=null;var oFullResponse=oRawResponse;if(this.responseType===DS.TYPE_UNKNOWN){var ctype=(oRawResponse&&oRawResponse.getResponseHeader)?oRawResponse.getResponseHeader["Content-Type"]:null;if(ctype){if(ctype.indexOf("text/xml")>-1){this.responseType=DS.TYPE_XML;}else{if(ctype.indexOf("application/json")>-1){this.responseType=DS.TYPE_JSON;}else{if(ctype.indexOf("text/plain")>-1){this.responseType=DS.TYPE_TEXT;}}}}else{if(YAHOO.lang.isArray(oRawResponse)){this.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse&&oRawResponse.nodeType&&(oRawResponse.nodeType===9||oRawResponse.nodeType===1||oRawResponse.nodeType===11)){this.responseType=DS.TYPE_XML;}else{if(oRawResponse&&oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){this.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){this.responseType=DS.TYPE_TEXT;}}}}}}}switch(this.responseType){case DS.TYPE_JSARRAY:if(xhr&&oRawResponse&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}try{if(lang.isString(oFullResponse)){var parseArgs=[oFullResponse].concat(this.parseJSONArgs);if(lang.JSON){oFullResponse=lang.JSON.parse.apply(lang.JSON,parseArgs);}else{if(window.JSON&&JSON.parse){oFullResponse=JSON.parse.apply(JSON,parseArgs);}else{if(oFullResponse.parseJSON){oFullResponse=oFullResponse.parseJSON.apply(oFullResponse,parseArgs.slice(1));}else{while(oFullResponse.length>0&&(oFullResponse.charAt(0)!="{")&&(oFullResponse.charAt(0)!="[")){oFullResponse=oFullResponse.substring(1,oFullResponse.length);}if(oFullResponse.length>0){var arrayEnd=Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));oFullResponse=oFullResponse.substring(0,arrayEnd+1);oFullResponse=eval("("+oFullResponse+")");}}}}}}catch(e1){}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseArrayData(oRequest,oFullResponse);break;case DS.TYPE_JSON:if(xhr&&oRawResponse&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}try{if(lang.isString(oFullResponse)){var parseArgs=[oFullResponse].concat(this.parseJSONArgs);if(lang.JSON){oFullResponse=lang.JSON.parse.apply(lang.JSON,parseArgs);}else{if(window.JSON&&JSON.parse){oFullResponse=JSON.parse.apply(JSON,parseArgs);}else{if(oFullResponse.parseJSON){oFullResponse=oFullResponse.parseJSON.apply(oFullResponse,parseArgs.slice(1));}else{while(oFullResponse.length>0&&(oFullResponse.charAt(0)!="{")&&(oFullResponse.charAt(0)!="[")){oFullResponse=oFullResponse.substring(1,oFullResponse.length);}if(oFullResponse.length>0){var objEnd=Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));oFullResponse=oFullResponse.substring(0,objEnd+1);oFullResponse=eval("("+oFullResponse+")");}}}}}}catch(e){}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseJSONData(oRequest,oFullResponse);break;case DS.TYPE_HTMLTABLE:if(xhr&&oRawResponse.responseText){var el=document.createElement("div");el.innerHTML=oRawResponse.responseText;oFullResponse=el.getElementsByTagName("table")[0];}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseHTMLTableData(oRequest,oFullResponse);break;case DS.TYPE_XML:if(xhr&&oRawResponse.responseXML){oFullResponse=oRawResponse.responseXML;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseXMLData(oRequest,oFullResponse);break;case DS.TYPE_TEXT:if(xhr&&lang.isString(oRawResponse.responseText)){oFullResponse=oRawResponse.responseText;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseTextData(oRequest,oFullResponse);break;default:oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseData(oRequest,oFullResponse);break;}oParsedResponse=oParsedResponse||{};if(!oParsedResponse.results){oParsedResponse.results=[];}if(!oParsedResponse.meta){oParsedResponse.meta={};}if(!oParsedResponse.error){oParsedResponse=this.doBeforeCallback(oRequest,oFullResponse,oParsedResponse,oCallback);this.fireEvent("responseParseEvent",{request:oRequest,response:oParsedResponse,callback:oCallback,caller:oCaller});this.addToCache(oRequest,oParsedResponse);}else{oParsedResponse.error=true;this.fireEvent("dataErrorEvent",{request:oRequest,response:oRawResponse,callback:oCallback,caller:oCaller,message:DS.ERROR_DATANULL});}oParsedResponse.tId=tId;DS.issueCallback(oCallback,[oRequest,oParsedResponse],oParsedResponse.error,oCaller);},doBeforeParseData:function(oRequest,oFullResponse,oCallback){return oFullResponse;},doBeforeCallback:function(oRequest,oFullResponse,oParsedResponse,oCallback){return oParsedResponse;},parseData:function(oRequest,oFullResponse){if(lang.isValue(oFullResponse)){var oParsedResponse={results:oFullResponse,meta:{}};return oParsedResponse;}return null;},parseArrayData:function(oRequest,oFullResponse){if(lang.isArray(oFullResponse)){var results=[],i,j,rec,field,data;if(lang.isArray(this.responseSchema.fields)){var fields=this.responseSchema.fields;for(i=fields.length-1;i>=0;--i){if(typeof fields[i]!=="object"){fields[i]={key:fields[i]};}}var parsers={},p;for(i=fields.length-1;i>=0;--i){p=(typeof fields[i].parser==="function"?fields[i].parser:DS.Parser[fields[i].parser+""])||fields[i].converter;if(p){parsers[fields[i].key]=p;}}var arrType=lang.isArray(oFullResponse[0]);for(i=oFullResponse.length-1;i>-1;i--){var oResult={};rec=oFullResponse[i];if(typeof rec==="object"){for(j=fields.length-1;j>-1;j--){field=fields[j];data=arrType?rec[j]:rec[field.key];if(parsers[field.key]){data=parsers[field.key].call(this,data);}if(data===undefined){data=null;}oResult[field.key]=data;}}else{if(lang.isString(rec)){for(j=fields.length-1;j>-1;j--){field=fields[j];data=rec;if(parsers[field.key]){data=parsers[field.key].call(this,data);}if(data===undefined){data=null;}oResult[field.key]=data;
+}}}results[i]=oResult;}}else{results=oFullResponse;}var oParsedResponse={results:results};return oParsedResponse;}return null;},parseTextData:function(oRequest,oFullResponse){if(lang.isString(oFullResponse)){if(lang.isString(this.responseSchema.recordDelim)&&lang.isString(this.responseSchema.fieldDelim)){var oParsedResponse={results:[]};var recDelim=this.responseSchema.recordDelim;var fieldDelim=this.responseSchema.fieldDelim;if(oFullResponse.length>0){var newLength=oFullResponse.length-recDelim.length;if(oFullResponse.substr(newLength)==recDelim){oFullResponse=oFullResponse.substr(0,newLength);}if(oFullResponse.length>0){var recordsarray=oFullResponse.split(recDelim);for(var i=0,len=recordsarray.length,recIdx=0;i<len;++i){var bError=false,sRecord=recordsarray[i];if(lang.isString(sRecord)&&(sRecord.length>0)){var fielddataarray=recordsarray[i].split(fieldDelim);var oResult={};if(lang.isArray(this.responseSchema.fields)){var fields=this.responseSchema.fields;for(var j=fields.length-1;j>-1;j--){try{var data=fielddataarray[j];if(lang.isString(data)){if(data.charAt(0)=='"'){data=data.substr(1);}if(data.charAt(data.length-1)=='"'){data=data.substr(0,data.length-1);}var field=fields[j];var key=(lang.isValue(field.key))?field.key:field;if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}else{bError=true;}}catch(e){bError=true;}}}else{oResult=fielddataarray;}if(!bError){oParsedResponse.results[recIdx++]=oResult;}}}}}return oParsedResponse;}}return null;},parseXMLResult:function(result){var oResult={},schema=this.responseSchema;try{for(var m=schema.fields.length-1;m>=0;m--){var field=schema.fields[m];var key=(lang.isValue(field.key))?field.key:field;var data=null;if(this.useXPath){data=YAHOO.util.DataSource._getLocationValue(field,result);}else{var xmlAttr=result.attributes.getNamedItem(key);if(xmlAttr){data=xmlAttr.value;}else{var xmlNode=result.getElementsByTagName(key);if(xmlNode&&xmlNode.item(0)){var item=xmlNode.item(0);data=(item)?((item.text)?item.text:(item.textContent)?item.textContent:null):null;if(!data){var datapieces=[];for(var j=0,len=item.childNodes.length;j<len;j++){if(item.childNodes[j].nodeValue){datapieces[datapieces.length]=item.childNodes[j].nodeValue;}}if(datapieces.length>0){data=datapieces.join("");}}}}}if(data===null){data="";}if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}}catch(e){}return oResult;},parseXMLData:function(oRequest,oFullResponse){var bError=false,schema=this.responseSchema,oParsedResponse={meta:{}},xmlList=null,metaNode=schema.metaNode,metaLocators=schema.metaFields||{},i,k,loc,v;try{if(this.useXPath){for(k in metaLocators){oParsedResponse.meta[k]=YAHOO.util.DataSource._getLocationValue(metaLocators[k],oFullResponse);}}else{metaNode=metaNode?oFullResponse.getElementsByTagName(metaNode)[0]:oFullResponse;if(metaNode){for(k in metaLocators){if(lang.hasOwnProperty(metaLocators,k)){loc=metaLocators[k];v=metaNode.getElementsByTagName(loc)[0];if(v){v=v.firstChild.nodeValue;}else{v=metaNode.attributes.getNamedItem(loc);if(v){v=v.value;}}if(lang.isValue(v)){oParsedResponse.meta[k]=v;}}}}}xmlList=(schema.resultNode)?oFullResponse.getElementsByTagName(schema.resultNode):null;}catch(e){}if(!xmlList||!lang.isArray(schema.fields)){bError=true;}else{oParsedResponse.results=[];for(i=xmlList.length-1;i>=0;--i){var oResult=this.parseXMLResult(xmlList.item(i));oParsedResponse.results[i]=oResult;}}if(bError){oParsedResponse.error=true;}else{}return oParsedResponse;},parseJSONData:function(oRequest,oFullResponse){var oParsedResponse={results:[],meta:{}};if(lang.isObject(oFullResponse)&&this.responseSchema.resultsList){var schema=this.responseSchema,fields=schema.fields,resultsList=oFullResponse,results=[],metaFields=schema.metaFields||{},fieldParsers=[],fieldPaths=[],simpleFields=[],bError=false,i,len,j,v,key,parser,path;var buildPath=function(needle){var path=null,keys=[],i=0;if(needle){needle=needle.replace(/\[(['"])(.*?)\1\]/g,function(x,$1,$2){keys[i]=$2;return".@"+(i++);}).replace(/\[(\d+)\]/g,function(x,$1){keys[i]=parseInt($1,10)|0;return".@"+(i++);}).replace(/^\./,"");if(!/[^\w\.\$@]/.test(needle)){path=needle.split(".");for(i=path.length-1;i>=0;--i){if(path[i].charAt(0)==="@"){path[i]=keys[parseInt(path[i].substr(1),10)];}}}else{}}return path;};var walkPath=function(path,origin){var v=origin,i=0,len=path.length;for(;i<len&&v;++i){v=v[path[i]];}return v;};path=buildPath(schema.resultsList);if(path){resultsList=walkPath(path,oFullResponse);if(resultsList===undefined){bError=true;}}else{bError=true;}if(!resultsList){resultsList=[];}if(!lang.isArray(resultsList)){resultsList=[resultsList];}if(!bError){if(schema.fields){var field;for(i=0,len=fields.length;i<len;i++){field=fields[i];key=field.key||field;parser=((typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""])||field.converter;path=buildPath(key);if(parser){fieldParsers[fieldParsers.length]={key:key,parser:parser};}if(path){if(path.length>1){fieldPaths[fieldPaths.length]={key:key,path:path};}else{simpleFields[simpleFields.length]={key:key,path:path[0]};}}else{}}for(i=resultsList.length-1;i>=0;--i){var r=resultsList[i],rec={};if(r){for(j=simpleFields.length-1;j>=0;--j){rec[simpleFields[j].key]=(r[simpleFields[j].path]!==undefined)?r[simpleFields[j].path]:r[j];}for(j=fieldPaths.length-1;j>=0;--j){rec[fieldPaths[j].key]=walkPath(fieldPaths[j].path,r);}for(j=fieldParsers.length-1;j>=0;--j){var p=fieldParsers[j].key;rec[p]=fieldParsers[j].parser.call(this,rec[p]);if(rec[p]===undefined){rec[p]=null;}}}results[i]=rec;}}else{results=resultsList;}for(key in metaFields){if(lang.hasOwnProperty(metaFields,key)){path=buildPath(metaFields[key]);
+if(path){v=walkPath(path,oFullResponse);oParsedResponse.meta[key]=v;}}}}else{oParsedResponse.error=true;}oParsedResponse.results=results;}else{oParsedResponse.error=true;}return oParsedResponse;},parseHTMLTableData:function(oRequest,oFullResponse){var bError=false;var elTable=oFullResponse;var fields=this.responseSchema.fields;var oParsedResponse={results:[]};if(lang.isArray(fields)){for(var i=0;i<elTable.tBodies.length;i++){var elTbody=elTable.tBodies[i];for(var j=elTbody.rows.length-1;j>-1;j--){var elRow=elTbody.rows[j];var oResult={};for(var k=fields.length-1;k>-1;k--){var field=fields[k];var key=(lang.isValue(field.key))?field.key:field;var data=elRow.cells[k].innerHTML;if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}oParsedResponse.results[j]=oResult;}}}else{bError=true;}if(bError){oParsedResponse.error=true;}else{}return oParsedResponse;}};lang.augmentProto(DS,util.EventProvider);util.LocalDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_LOCAL;if(oLiveData){if(YAHOO.lang.isArray(oLiveData)){this.responseType=DS.TYPE_JSARRAY;}else{if(oLiveData.nodeType&&oLiveData.nodeType==9){this.responseType=DS.TYPE_XML;}else{if(oLiveData.nodeName&&(oLiveData.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;oLiveData=oLiveData.cloneNode(true);}else{if(YAHOO.lang.isString(oLiveData)){this.responseType=DS.TYPE_TEXT;}else{if(YAHOO.lang.isObject(oLiveData)){this.responseType=DS.TYPE_JSON;}}}}}}else{oLiveData=[];this.responseType=DS.TYPE_JSARRAY;}util.LocalDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.LocalDataSource,DS);lang.augmentObject(util.LocalDataSource,DS);util.FunctionDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_JSFUNCTION;oLiveData=oLiveData||function(){};util.FunctionDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.FunctionDataSource,DS,{scope:null,makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oRawResponse=(this.scope)?this.liveData.call(this.scope,oRequest,this,oCallback):this.liveData(oRequest,oCallback);if(this.responseType===DS.TYPE_UNKNOWN){if(YAHOO.lang.isArray(oRawResponse)){this.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse&&oRawResponse.nodeType&&oRawResponse.nodeType==9){this.responseType=DS.TYPE_XML;}else{if(oRawResponse&&oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){this.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){this.responseType=DS.TYPE_TEXT;}}}}}}this.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);return tId;}});lang.augmentObject(util.FunctionDataSource,DS);util.ScriptNodeDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_SCRIPTNODE;oLiveData=oLiveData||"";util.ScriptNodeDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.ScriptNodeDataSource,DS,{getUtility:util.Get,asyncMode:"allowAll",scriptCallbackParam:"callback",generateRequestCallback:function(id){return"&"+this.scriptCallbackParam+"=YAHOO.util.ScriptNodeDataSource.callbacks["+id+"]";},doBeforeGetScriptNode:function(sUri){return sUri;},makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});if(util.ScriptNodeDataSource._nPending===0){util.ScriptNodeDataSource.callbacks=[];util.ScriptNodeDataSource._nId=0;}var id=util.ScriptNodeDataSource._nId;util.ScriptNodeDataSource._nId++;var oSelf=this;util.ScriptNodeDataSource.callbacks[id]=function(oRawResponse){if((oSelf.asyncMode!=="ignoreStaleResponses")||(id===util.ScriptNodeDataSource.callbacks.length-1)){if(oSelf.responseType===DS.TYPE_UNKNOWN){if(YAHOO.lang.isArray(oRawResponse)){oSelf.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse.nodeType&&oRawResponse.nodeType==9){oSelf.responseType=DS.TYPE_XML;}else{if(oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){oSelf.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){oSelf.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){oSelf.responseType=DS.TYPE_TEXT;}}}}}}oSelf.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);}else{}delete util.ScriptNodeDataSource.callbacks[id];};util.ScriptNodeDataSource._nPending++;var sUri=this.liveData+oRequest+this.generateRequestCallback(id);sUri=this.doBeforeGetScriptNode(sUri);this.getUtility.script(sUri,{autopurge:true,onsuccess:util.ScriptNodeDataSource._bumpPendingDown,onfail:util.ScriptNodeDataSource._bumpPendingDown});return tId;}});lang.augmentObject(util.ScriptNodeDataSource,DS);lang.augmentObject(util.ScriptNodeDataSource,{_nId:0,_nPending:0,callbacks:[]});util.XHRDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_XHR;this.connMgr=this.connMgr||util.Connect;oLiveData=oLiveData||"";util.XHRDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.XHRDataSource,DS,{connMgr:null,connXhrMode:"allowAll",connMethodPost:false,connTimeout:0,makeConnection:function(oRequest,oCallback,oCaller){var oRawResponse=null;var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oSelf=this;var oConnMgr=this.connMgr;var oQueue=this._oQueue;var _xhrSuccess=function(oResponse){if(oResponse&&(this.connXhrMode=="ignoreStaleResponses")&&(oResponse.tId!=oQueue.conn.tId)){return null;}else{if(!oResponse){this.fireEvent("dataErrorEvent",{request:oRequest,response:null,callback:oCallback,caller:oCaller,message:DS.ERROR_DATANULL});DS.issueCallback(oCallback,[oRequest,{error:true}],true,oCaller);return null;
+}else{if(this.responseType===DS.TYPE_UNKNOWN){var ctype=(oResponse.getResponseHeader)?oResponse.getResponseHeader["Content-Type"]:null;if(ctype){if(ctype.indexOf("text/xml")>-1){this.responseType=DS.TYPE_XML;}else{if(ctype.indexOf("application/json")>-1){this.responseType=DS.TYPE_JSON;}else{if(ctype.indexOf("text/plain")>-1){this.responseType=DS.TYPE_TEXT;}}}}}this.handleResponse(oRequest,oResponse,oCallback,oCaller,tId);}}};var _xhrFailure=function(oResponse){this.fireEvent("dataErrorEvent",{request:oRequest,response:oResponse,callback:oCallback,caller:oCaller,message:DS.ERROR_DATAINVALID});if(lang.isString(this.liveData)&&lang.isString(oRequest)&&(this.liveData.lastIndexOf("?")!==this.liveData.length-1)&&(oRequest.indexOf("?")!==0)){}oResponse=oResponse||{};oResponse.error=true;DS.issueCallback(oCallback,[oRequest,oResponse],true,oCaller);return null;};var _xhrCallback={success:_xhrSuccess,failure:_xhrFailure,scope:this};if(lang.isNumber(this.connTimeout)){_xhrCallback.timeout=this.connTimeout;}if(this.connXhrMode=="cancelStaleRequests"){if(oQueue.conn){if(oConnMgr.abort){oConnMgr.abort(oQueue.conn);oQueue.conn=null;}else{}}}if(oConnMgr&&oConnMgr.asyncRequest){var sLiveData=this.liveData;var isPost=this.connMethodPost;var sMethod=(isPost)?"POST":"GET";var sUri=(isPost||!lang.isValue(oRequest))?sLiveData:sLiveData+oRequest;var sRequest=(isPost)?oRequest:null;if(this.connXhrMode!="queueRequests"){oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,_xhrCallback,sRequest);}else{if(oQueue.conn){var allRequests=oQueue.requests;allRequests.push({request:oRequest,callback:_xhrCallback});if(!oQueue.interval){oQueue.interval=setInterval(function(){if(oConnMgr.isCallInProgress(oQueue.conn)){return;}else{if(allRequests.length>0){sUri=(isPost||!lang.isValue(allRequests[0].request))?sLiveData:sLiveData+allRequests[0].request;sRequest=(isPost)?allRequests[0].request:null;oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,allRequests[0].callback,sRequest);allRequests.shift();}else{clearInterval(oQueue.interval);oQueue.interval=null;}}},50);}}else{oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,_xhrCallback,sRequest);}}}else{DS.issueCallback(oCallback,[oRequest,{error:true}],true,oCaller);}return tId;}});lang.augmentObject(util.XHRDataSource,DS);util.DataSource=function(oLiveData,oConfigs){oConfigs=oConfigs||{};var dataType=oConfigs.dataType;if(dataType){if(dataType==DS.TYPE_LOCAL){return new util.LocalDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_XHR){return new util.XHRDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_SCRIPTNODE){return new util.ScriptNodeDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_JSFUNCTION){return new util.FunctionDataSource(oLiveData,oConfigs);}}}}}if(YAHOO.lang.isString(oLiveData)){return new util.XHRDataSource(oLiveData,oConfigs);}else{if(YAHOO.lang.isFunction(oLiveData)){return new util.FunctionDataSource(oLiveData,oConfigs);}else{return new util.LocalDataSource(oLiveData,oConfigs);}}};lang.augmentObject(util.DataSource,DS);})();YAHOO.util.Number={format:function(e,k){if(e===""||e===null||!isFinite(e)){return"";}e=+e;k=YAHOO.lang.merge(YAHOO.util.Number.format.defaults,(k||{}));var j=e+"",l=Math.abs(e),b=k.decimalPlaces||0,r=k.thousandsSeparator,f=k.negativeFormat||("-"+k.format),q,p,g,h;if(f.indexOf("#")>-1){f=f.replace(/#/,k.format);}if(b<0){q=l-(l%1)+"";g=q.length+b;if(g>0){q=Number("."+q).toFixed(g).slice(2)+new Array(q.length-g+1).join("0");}else{q="0";}}else{var a=l+"";if(b>0||a.indexOf(".")>0){var d=Math.pow(10,b);q=Math.round(l*d)/d+"";var c=q.indexOf("."),m,o;if(c<0){m=b;o=(Math.pow(10,m)+"").substring(1);if(b>0){q=q+"."+o;}}else{m=b-(q.length-c-1);o=(Math.pow(10,m)+"").substring(1);q=q+o;}}else{q=l.toFixed(b)+"";}}p=q.split(/\D/);if(l>=1000){g=p[0].length%3||3;p[0]=p[0].slice(0,g)+p[0].slice(g).replace(/(\d{3})/g,r+"$1");}return YAHOO.util.Number.format._applyFormat((e<0?f:k.format),p.join(k.decimalSeparator),k);}};YAHOO.util.Number.format.defaults={format:"{prefix}{number}{suffix}",negativeFormat:null,decimalSeparator:".",decimalPlaces:null,thousandsSeparator:""};YAHOO.util.Number.format._applyFormat=function(a,b,c){return a.replace(/\{(\w+)\}/g,function(d,e){return e==="number"?b:e in c?c[e]:"";});};(function(){var a=function(c,e,d){if(typeof d==="undefined"){d=10;}for(;parseInt(c,10)<d&&d>1;d/=10){c=e.toString()+c;}return c.toString();};var b={formats:{a:function(e,c){return c.a[e.getDay()];},A:function(e,c){return c.A[e.getDay()];},b:function(e,c){return c.b[e.getMonth()];},B:function(e,c){return c.B[e.getMonth()];},C:function(c){return a(parseInt(c.getFullYear()/100,10),0);},d:["getDate","0"],e:["getDate"," "],g:function(c){return a(parseInt(b.formats.G(c)%100,10),0);},G:function(f){var g=f.getFullYear();var e=parseInt(b.formats.V(f),10);var c=parseInt(b.formats.W(f),10);if(c>e){g++;}else{if(c===0&&e>=52){g--;}}return g;},H:["getHours","0"],I:function(e){var c=e.getHours()%12;return a(c===0?12:c,0);},j:function(h){var g=new Date(""+h.getFullYear()+"/1/1 GMT");var e=new Date(""+h.getFullYear()+"/"+(h.getMonth()+1)+"/"+h.getDate()+" GMT");var c=e-g;var f=parseInt(c/60000/60/24,10)+1;return a(f,0,100);},k:["getHours"," "],l:function(e){var c=e.getHours()%12;return a(c===0?12:c," ");},m:function(c){return a(c.getMonth()+1,0);},M:["getMinutes","0"],p:function(e,c){return c.p[e.getHours()>=12?1:0];},P:function(e,c){return c.P[e.getHours()>=12?1:0];},s:function(e,c){return parseInt(e.getTime()/1000,10);},S:["getSeconds","0"],u:function(c){var e=c.getDay();return e===0?7:e;},U:function(g){var c=parseInt(b.formats.j(g),10);var f=6-g.getDay();var e=parseInt((c+f)/7,10);return a(e,0);},V:function(g){var f=parseInt(b.formats.W(g),10);var c=(new Date(""+g.getFullYear()+"/1/1")).getDay();var e=f+(c>4||c<=1?0:1);if(e===53&&(new Date(""+g.getFullYear()+"/12/31")).getDay()<4){e=1;}else{if(e===0){e=b.formats.V(new Date(""+(g.getFullYear()-1)+"/12/31"));}}return a(e,0);},w:"getDay",W:function(g){var c=parseInt(b.formats.j(g),10);var f=7-b.formats.u(g);var e=parseInt((c+f)/7,10);
+return a(e,0,10);},y:function(c){return a(c.getFullYear()%100,0);},Y:"getFullYear",z:function(f){var e=f.getTimezoneOffset();var c=a(parseInt(Math.abs(e/60),10),0);var g=a(Math.abs(e%60),0);return(e>0?"-":"+")+c+g;},Z:function(c){var e=c.toString().replace(/^.*:\d\d( GMT[+-]\d+)? \(?([A-Za-z ]+)\)?\d*$/,"$2").replace(/[a-z ]/g,"");if(e.length>4){e=b.formats.z(c);}return e;},"%":function(c){return"%";}},aggregates:{c:"locale",D:"%m/%d/%y",F:"%Y-%m-%d",h:"%b",n:"\n",r:"locale",R:"%H:%M",t:"\t",T:"%H:%M:%S",x:"locale",X:"locale"},format:function(g,f,d){f=f||{};if(!(g instanceof Date)){return YAHOO.lang.isValue(g)?g:"";}var h=f.format||"%m/%d/%Y";if(h==="YYYY/MM/DD"){h="%Y/%m/%d";}else{if(h==="DD/MM/YYYY"){h="%d/%m/%Y";}else{if(h==="MM/DD/YYYY"){h="%m/%d/%Y";}}}d=d||"en";if(!(d in YAHOO.util.DateLocale)){if(d.replace(/-[a-zA-Z]+$/,"") in YAHOO.util.DateLocale){d=d.replace(/-[a-zA-Z]+$/,"");}else{d="en";}}var j=YAHOO.util.DateLocale[d];var c=function(l,k){var m=b.aggregates[k];return(m==="locale"?j[k]:m);};var e=function(l,k){var m=b.formats[k];if(typeof m==="string"){return g[m]();}else{if(typeof m==="function"){return m.call(g,g,j);}else{if(typeof m==="object"&&typeof m[0]==="string"){return a(g[m[0]](),m[1]);}else{return k;}}}};while(h.match(/%[cDFhnrRtTxX]/)){h=h.replace(/%([cDFhnrRtTxX])/g,c);}var i=h.replace(/%([aAbBCdegGHIjklmMpPsSuUVwWyYzZ%])/g,e);c=e=undefined;return i;}};YAHOO.namespace("YAHOO.util");YAHOO.util.Date=b;YAHOO.util.DateLocale={a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a %d %b %Y %T %Z",p:["AM","PM"],P:["am","pm"],r:"%I:%M:%S %p",x:"%d/%m/%y",X:"%T"};YAHOO.util.DateLocale["en"]=YAHOO.lang.merge(YAHOO.util.DateLocale,{});YAHOO.util.DateLocale["en-US"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"],{c:"%a %d %b %Y %I:%M:%S %p %Z",x:"%m/%d/%Y",X:"%I:%M:%S %p"});YAHOO.util.DateLocale["en-GB"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"],{r:"%l:%M:%S %P %Z"});YAHOO.util.DateLocale["en-AU"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"]);})();YAHOO.register("datasource",YAHOO.util.DataSource,{version:"2.9.0",build:"2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+YAHOO.widget.DS_JSArray=YAHOO.util.LocalDataSource;YAHOO.widget.DS_JSFunction=YAHOO.util.FunctionDataSource;YAHOO.widget.DS_XHR=function(b,a,d){var c=new YAHOO.util.XHRDataSource(b,d);c._aDeprecatedSchema=a;return c;};YAHOO.widget.DS_ScriptNode=function(b,a,d){var c=new YAHOO.util.ScriptNodeDataSource(b,d);c._aDeprecatedSchema=a;return c;};YAHOO.widget.DS_XHR.TYPE_JSON=YAHOO.util.DataSourceBase.TYPE_JSON;YAHOO.widget.DS_XHR.TYPE_XML=YAHOO.util.DataSourceBase.TYPE_XML;YAHOO.widget.DS_XHR.TYPE_FLAT=YAHOO.util.DataSourceBase.TYPE_TEXT;YAHOO.widget.AutoComplete=function(g,b,j,c){if(g&&b&&j){if(j&&YAHOO.lang.isFunction(j.sendRequest)){this.dataSource=j;}else{return;}this.key=0;var d=j.responseSchema;if(j._aDeprecatedSchema){var k=j._aDeprecatedSchema;if(YAHOO.lang.isArray(k)){if((j.responseType===YAHOO.util.DataSourceBase.TYPE_JSON)||(j.responseType===YAHOO.util.DataSourceBase.TYPE_UNKNOWN)){d.resultsList=k[0];this.key=k[1];d.fields=(k.length<3)?null:k.slice(1);}else{if(j.responseType===YAHOO.util.DataSourceBase.TYPE_XML){d.resultNode=k[0];this.key=k[1];d.fields=k.slice(1);}else{if(j.responseType===YAHOO.util.DataSourceBase.TYPE_TEXT){d.recordDelim=k[0];d.fieldDelim=k[1];}}}j.responseSchema=d;}}if(YAHOO.util.Dom.inDocument(g)){if(YAHOO.lang.isString(g)){this._sName="instance"+YAHOO.widget.AutoComplete._nIndex+" "+g;this._elTextbox=document.getElementById(g);}else{this._sName=(g.id)?"instance"+YAHOO.widget.AutoComplete._nIndex+" "+g.id:"instance"+YAHOO.widget.AutoComplete._nIndex;this._elTextbox=g;}YAHOO.util.Dom.addClass(this._elTextbox,"yui-ac-input");}else{return;}if(YAHOO.util.Dom.inDocument(b)){if(YAHOO.lang.isString(b)){this._elContainer=document.getElementById(b);}else{this._elContainer=b;}if(this._elContainer.style.display=="none"){}var e=this._elContainer.parentNode;var a=e.tagName.toLowerCase();if(a=="div"){YAHOO.util.Dom.addClass(e,"yui-ac");}else{}}else{return;}if(this.dataSource.dataType===YAHOO.util.DataSourceBase.TYPE_LOCAL){this.applyLocalFilter=true;}if(c&&(c.constructor==Object)){for(var i in c){if(i){this[i]=c[i];}}}this._initContainerEl();this._initProps();this._initListEl();this._initContainerHelperEls();var h=this;var f=this._elTextbox;YAHOO.util.Event.addListener(f,"keyup",h._onTextboxKeyUp,h);YAHOO.util.Event.addListener(f,"keydown",h._onTextboxKeyDown,h);YAHOO.util.Event.addListener(f,"focus",h._onTextboxFocus,h);YAHOO.util.Event.addListener(f,"blur",h._onTextboxBlur,h);YAHOO.util.Event.addListener(b,"mouseover",h._onContainerMouseover,h);YAHOO.util.Event.addListener(b,"mouseout",h._onContainerMouseout,h);YAHOO.util.Event.addListener(b,"click",h._onContainerClick,h);YAHOO.util.Event.addListener(b,"scroll",h._onContainerScroll,h);YAHOO.util.Event.addListener(b,"resize",h._onContainerResize,h);YAHOO.util.Event.addListener(f,"keypress",h._onTextboxKeyPress,h);YAHOO.util.Event.addListener(window,"unload",h._onWindowUnload,h);this.textboxFocusEvent=new YAHOO.util.CustomEvent("textboxFocus",this);this.textboxKeyEvent=new YAHOO.util.CustomEvent("textboxKey",this);this.dataRequestEvent=new YAHOO.util.CustomEvent("dataRequest",this);this.dataRequestCancelEvent=new YAHOO.util.CustomEvent("dataRequestCancel",this);this.dataReturnEvent=new YAHOO.util.CustomEvent("dataReturn",this);this.dataErrorEvent=new YAHOO.util.CustomEvent("dataError",this);this.containerPopulateEvent=new YAHOO.util.CustomEvent("containerPopulate",this);this.containerExpandEvent=new YAHOO.util.CustomEvent("containerExpand",this);this.typeAheadEvent=new YAHOO.util.CustomEvent("typeAhead",this);this.itemMouseOverEvent=new YAHOO.util.CustomEvent("itemMouseOver",this);this.itemMouseOutEvent=new YAHOO.util.CustomEvent("itemMouseOut",this);this.itemArrowToEvent=new YAHOO.util.CustomEvent("itemArrowTo",this);this.itemArrowFromEvent=new YAHOO.util.CustomEvent("itemArrowFrom",this);this.itemSelectEvent=new YAHOO.util.CustomEvent("itemSelect",this);this.unmatchedItemSelectEvent=new YAHOO.util.CustomEvent("unmatchedItemSelect",this);this.selectionEnforceEvent=new YAHOO.util.CustomEvent("selectionEnforce",this);this.containerCollapseEvent=new YAHOO.util.CustomEvent("containerCollapse",this);this.textboxBlurEvent=new YAHOO.util.CustomEvent("textboxBlur",this);this.textboxChangeEvent=new YAHOO.util.CustomEvent("textboxChange",this);f.setAttribute("autocomplete","off");YAHOO.widget.AutoComplete._nIndex++;}else{}};YAHOO.widget.AutoComplete.prototype.dataSource=null;YAHOO.widget.AutoComplete.prototype.applyLocalFilter=null;YAHOO.widget.AutoComplete.prototype.queryMatchCase=false;YAHOO.widget.AutoComplete.prototype.queryMatchContains=false;YAHOO.widget.AutoComplete.prototype.queryMatchSubset=false;YAHOO.widget.AutoComplete.prototype.minQueryLength=1;YAHOO.widget.AutoComplete.prototype.maxResultsDisplayed=10;YAHOO.widget.AutoComplete.prototype.queryDelay=0.2;YAHOO.widget.AutoComplete.prototype.typeAheadDelay=0.5;YAHOO.widget.AutoComplete.prototype.queryInterval=500;YAHOO.widget.AutoComplete.prototype.highlightClassName="yui-ac-highlight";YAHOO.widget.AutoComplete.prototype.prehighlightClassName=null;YAHOO.widget.AutoComplete.prototype.delimChar=null;YAHOO.widget.AutoComplete.prototype.autoHighlight=true;YAHOO.widget.AutoComplete.prototype.typeAhead=false;YAHOO.widget.AutoComplete.prototype.animHoriz=false;YAHOO.widget.AutoComplete.prototype.animVert=true;YAHOO.widget.AutoComplete.prototype.animSpeed=0.3;YAHOO.widget.AutoComplete.prototype.forceSelection=false;YAHOO.widget.AutoComplete.prototype.allowBrowserAutocomplete=true;YAHOO.widget.AutoComplete.prototype.alwaysShowContainer=false;YAHOO.widget.AutoComplete.prototype.useIFrame=false;YAHOO.widget.AutoComplete.prototype.useShadow=false;YAHOO.widget.AutoComplete.prototype.suppressInputUpdate=false;YAHOO.widget.AutoComplete.prototype.resultTypeList=true;YAHOO.widget.AutoComplete.prototype.queryQuestionMark=true;YAHOO.widget.AutoComplete.prototype.autoSnapContainer=true;YAHOO.widget.AutoComplete.prototype.toString=function(){return"AutoComplete "+this._sName;};YAHOO.widget.AutoComplete.prototype.getInputEl=function(){return this._elTextbox;
+};YAHOO.widget.AutoComplete.prototype.getContainerEl=function(){return this._elContainer;};YAHOO.widget.AutoComplete.prototype.isFocused=function(){return this._bFocused;};YAHOO.widget.AutoComplete.prototype.isContainerOpen=function(){return this._bContainerOpen;};YAHOO.widget.AutoComplete.prototype.getListEl=function(){return this._elList;};YAHOO.widget.AutoComplete.prototype.getListItemMatch=function(a){if(a._sResultMatch){return a._sResultMatch;}else{return null;}};YAHOO.widget.AutoComplete.prototype.getListItemData=function(a){if(a._oResultData){return a._oResultData;}else{return null;}};YAHOO.widget.AutoComplete.prototype.getListItemIndex=function(a){if(YAHOO.lang.isNumber(a._nItemIndex)){return a._nItemIndex;}else{return null;}};YAHOO.widget.AutoComplete.prototype.setHeader=function(b){if(this._elHeader){var a=this._elHeader;if(b){a.innerHTML=b;a.style.display="";}else{a.innerHTML="";a.style.display="none";}}};YAHOO.widget.AutoComplete.prototype.setFooter=function(b){if(this._elFooter){var a=this._elFooter;if(b){a.innerHTML=b;a.style.display="";}else{a.innerHTML="";a.style.display="none";}}};YAHOO.widget.AutoComplete.prototype.setBody=function(a){if(this._elBody){var b=this._elBody;YAHOO.util.Event.purgeElement(b,true);if(a){b.innerHTML=a;b.style.display="";}else{b.innerHTML="";b.style.display="none";}this._elList=null;}};YAHOO.widget.AutoComplete.prototype.generateRequest=function(b){var a=this.dataSource.dataType;if(a===YAHOO.util.DataSourceBase.TYPE_XHR){if(!this.dataSource.connMethodPost){b=(this.queryQuestionMark?"?":"")+(this.dataSource.scriptQueryParam||"query")+"="+b+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}else{b=(this.dataSource.scriptQueryParam||"query")+"="+b+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}}else{if(a===YAHOO.util.DataSourceBase.TYPE_SCRIPTNODE){b="&"+(this.dataSource.scriptQueryParam||"query")+"="+b+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}}return b;};YAHOO.widget.AutoComplete.prototype.sendQuery=function(b){this._bFocused=true;var a=(this.delimChar)?this._elTextbox.value+b:b;this._sendQuery(a);};YAHOO.widget.AutoComplete.prototype.snapContainer=function(){var a=this._elTextbox,b=YAHOO.util.Dom.getXY(a);b[1]+=YAHOO.util.Dom.get(a).offsetHeight+2;YAHOO.util.Dom.setXY(this._elContainer,b);};YAHOO.widget.AutoComplete.prototype.expandContainer=function(){this._toggleContainer(true);};YAHOO.widget.AutoComplete.prototype.collapseContainer=function(){this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype.clearList=function(){var b=this._elList.childNodes,a=b.length-1;for(;a>-1;a--){b[a].style.display="none";}};YAHOO.widget.AutoComplete.prototype.getSubsetMatches=function(e){var d,c,a;for(var b=e.length;b>=this.minQueryLength;b--){a=this.generateRequest(e.substr(0,b));this.dataRequestEvent.fire(this,d,a);c=this.dataSource.getCachedResponse(a);if(c){return this.filterResults.apply(this.dataSource,[e,c,c,{scope:this}]);}}return null;};YAHOO.widget.AutoComplete.prototype.preparseRawResponse=function(c,b,a){var d=((this.responseStripAfter!=="")&&(b.indexOf))?b.indexOf(this.responseStripAfter):-1;if(d!=-1){b=b.substring(0,d);}return b;};YAHOO.widget.AutoComplete.prototype.filterResults=function(l,n,r,m){if(m&&m.argument&&YAHOO.lang.isValue(m.argument.query)){l=m.argument.query;}if(l&&l!==""){r=YAHOO.widget.AutoComplete._cloneObject(r);var j=m.scope,q=this,c=r.results,o=[],b=j.maxResultsDisplayed,k=(q.queryMatchCase||j.queryMatchCase),a=(q.queryMatchContains||j.queryMatchContains);for(var d=0,h=c.length;d<h;d++){var f=c[d];var e=null;if(YAHOO.lang.isString(f)){e=f;}else{if(YAHOO.lang.isArray(f)){e=f[0];}else{if(this.responseSchema.fields){var p=this.responseSchema.fields[0].key||this.responseSchema.fields[0];e=f[p];}else{if(this.key){e=f[this.key];}}}}if(YAHOO.lang.isString(e)){var g=(k)?e.indexOf(decodeURIComponent(l)):e.toLowerCase().indexOf(decodeURIComponent(l).toLowerCase());if((!a&&(g===0))||(a&&(g>-1))){o.push(f);}}if(h>b&&o.length===b){break;}}r.results=o;}else{}return r;};YAHOO.widget.AutoComplete.prototype.handleResponse=function(c,a,b){if((this instanceof YAHOO.widget.AutoComplete)&&this._sName){this._populateList(c,a,b);}};YAHOO.widget.AutoComplete.prototype.doBeforeLoadData=function(c,a,b){return true;};YAHOO.widget.AutoComplete.prototype.formatResult=function(b,d,a){var c=(a)?a:"";return c;};YAHOO.widget.AutoComplete.prototype.formatEscapedResult=function(c,d,b){var a=(b)?b:"";return YAHOO.lang.escapeHTML(a);};YAHOO.widget.AutoComplete.prototype.doBeforeExpandContainer=function(d,a,c,b){return true;};YAHOO.widget.AutoComplete.prototype.destroy=function(){var b=this.toString();var a=this._elTextbox;var d=this._elContainer;this.textboxFocusEvent.unsubscribeAll();this.textboxKeyEvent.unsubscribeAll();this.dataRequestEvent.unsubscribeAll();this.dataReturnEvent.unsubscribeAll();this.dataErrorEvent.unsubscribeAll();this.containerPopulateEvent.unsubscribeAll();this.containerExpandEvent.unsubscribeAll();this.typeAheadEvent.unsubscribeAll();this.itemMouseOverEvent.unsubscribeAll();this.itemMouseOutEvent.unsubscribeAll();this.itemArrowToEvent.unsubscribeAll();this.itemArrowFromEvent.unsubscribeAll();this.itemSelectEvent.unsubscribeAll();this.unmatchedItemSelectEvent.unsubscribeAll();this.selectionEnforceEvent.unsubscribeAll();this.containerCollapseEvent.unsubscribeAll();this.textboxBlurEvent.unsubscribeAll();this.textboxChangeEvent.unsubscribeAll();YAHOO.util.Event.purgeElement(a,true);YAHOO.util.Event.purgeElement(d,true);d.innerHTML="";for(var c in this){if(YAHOO.lang.hasOwnProperty(this,c)){this[c]=null;}}};YAHOO.widget.AutoComplete.prototype.textboxFocusEvent=null;YAHOO.widget.AutoComplete.prototype.textboxKeyEvent=null;YAHOO.widget.AutoComplete.prototype.dataRequestEvent=null;YAHOO.widget.AutoComplete.prototype.dataRequestCancelEvent=null;YAHOO.widget.AutoComplete.prototype.dataReturnEvent=null;YAHOO.widget.AutoComplete.prototype.dataErrorEvent=null;
+YAHOO.widget.AutoComplete.prototype.containerPopulateEvent=null;YAHOO.widget.AutoComplete.prototype.containerExpandEvent=null;YAHOO.widget.AutoComplete.prototype.typeAheadEvent=null;YAHOO.widget.AutoComplete.prototype.itemMouseOverEvent=null;YAHOO.widget.AutoComplete.prototype.itemMouseOutEvent=null;YAHOO.widget.AutoComplete.prototype.itemArrowToEvent=null;YAHOO.widget.AutoComplete.prototype.itemArrowFromEvent=null;YAHOO.widget.AutoComplete.prototype.itemSelectEvent=null;YAHOO.widget.AutoComplete.prototype.unmatchedItemSelectEvent=null;YAHOO.widget.AutoComplete.prototype.selectionEnforceEvent=null;YAHOO.widget.AutoComplete.prototype.containerCollapseEvent=null;YAHOO.widget.AutoComplete.prototype.textboxBlurEvent=null;YAHOO.widget.AutoComplete.prototype.textboxChangeEvent=null;YAHOO.widget.AutoComplete._nIndex=0;YAHOO.widget.AutoComplete.prototype._sName=null;YAHOO.widget.AutoComplete.prototype._elTextbox=null;YAHOO.widget.AutoComplete.prototype._elContainer=null;YAHOO.widget.AutoComplete.prototype._elContent=null;YAHOO.widget.AutoComplete.prototype._elHeader=null;YAHOO.widget.AutoComplete.prototype._elBody=null;YAHOO.widget.AutoComplete.prototype._elFooter=null;YAHOO.widget.AutoComplete.prototype._elShadow=null;YAHOO.widget.AutoComplete.prototype._elIFrame=null;YAHOO.widget.AutoComplete.prototype._bFocused=false;YAHOO.widget.AutoComplete.prototype._oAnim=null;YAHOO.widget.AutoComplete.prototype._bContainerOpen=false;YAHOO.widget.AutoComplete.prototype._bOverContainer=false;YAHOO.widget.AutoComplete.prototype._elList=null;YAHOO.widget.AutoComplete.prototype._nDisplayedItems=0;YAHOO.widget.AutoComplete.prototype._sCurQuery=null;YAHOO.widget.AutoComplete.prototype._sPastSelections="";YAHOO.widget.AutoComplete.prototype._sInitInputValue=null;YAHOO.widget.AutoComplete.prototype._elCurListItem=null;YAHOO.widget.AutoComplete.prototype._elCurPrehighlightItem=null;YAHOO.widget.AutoComplete.prototype._bItemSelected=false;YAHOO.widget.AutoComplete.prototype._nKeyCode=null;YAHOO.widget.AutoComplete.prototype._nDelayID=-1;YAHOO.widget.AutoComplete.prototype._nTypeAheadDelayID=-1;YAHOO.widget.AutoComplete.prototype._iFrameSrc="javascript:false;";YAHOO.widget.AutoComplete.prototype._queryInterval=null;YAHOO.widget.AutoComplete.prototype._sLastTextboxValue=null;YAHOO.widget.AutoComplete.prototype._initProps=function(){var b=this.minQueryLength;if(!YAHOO.lang.isNumber(b)){this.minQueryLength=1;}var e=this.maxResultsDisplayed;if(!YAHOO.lang.isNumber(e)||(e<1)){this.maxResultsDisplayed=10;}var f=this.queryDelay;if(!YAHOO.lang.isNumber(f)||(f<0)){this.queryDelay=0.2;}var c=this.typeAheadDelay;if(!YAHOO.lang.isNumber(c)||(c<0)){this.typeAheadDelay=0.2;}var a=this.delimChar;if(YAHOO.lang.isString(a)&&(a.length>0)){this.delimChar=[a];}else{if(!YAHOO.lang.isArray(a)){this.delimChar=null;}}var d=this.animSpeed;if((this.animHoriz||this.animVert)&&YAHOO.util.Anim){if(!YAHOO.lang.isNumber(d)||(d<0)){this.animSpeed=0.3;}if(!this._oAnim){this._oAnim=new YAHOO.util.Anim(this._elContent,{},this.animSpeed);}else{this._oAnim.duration=this.animSpeed;}}if(this.forceSelection&&a){}};YAHOO.widget.AutoComplete.prototype._initContainerHelperEls=function(){if(this.useShadow&&!this._elShadow){var a=document.createElement("div");a.className="yui-ac-shadow";a.style.width=0;a.style.height=0;this._elShadow=this._elContainer.appendChild(a);}if(this.useIFrame&&!this._elIFrame){var b=document.createElement("iframe");b.src=this._iFrameSrc;b.frameBorder=0;b.scrolling="no";b.style.position="absolute";b.style.width=0;b.style.height=0;b.style.padding=0;b.tabIndex=-1;b.role="presentation";b.title="Presentational iframe shim";this._elIFrame=this._elContainer.appendChild(b);}};YAHOO.widget.AutoComplete.prototype._initContainerEl=function(){YAHOO.util.Dom.addClass(this._elContainer,"yui-ac-container");if(!this._elContent){var c=document.createElement("div");c.className="yui-ac-content";c.style.display="none";this._elContent=this._elContainer.appendChild(c);var b=document.createElement("div");b.className="yui-ac-hd";b.style.display="none";this._elHeader=this._elContent.appendChild(b);var d=document.createElement("div");d.className="yui-ac-bd";this._elBody=this._elContent.appendChild(d);var a=document.createElement("div");a.className="yui-ac-ft";a.style.display="none";this._elFooter=this._elContent.appendChild(a);}else{}};YAHOO.widget.AutoComplete.prototype._initListEl=function(){var c=this.maxResultsDisplayed,a=this._elList||document.createElement("ul"),b;while(a.childNodes.length<c){b=document.createElement("li");b.style.display="none";b._nItemIndex=a.childNodes.length;a.appendChild(b);}if(!this._elList){var d=this._elBody;YAHOO.util.Event.purgeElement(d,true);d.innerHTML="";this._elList=d.appendChild(a);}this._elBody.style.display="";};YAHOO.widget.AutoComplete.prototype._focus=function(){var a=this;setTimeout(function(){try{a._elTextbox.focus();}catch(b){}},0);};YAHOO.widget.AutoComplete.prototype._enableIntervalDetection=function(){var a=this;if(!a._queryInterval&&a.queryInterval){a._queryInterval=setInterval(function(){a._onInterval();},a.queryInterval);}};YAHOO.widget.AutoComplete.prototype.enableIntervalDetection=YAHOO.widget.AutoComplete.prototype._enableIntervalDetection;YAHOO.widget.AutoComplete.prototype._onInterval=function(){var a=this._elTextbox.value;var b=this._sLastTextboxValue;if(a!=b){this._sLastTextboxValue=a;this._sendQuery(a);}};YAHOO.widget.AutoComplete.prototype._clearInterval=function(){if(this._queryInterval){clearInterval(this._queryInterval);this._queryInterval=null;}};YAHOO.widget.AutoComplete.prototype._isIgnoreKey=function(a){if((a==9)||(a==13)||(a==16)||(a==17)||(a>=18&&a<=20)||(a==27)||(a>=33&&a<=35)||(a>=36&&a<=40)||(a>=44&&a<=45)||(a==229)){return true;}return false;};YAHOO.widget.AutoComplete.prototype._sendQuery=function(d){if(this.minQueryLength<0){this._toggleContainer(false);return;}if(this.delimChar){var a=this._extractQuery(d);d=a.query;this._sPastSelections=a.previous;}if((d&&(d.length<this.minQueryLength))||(!d&&this.minQueryLength>0)){if(this._nDelayID!=-1){clearTimeout(this._nDelayID);
+}this._toggleContainer(false);return;}d=encodeURIComponent(d);this._nDelayID=-1;if(this.dataSource.queryMatchSubset||this.queryMatchSubset){var c=this.getSubsetMatches(d);if(c){this.handleResponse(d,c,{query:d});return;}}if(this.dataSource.responseStripAfter){this.dataSource.doBeforeParseData=this.preparseRawResponse;}if(this.applyLocalFilter){this.dataSource.doBeforeCallback=this.filterResults;}var b=this.generateRequest(d);if(b!==undefined){this.dataRequestEvent.fire(this,d,b);this.dataSource.sendRequest(b,{success:this.handleResponse,failure:this.handleResponse,scope:this,argument:{query:d}});}else{this.dataRequestCancelEvent.fire(this,d);}};YAHOO.widget.AutoComplete.prototype._populateListItem=function(b,a,c){b.innerHTML=this.formatResult(a,c,b._sResultMatch);};YAHOO.widget.AutoComplete.prototype._populateList=function(n,f,c){if(this._nTypeAheadDelayID!=-1){clearTimeout(this._nTypeAheadDelayID);}n=(c&&c.query)?c.query:n;var h=this.doBeforeLoadData(n,f,c);if(h&&!f.error){this.dataReturnEvent.fire(this,n,f.results);if(this._bFocused){var p=decodeURIComponent(n);this._sCurQuery=p;this._bItemSelected=false;var u=f.results,a=Math.min(u.length,this.maxResultsDisplayed),m=(this.dataSource.responseSchema.fields)?(this.dataSource.responseSchema.fields[0].key||this.dataSource.responseSchema.fields[0]):0;if(a>0){if(!this._elList||(this._elList.childNodes.length<a)){this._initListEl();}this._initContainerHelperEls();var l=this._elList.childNodes;for(var t=a-1;t>=0;t--){var s=l[t],e=u[t];if(this.resultTypeList){var b=[];b[0]=(YAHOO.lang.isString(e))?e:e[m]||e[this.key];var o=this.dataSource.responseSchema.fields;if(YAHOO.lang.isArray(o)&&(o.length>1)){for(var q=1,v=o.length;q<v;q++){b[b.length]=e[o[q].key||o[q]];}}else{if(YAHOO.lang.isArray(e)){b=e;}else{if(YAHOO.lang.isString(e)){b=[e];}else{b[1]=e;}}}e=b;}s._sResultMatch=(YAHOO.lang.isString(e))?e:(YAHOO.lang.isArray(e))?e[0]:(e[m]||"");s._oResultData=e;this._populateListItem(s,e,p);s.style.display="";}if(a<l.length){var g;for(var r=l.length-1;r>=a;r--){g=l[r];g.style.display="none";}}this._nDisplayedItems=a;this.containerPopulateEvent.fire(this,n,u);if(this.autoHighlight){var d=this._elList.firstChild;this._toggleHighlight(d,"to");this.itemArrowToEvent.fire(this,d);this._typeAhead(d,n);}else{this._toggleHighlight(this._elCurListItem,"from");}h=this._doBeforeExpandContainer(this._elTextbox,this._elContainer,n,u);this._toggleContainer(h);}else{this._toggleContainer(false);}return;}}else{this.dataErrorEvent.fire(this,n,f);}};YAHOO.widget.AutoComplete.prototype._doBeforeExpandContainer=function(d,a,c,b){if(this.autoSnapContainer){this.snapContainer();}return this.doBeforeExpandContainer(d,a,c,b);};YAHOO.widget.AutoComplete.prototype._clearSelection=function(){var a=(this.delimChar)?this._extractQuery(this._elTextbox.value):{previous:"",query:this._elTextbox.value};this._elTextbox.value=a.previous;this.selectionEnforceEvent.fire(this,a.query);};YAHOO.widget.AutoComplete.prototype._textMatchesOption=function(){var a=null;for(var b=0;b<this._nDisplayedItems;b++){var c=this._elList.childNodes[b];var d=(""+c._sResultMatch).toLowerCase();if(d==this._sCurQuery.toLowerCase()){a=c;break;}}return(a);};YAHOO.widget.AutoComplete.prototype._typeAhead=function(b,d){if(!this.typeAhead||(this._nKeyCode==8)){return;}var a=this,c=this._elTextbox;if(c.setSelectionRange||c.createTextRange){this._nTypeAheadDelayID=setTimeout(function(){var f=c.value.length;a._updateValue(b);var g=c.value.length;a._selectText(c,f,g);var e=c.value.substr(f,g);a._sCurQuery=b._sResultMatch;a.typeAheadEvent.fire(a,d,e);},(this.typeAheadDelay*1000));}};YAHOO.widget.AutoComplete.prototype._selectText=function(d,a,b){if(d.setSelectionRange){d.setSelectionRange(a,b);}else{if(d.createTextRange){var c=d.createTextRange();c.moveStart("character",a);c.moveEnd("character",b-d.value.length);c.select();}else{d.select();}}};YAHOO.widget.AutoComplete.prototype._extractQuery=function(h){var c=this.delimChar,f=-1,g,e,b=c.length-1,d;for(;b>=0;b--){g=h.lastIndexOf(c[b]);if(g>f){f=g;}}if(c[b]==" "){for(var a=c.length-1;a>=0;a--){if(h[f-1]==c[a]){f--;break;}}}if(f>-1){e=f+1;while(h.charAt(e)==" "){e+=1;}d=h.substring(0,e);h=h.substr(e);}else{d="";}return{previous:d,query:h};};YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers=function(d){var e=this._elContent.offsetWidth+"px";var b=this._elContent.offsetHeight+"px";if(this.useIFrame&&this._elIFrame){var c=this._elIFrame;if(d){c.style.width=e;c.style.height=b;c.style.padding="";}else{c.style.width=0;c.style.height=0;c.style.padding=0;}}if(this.useShadow&&this._elShadow){var a=this._elShadow;if(d){a.style.width=e;a.style.height=b;}else{a.style.width=0;a.style.height=0;}}};YAHOO.widget.AutoComplete.prototype._toggleContainer=function(i){var d=this._elContainer;if(this.alwaysShowContainer&&this._bContainerOpen){return;}if(!i){this._toggleHighlight(this._elCurListItem,"from");this._nDisplayedItems=0;this._sCurQuery=null;if(this._elContent.style.display=="none"){return;}}var a=this._oAnim;if(a&&a.getEl()&&(this.animHoriz||this.animVert)){if(a.isAnimated()){a.stop(true);}var g=this._elContent.cloneNode(true);d.appendChild(g);g.style.top="-9000px";g.style.width="";g.style.height="";g.style.display="";var f=g.offsetWidth;var c=g.offsetHeight;var b=(this.animHoriz)?0:f;var e=(this.animVert)?0:c;a.attributes=(i)?{width:{to:f},height:{to:c}}:{width:{to:b},height:{to:e}};if(i&&!this._bContainerOpen){this._elContent.style.width=b+"px";this._elContent.style.height=e+"px";}else{this._elContent.style.width=f+"px";this._elContent.style.height=c+"px";}d.removeChild(g);g=null;var h=this;var j=function(){a.onComplete.unsubscribeAll();if(i){h._toggleContainerHelpers(true);h._bContainerOpen=i;h.containerExpandEvent.fire(h);}else{h._elContent.style.display="none";h._bContainerOpen=i;h.containerCollapseEvent.fire(h);}};this._toggleContainerHelpers(false);this._elContent.style.display="";a.onComplete.subscribe(j);a.animate();}else{if(i){this._elContent.style.display="";this._toggleContainerHelpers(true);
+this._bContainerOpen=i;this.containerExpandEvent.fire(this);}else{this._toggleContainerHelpers(false);this._elContent.style.display="none";this._bContainerOpen=i;this.containerCollapseEvent.fire(this);}}};YAHOO.widget.AutoComplete.prototype._toggleHighlight=function(a,c){if(a){var b=this.highlightClassName;if(this._elCurListItem){YAHOO.util.Dom.removeClass(this._elCurListItem,b);this._elCurListItem=null;}if((c=="to")&&b){YAHOO.util.Dom.addClass(a,b);this._elCurListItem=a;}}};YAHOO.widget.AutoComplete.prototype._togglePrehighlight=function(b,c){var a=this.prehighlightClassName;if(this._elCurPrehighlightItem){YAHOO.util.Dom.removeClass(this._elCurPrehighlightItem,a);}if(b==this._elCurListItem){return;}if((c=="mouseover")&&a){YAHOO.util.Dom.addClass(b,a);this._elCurPrehighlightItem=b;}else{YAHOO.util.Dom.removeClass(b,a);}};YAHOO.widget.AutoComplete.prototype._updateValue=function(c){if(!this.suppressInputUpdate){var f=this._elTextbox;var e=(this.delimChar)?(this.delimChar[0]||this.delimChar):null;var b=c._sResultMatch;var d="";if(e){d=this._sPastSelections;d+=b+e;if(e!=" "){d+=" ";}}else{d=b;}f.value=d;if(f.type=="textarea"){f.scrollTop=f.scrollHeight;}var a=f.value.length;this._selectText(f,a,a);this._elCurListItem=c;}};YAHOO.widget.AutoComplete.prototype._selectItem=function(a){this._bItemSelected=true;this._updateValue(a);this._sPastSelections=this._elTextbox.value;this._clearInterval();this.itemSelectEvent.fire(this,a,a._oResultData);this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype._jumpSelection=function(){if(this._elCurListItem){this._selectItem(this._elCurListItem);}else{this._toggleContainer(false);}};YAHOO.widget.AutoComplete.prototype._moveSelection=function(g){if(this._bContainerOpen){var h=this._elCurListItem,d=-1;if(h){d=h._nItemIndex;}var e=(g==40)?(d+1):(d-1);if(e<-2||e>=this._nDisplayedItems){return;}if(h){this._toggleHighlight(h,"from");this.itemArrowFromEvent.fire(this,h);}if(e==-1){if(this.delimChar){this._elTextbox.value=this._sPastSelections+this._sCurQuery;}else{this._elTextbox.value=this._sCurQuery;}return;}if(e==-2){this._toggleContainer(false);return;}var f=this._elList.childNodes[e],b=this._elContent,c=YAHOO.util.Dom.getStyle(b,"overflow"),i=YAHOO.util.Dom.getStyle(b,"overflowY"),a=((c=="auto")||(c=="scroll")||(i=="auto")||(i=="scroll"));if(a&&(e>-1)&&(e<this._nDisplayedItems)){if(g==40){if((f.offsetTop+f.offsetHeight)>(b.scrollTop+b.offsetHeight)){b.scrollTop=(f.offsetTop+f.offsetHeight)-b.offsetHeight;}else{if((f.offsetTop+f.offsetHeight)<b.scrollTop){b.scrollTop=f.offsetTop;}}}else{if(f.offsetTop<b.scrollTop){this._elContent.scrollTop=f.offsetTop;}else{if(f.offsetTop>(b.scrollTop+b.offsetHeight)){this._elContent.scrollTop=(f.offsetTop+f.offsetHeight)-b.offsetHeight;}}}}this._toggleHighlight(f,"to");this.itemArrowToEvent.fire(this,f);if(this.typeAhead){this._updateValue(f);this._sCurQuery=f._sResultMatch;}}};YAHOO.widget.AutoComplete.prototype._onContainerMouseover=function(a,c){var d=YAHOO.util.Event.getTarget(a);var b=d.nodeName.toLowerCase();while(d&&(b!="table")){switch(b){case"body":return;case"li":if(c.prehighlightClassName){c._togglePrehighlight(d,"mouseover");}else{c._toggleHighlight(d,"to");}c.itemMouseOverEvent.fire(c,d);break;case"div":if(YAHOO.util.Dom.hasClass(d,"yui-ac-container")){c._bOverContainer=true;return;}break;default:break;}d=d.parentNode;if(d){b=d.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerMouseout=function(a,c){var d=YAHOO.util.Event.getTarget(a);var b=d.nodeName.toLowerCase();while(d&&(b!="table")){switch(b){case"body":return;case"li":if(c.prehighlightClassName){c._togglePrehighlight(d,"mouseout");}else{c._toggleHighlight(d,"from");}c.itemMouseOutEvent.fire(c,d);break;case"ul":c._toggleHighlight(c._elCurListItem,"to");break;case"div":if(YAHOO.util.Dom.hasClass(d,"yui-ac-container")){c._bOverContainer=false;return;}break;default:break;}d=d.parentNode;if(d){b=d.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerClick=function(a,c){var d=YAHOO.util.Event.getTarget(a);var b=d.nodeName.toLowerCase();while(d&&(b!="table")){switch(b){case"body":return;case"li":c._toggleHighlight(d,"to");c._selectItem(d);return;default:break;}d=d.parentNode;if(d){b=d.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerScroll=function(a,b){b._focus();};YAHOO.widget.AutoComplete.prototype._onContainerResize=function(a,b){b._toggleContainerHelpers(b._bContainerOpen);};YAHOO.widget.AutoComplete.prototype._onTextboxKeyDown=function(a,b){var c=a.keyCode;if(b._nTypeAheadDelayID!=-1){clearTimeout(b._nTypeAheadDelayID);}switch(c){case 9:if(!YAHOO.env.ua.opera&&(navigator.userAgent.toLowerCase().indexOf("mac")==-1)||(YAHOO.env.ua.webkit>420)){if(b._elCurListItem){if(b.delimChar&&(b._nKeyCode!=c)){if(b._bContainerOpen){YAHOO.util.Event.stopEvent(a);}}b._selectItem(b._elCurListItem);}else{b._toggleContainer(false);}}break;case 13:if(!YAHOO.env.ua.opera&&(navigator.userAgent.toLowerCase().indexOf("mac")==-1)||(YAHOO.env.ua.webkit>420)){if(b._elCurListItem){if(b._nKeyCode!=c){if(b._bContainerOpen){YAHOO.util.Event.stopEvent(a);}}b._selectItem(b._elCurListItem);}else{b._toggleContainer(false);}}break;case 27:b._toggleContainer(false);return;case 39:b._jumpSelection();break;case 38:if(b._bContainerOpen){YAHOO.util.Event.stopEvent(a);b._moveSelection(c);}break;case 40:if(b._bContainerOpen){YAHOO.util.Event.stopEvent(a);b._moveSelection(c);}break;default:b._bItemSelected=false;b._toggleHighlight(b._elCurListItem,"from");b.textboxKeyEvent.fire(b,c);break;}if(c===18){b._enableIntervalDetection();}b._nKeyCode=c;};YAHOO.widget.AutoComplete.prototype._onTextboxKeyPress=function(a,b){var c=a.keyCode;if(YAHOO.env.ua.opera||(navigator.userAgent.toLowerCase().indexOf("mac")!=-1)&&(YAHOO.env.ua.webkit<420)){switch(c){case 9:if(b._bContainerOpen){if(b.delimChar){YAHOO.util.Event.stopEvent(a);}if(b._elCurListItem){b._selectItem(b._elCurListItem);}else{b._toggleContainer(false);}}break;case 13:if(b._bContainerOpen){YAHOO.util.Event.stopEvent(a);
+if(b._elCurListItem){b._selectItem(b._elCurListItem);}else{b._toggleContainer(false);}}break;default:break;}}else{if(c==229){b._enableIntervalDetection();}}};YAHOO.widget.AutoComplete.prototype._onTextboxKeyUp=function(a,c){var b=this.value;c._initProps();var d=a.keyCode;if(c._isIgnoreKey(d)){return;}if(c._nDelayID!=-1){clearTimeout(c._nDelayID);}c._nDelayID=setTimeout(function(){c._sendQuery(b);},(c.queryDelay*1000));};YAHOO.widget.AutoComplete.prototype._onTextboxFocus=function(a,b){if(!b._bFocused){b._elTextbox.setAttribute("autocomplete","off");b._bFocused=true;b._sInitInputValue=b._elTextbox.value;b.textboxFocusEvent.fire(b);}};YAHOO.widget.AutoComplete.prototype._onTextboxBlur=function(a,c){if(!c._bOverContainer||(c._nKeyCode==9)){if(!c._bItemSelected){var b=c._textMatchesOption();if(!c._bContainerOpen||(c._bContainerOpen&&(b===null))){if(c.forceSelection){c._clearSelection();}else{c.unmatchedItemSelectEvent.fire(c,c._sCurQuery);}}else{if(c.forceSelection){c._selectItem(b);}}}c._clearInterval();c._bFocused=false;if(c._sInitInputValue!==c._elTextbox.value){c.textboxChangeEvent.fire(c);}c.textboxBlurEvent.fire(c);c._toggleContainer(false);}else{c._focus();}};YAHOO.widget.AutoComplete.prototype._onWindowUnload=function(a,b){if(b&&b._elTextbox&&b.allowBrowserAutocomplete){b._elTextbox.setAttribute("autocomplete","on");}};YAHOO.widget.AutoComplete.prototype.doBeforeSendQuery=function(a){return this.generateRequest(a);};YAHOO.widget.AutoComplete.prototype.getListItems=function(){var c=[],b=this._elList.childNodes;for(var a=b.length-1;a>=0;a--){c[a]=b[a];}return c;};YAHOO.widget.AutoComplete._cloneObject=function(d){if(!YAHOO.lang.isValue(d)){return d;}var f={};if(YAHOO.lang.isFunction(d)){f=d;}else{if(YAHOO.lang.isArray(d)){var e=[];for(var c=0,b=d.length;c<b;c++){e[c]=YAHOO.widget.AutoComplete._cloneObject(d[c]);}f=e;}else{if(YAHOO.lang.isObject(d)){for(var a in d){if(YAHOO.lang.hasOwnProperty(d,a)){if(YAHOO.lang.isValue(d[a])&&YAHOO.lang.isObject(d[a])||YAHOO.lang.isArray(d[a])){f[a]=YAHOO.widget.AutoComplete._cloneObject(d[a]);}else{f[a]=d[a];}}}}else{f=d;}}}return f;};YAHOO.register("autocomplete",YAHOO.widget.AutoComplete,{version:"2.9.0",build:"2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+(function(){YAHOO.util.Config=function(d){if(d){this.init(d);}};var b=YAHOO.lang,c=YAHOO.util.CustomEvent,a=YAHOO.util.Config;a.CONFIG_CHANGED_EVENT="configChanged";a.BOOLEAN_TYPE="boolean";a.prototype={owner:null,queueInProgress:false,config:null,initialConfig:null,eventQueue:null,configChangedEvent:null,init:function(d){this.owner=d;this.configChangedEvent=this.createEvent(a.CONFIG_CHANGED_EVENT);this.configChangedEvent.signature=c.LIST;this.queueInProgress=false;this.config={};this.initialConfig={};this.eventQueue=[];},checkBoolean:function(d){return(typeof d==a.BOOLEAN_TYPE);},checkNumber:function(d){return(!isNaN(d));},fireEvent:function(d,f){var e=this.config[d];if(e&&e.event){e.event.fire(f);}},addProperty:function(e,d){e=e.toLowerCase();this.config[e]=d;d.event=this.createEvent(e,{scope:this.owner});d.event.signature=c.LIST;d.key=e;if(d.handler){d.event.subscribe(d.handler,this.owner);}this.setProperty(e,d.value,true);if(!d.suppressEvent){this.queueProperty(e,d.value);}},getConfig:function(){var d={},f=this.config,g,e;for(g in f){if(b.hasOwnProperty(f,g)){e=f[g];if(e&&e.event){d[g]=e.value;}}}return d;},getProperty:function(d){var e=this.config[d.toLowerCase()];if(e&&e.event){return e.value;}else{return undefined;}},resetProperty:function(d){d=d.toLowerCase();var e=this.config[d];if(e&&e.event){if(d in this.initialConfig){this.setProperty(d,this.initialConfig[d]);return true;}}else{return false;}},setProperty:function(e,g,d){var f;e=e.toLowerCase();if(this.queueInProgress&&!d){this.queueProperty(e,g);return true;}else{f=this.config[e];if(f&&f.event){if(f.validator&&!f.validator(g)){return false;}else{f.value=g;if(!d){this.fireEvent(e,g);this.configChangedEvent.fire([e,g]);}return true;}}else{return false;}}},queueProperty:function(v,r){v=v.toLowerCase();var u=this.config[v],l=false,k,g,h,j,p,t,f,n,o,d,m,w,e;if(u&&u.event){if(!b.isUndefined(r)&&u.validator&&!u.validator(r)){return false;}else{if(!b.isUndefined(r)){u.value=r;}else{r=u.value;}l=false;k=this.eventQueue.length;for(m=0;m<k;m++){g=this.eventQueue[m];if(g){h=g[0];j=g[1];if(h==v){this.eventQueue[m]=null;this.eventQueue.push([v,(!b.isUndefined(r)?r:j)]);l=true;break;}}}if(!l&&!b.isUndefined(r)){this.eventQueue.push([v,r]);}}if(u.supercedes){p=u.supercedes.length;for(w=0;w<p;w++){t=u.supercedes[w];f=this.eventQueue.length;for(e=0;e<f;e++){n=this.eventQueue[e];if(n){o=n[0];d=n[1];if(o==t.toLowerCase()){this.eventQueue.push([o,d]);this.eventQueue[e]=null;break;}}}}}return true;}else{return false;}},refireEvent:function(d){d=d.toLowerCase();var e=this.config[d];if(e&&e.event&&!b.isUndefined(e.value)){if(this.queueInProgress){this.queueProperty(d);}else{this.fireEvent(d,e.value);}}},applyConfig:function(d,g){var f,e;if(g){e={};for(f in d){if(b.hasOwnProperty(d,f)){e[f.toLowerCase()]=d[f];}}this.initialConfig=e;}for(f in d){if(b.hasOwnProperty(d,f)){this.queueProperty(f,d[f]);}}},refresh:function(){var d;for(d in this.config){if(b.hasOwnProperty(this.config,d)){this.refireEvent(d);}}},fireQueue:function(){var e,h,d,g,f;this.queueInProgress=true;for(e=0;e<this.eventQueue.length;e++){h=this.eventQueue[e];if(h){d=h[0];g=h[1];f=this.config[d];f.value=g;this.eventQueue[e]=null;this.fireEvent(d,g);}}this.queueInProgress=false;this.eventQueue=[];},subscribeToConfigEvent:function(d,e,g,h){var f=this.config[d.toLowerCase()];if(f&&f.event){if(!a.alreadySubscribed(f.event,e,g)){f.event.subscribe(e,g,h);}return true;}else{return false;}},unsubscribeFromConfigEvent:function(d,e,g){var f=this.config[d.toLowerCase()];if(f&&f.event){return f.event.unsubscribe(e,g);}else{return false;}},toString:function(){var d="Config";if(this.owner){d+=" ["+this.owner.toString()+"]";}return d;},outputEventQueue:function(){var d="",g,e,f=this.eventQueue.length;for(e=0;e<f;e++){g=this.eventQueue[e];if(g){d+=g[0]+"="+g[1]+", ";}}return d;},destroy:function(){var e=this.config,d,f;for(d in e){if(b.hasOwnProperty(e,d)){f=e[d];f.event.unsubscribeAll();f.event=null;}}this.configChangedEvent.unsubscribeAll();this.configChangedEvent=null;this.owner=null;this.config=null;this.initialConfig=null;this.eventQueue=null;}};a.alreadySubscribed=function(e,h,j){var f=e.subscribers.length,d,g;if(f>0){g=f-1;do{d=e.subscribers[g];if(d&&d.obj==j&&d.fn==h){return true;}}while(g--);}return false;};YAHOO.lang.augmentProto(a,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Module=function(r,q){if(r){this.init(r,q);}else{}};var f=YAHOO.util.Dom,d=YAHOO.util.Config,n=YAHOO.util.Event,m=YAHOO.util.CustomEvent,g=YAHOO.widget.Module,i=YAHOO.env.ua,h,p,o,e,a={"BEFORE_INIT":"beforeInit","INIT":"init","APPEND":"append","BEFORE_RENDER":"beforeRender","RENDER":"render","CHANGE_HEADER":"changeHeader","CHANGE_BODY":"changeBody","CHANGE_FOOTER":"changeFooter","CHANGE_CONTENT":"changeContent","DESTROY":"destroy","BEFORE_SHOW":"beforeShow","SHOW":"show","BEFORE_HIDE":"beforeHide","HIDE":"hide"},j={"VISIBLE":{key:"visible",value:true,validator:YAHOO.lang.isBoolean},"EFFECT":{key:"effect",suppressEvent:true,supercedes:["visible"]},"MONITOR_RESIZE":{key:"monitorresize",value:true},"APPEND_TO_DOCUMENT_BODY":{key:"appendtodocumentbody",value:false}};g.IMG_ROOT=null;g.IMG_ROOT_SSL=null;g.CSS_MODULE="yui-module";g.CSS_HEADER="hd";g.CSS_BODY="bd";g.CSS_FOOTER="ft";g.RESIZE_MONITOR_SECURE_URL="javascript:false;";g.RESIZE_MONITOR_BUFFER=1;g.textResizeEvent=new m("textResize");g.forceDocumentRedraw=function(){var q=document.documentElement;if(q){q.className+=" ";q.className=YAHOO.lang.trim(q.className);}};function l(){if(!h){h=document.createElement("div");h.innerHTML=('<div class="'+g.CSS_HEADER+'"></div>'+'<div class="'+g.CSS_BODY+'"></div><div class="'+g.CSS_FOOTER+'"></div>');p=h.firstChild;o=p.nextSibling;e=o.nextSibling;}return h;}function k(){if(!p){l();}return(p.cloneNode(false));}function b(){if(!o){l();}return(o.cloneNode(false));}function c(){if(!e){l();}return(e.cloneNode(false));}g.prototype={constructor:g,element:null,header:null,body:null,footer:null,id:null,imageRoot:g.IMG_ROOT,initEvents:function(){var q=m.LIST;
+this.beforeInitEvent=this.createEvent(a.BEFORE_INIT);this.beforeInitEvent.signature=q;this.initEvent=this.createEvent(a.INIT);this.initEvent.signature=q;this.appendEvent=this.createEvent(a.APPEND);this.appendEvent.signature=q;this.beforeRenderEvent=this.createEvent(a.BEFORE_RENDER);this.beforeRenderEvent.signature=q;this.renderEvent=this.createEvent(a.RENDER);this.renderEvent.signature=q;this.changeHeaderEvent=this.createEvent(a.CHANGE_HEADER);this.changeHeaderEvent.signature=q;this.changeBodyEvent=this.createEvent(a.CHANGE_BODY);this.changeBodyEvent.signature=q;this.changeFooterEvent=this.createEvent(a.CHANGE_FOOTER);this.changeFooterEvent.signature=q;this.changeContentEvent=this.createEvent(a.CHANGE_CONTENT);this.changeContentEvent.signature=q;this.destroyEvent=this.createEvent(a.DESTROY);this.destroyEvent.signature=q;this.beforeShowEvent=this.createEvent(a.BEFORE_SHOW);this.beforeShowEvent.signature=q;this.showEvent=this.createEvent(a.SHOW);this.showEvent.signature=q;this.beforeHideEvent=this.createEvent(a.BEFORE_HIDE);this.beforeHideEvent.signature=q;this.hideEvent=this.createEvent(a.HIDE);this.hideEvent.signature=q;},platform:function(){var q=navigator.userAgent.toLowerCase();if(q.indexOf("windows")!=-1||q.indexOf("win32")!=-1){return"windows";}else{if(q.indexOf("macintosh")!=-1){return"mac";}else{return false;}}}(),browser:function(){var q=navigator.userAgent.toLowerCase();if(q.indexOf("opera")!=-1){return"opera";}else{if(q.indexOf("msie 7")!=-1){return"ie7";}else{if(q.indexOf("msie")!=-1){return"ie";}else{if(q.indexOf("safari")!=-1){return"safari";}else{if(q.indexOf("gecko")!=-1){return"gecko";}else{return false;}}}}}}(),isSecure:function(){if(window.location.href.toLowerCase().indexOf("https")===0){return true;}else{return false;}}(),initDefaultConfig:function(){this.cfg.addProperty(j.VISIBLE.key,{handler:this.configVisible,value:j.VISIBLE.value,validator:j.VISIBLE.validator});this.cfg.addProperty(j.EFFECT.key,{handler:this.configEffect,suppressEvent:j.EFFECT.suppressEvent,supercedes:j.EFFECT.supercedes});this.cfg.addProperty(j.MONITOR_RESIZE.key,{handler:this.configMonitorResize,value:j.MONITOR_RESIZE.value});this.cfg.addProperty(j.APPEND_TO_DOCUMENT_BODY.key,{value:j.APPEND_TO_DOCUMENT_BODY.value});},init:function(v,u){var s,w;this.initEvents();this.beforeInitEvent.fire(g);this.cfg=new d(this);if(this.isSecure){this.imageRoot=g.IMG_ROOT_SSL;}if(typeof v=="string"){s=v;v=document.getElementById(v);if(!v){v=(l()).cloneNode(false);v.id=s;}}this.id=f.generateId(v);this.element=v;w=this.element.firstChild;if(w){var r=false,q=false,t=false;do{if(1==w.nodeType){if(!r&&f.hasClass(w,g.CSS_HEADER)){this.header=w;r=true;}else{if(!q&&f.hasClass(w,g.CSS_BODY)){this.body=w;q=true;}else{if(!t&&f.hasClass(w,g.CSS_FOOTER)){this.footer=w;t=true;}}}}}while((w=w.nextSibling));}this.initDefaultConfig();f.addClass(this.element,g.CSS_MODULE);if(u){this.cfg.applyConfig(u,true);}if(!d.alreadySubscribed(this.renderEvent,this.cfg.fireQueue,this.cfg)){this.renderEvent.subscribe(this.cfg.fireQueue,this.cfg,true);}this.initEvent.fire(g);},initResizeMonitor:function(){var r=(i.gecko&&this.platform=="windows");if(r){var q=this;setTimeout(function(){q._initResizeMonitor();},0);}else{this._initResizeMonitor();}},_initResizeMonitor:function(){var q,s,u;function w(){g.textResizeEvent.fire();}if(!i.opera){s=f.get("_yuiResizeMonitor");var v=this._supportsCWResize();if(!s){s=document.createElement("iframe");if(this.isSecure&&g.RESIZE_MONITOR_SECURE_URL&&i.ie){s.src=g.RESIZE_MONITOR_SECURE_URL;}if(!v){u=["<html><head><script ",'type="text/javascript">',"window.onresize=function(){window.parent.","YAHOO.widget.Module.textResizeEvent.","fire();};<","/script></head>","<body></body></html>"].join("");s.src="data:text/html;charset=utf-8,"+encodeURIComponent(u);}s.id="_yuiResizeMonitor";s.title="Text Resize Monitor";s.tabIndex=-1;s.setAttribute("role","presentation");s.style.position="absolute";s.style.visibility="hidden";var r=document.body,t=r.firstChild;if(t){r.insertBefore(s,t);}else{r.appendChild(s);}s.style.backgroundColor="transparent";s.style.borderWidth="0";s.style.width="2em";s.style.height="2em";s.style.left="0";s.style.top=(-1*(s.offsetHeight+g.RESIZE_MONITOR_BUFFER))+"px";s.style.visibility="visible";if(i.webkit){q=s.contentWindow.document;q.open();q.close();}}if(s&&s.contentWindow){g.textResizeEvent.subscribe(this.onDomResize,this,true);if(!g.textResizeInitialized){if(v){if(!n.on(s.contentWindow,"resize",w)){n.on(s,"resize",w);}}g.textResizeInitialized=true;}this.resizeMonitor=s;}}},_supportsCWResize:function(){var q=true;if(i.gecko&&i.gecko<=1.8){q=false;}return q;},onDomResize:function(s,r){var q=-1*(this.resizeMonitor.offsetHeight+g.RESIZE_MONITOR_BUFFER);this.resizeMonitor.style.top=q+"px";this.resizeMonitor.style.left="0";},setHeader:function(r){var q=this.header||(this.header=k());if(r.nodeName){q.innerHTML="";q.appendChild(r);}else{q.innerHTML=r;}if(this._rendered){this._renderHeader();}this.changeHeaderEvent.fire(r);this.changeContentEvent.fire();},appendToHeader:function(r){var q=this.header||(this.header=k());q.appendChild(r);this.changeHeaderEvent.fire(r);this.changeContentEvent.fire();},setBody:function(r){var q=this.body||(this.body=b());if(r.nodeName){q.innerHTML="";q.appendChild(r);}else{q.innerHTML=r;}if(this._rendered){this._renderBody();}this.changeBodyEvent.fire(r);this.changeContentEvent.fire();},appendToBody:function(r){var q=this.body||(this.body=b());q.appendChild(r);this.changeBodyEvent.fire(r);this.changeContentEvent.fire();},setFooter:function(r){var q=this.footer||(this.footer=c());if(r.nodeName){q.innerHTML="";q.appendChild(r);}else{q.innerHTML=r;}if(this._rendered){this._renderFooter();}this.changeFooterEvent.fire(r);this.changeContentEvent.fire();},appendToFooter:function(r){var q=this.footer||(this.footer=c());q.appendChild(r);this.changeFooterEvent.fire(r);this.changeContentEvent.fire();},render:function(s,q){var t=this;function r(u){if(typeof u=="string"){u=document.getElementById(u);
+}if(u){t._addToParent(u,t.element);t.appendEvent.fire();}}this.beforeRenderEvent.fire();if(!q){q=this.element;}if(s){r(s);}else{if(!f.inDocument(this.element)){return false;}}this._renderHeader(q);this._renderBody(q);this._renderFooter(q);this._rendered=true;this.renderEvent.fire();return true;},_renderHeader:function(q){q=q||this.element;if(this.header&&!f.inDocument(this.header)){var r=q.firstChild;if(r){q.insertBefore(this.header,r);}else{q.appendChild(this.header);}}},_renderBody:function(q){q=q||this.element;if(this.body&&!f.inDocument(this.body)){if(this.footer&&f.isAncestor(q,this.footer)){q.insertBefore(this.body,this.footer);}else{q.appendChild(this.body);}}},_renderFooter:function(q){q=q||this.element;if(this.footer&&!f.inDocument(this.footer)){q.appendChild(this.footer);}},destroy:function(q){var r,s=!(q);if(this.element){n.purgeElement(this.element,s);r=this.element.parentNode;}if(r){r.removeChild(this.element);}this.element=null;this.header=null;this.body=null;this.footer=null;g.textResizeEvent.unsubscribe(this.onDomResize,this);this.cfg.destroy();this.cfg=null;this.destroyEvent.fire();},show:function(){this.cfg.setProperty("visible",true);},hide:function(){this.cfg.setProperty("visible",false);},configVisible:function(r,q,s){var t=q[0];if(t){if(this.beforeShowEvent.fire()){f.setStyle(this.element,"display","block");this.showEvent.fire();}}else{if(this.beforeHideEvent.fire()){f.setStyle(this.element,"display","none");this.hideEvent.fire();}}},configEffect:function(r,q,s){this._cachedEffects=(this.cacheEffects)?this._createEffects(q[0]):null;},cacheEffects:true,_createEffects:function(t){var q=null,u,r,s;if(t){if(t instanceof Array){q=[];u=t.length;for(r=0;r<u;r++){s=t[r];if(s.effect){q[q.length]=s.effect(this,s.duration);}}}else{if(t.effect){q=[t.effect(this,t.duration)];}}}return q;},configMonitorResize:function(s,r,t){var q=r[0];if(q){this.initResizeMonitor();}else{g.textResizeEvent.unsubscribe(this.onDomResize,this,true);this.resizeMonitor=null;}},_addToParent:function(q,r){if(!this.cfg.getProperty("appendtodocumentbody")&&q===document.body&&q.firstChild){q.insertBefore(r,q.firstChild);}else{q.appendChild(r);}},toString:function(){return"Module "+this.id;}};YAHOO.lang.augmentProto(g,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Overlay=function(p,o){YAHOO.widget.Overlay.superclass.constructor.call(this,p,o);};var i=YAHOO.lang,m=YAHOO.util.CustomEvent,g=YAHOO.widget.Module,n=YAHOO.util.Event,f=YAHOO.util.Dom,d=YAHOO.util.Config,k=YAHOO.env.ua,b=YAHOO.widget.Overlay,h="subscribe",e="unsubscribe",c="contained",j,a={"BEFORE_MOVE":"beforeMove","MOVE":"move"},l={"X":{key:"x",validator:i.isNumber,suppressEvent:true,supercedes:["iframe"]},"Y":{key:"y",validator:i.isNumber,suppressEvent:true,supercedes:["iframe"]},"XY":{key:"xy",suppressEvent:true,supercedes:["iframe"]},"CONTEXT":{key:"context",suppressEvent:true,supercedes:["iframe"]},"FIXED_CENTER":{key:"fixedcenter",value:false,supercedes:["iframe","visible"]},"WIDTH":{key:"width",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"HEIGHT":{key:"height",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"AUTO_FILL_HEIGHT":{key:"autofillheight",supercedes:["height"],value:"body"},"ZINDEX":{key:"zindex",value:null},"CONSTRAIN_TO_VIEWPORT":{key:"constraintoviewport",value:false,validator:i.isBoolean,supercedes:["iframe","x","y","xy"]},"IFRAME":{key:"iframe",value:(k.ie==6?true:false),validator:i.isBoolean,supercedes:["zindex"]},"PREVENT_CONTEXT_OVERLAP":{key:"preventcontextoverlap",value:false,validator:i.isBoolean,supercedes:["constraintoviewport"]}};b.IFRAME_SRC="javascript:false;";b.IFRAME_OFFSET=3;b.VIEWPORT_OFFSET=10;b.TOP_LEFT="tl";b.TOP_RIGHT="tr";b.BOTTOM_LEFT="bl";b.BOTTOM_RIGHT="br";b.PREVENT_OVERLAP_X={"tltr":true,"blbr":true,"brbl":true,"trtl":true};b.PREVENT_OVERLAP_Y={"trbr":true,"tlbl":true,"bltl":true,"brtr":true};b.CSS_OVERLAY="yui-overlay";b.CSS_HIDDEN="yui-overlay-hidden";b.CSS_IFRAME="yui-overlay-iframe";b.STD_MOD_RE=/^\s*?(body|footer|header)\s*?$/i;b.windowScrollEvent=new m("windowScroll");b.windowResizeEvent=new m("windowResize");b.windowScrollHandler=function(p){var o=n.getTarget(p);if(!o||o===window||o===window.document){if(k.ie){if(!window.scrollEnd){window.scrollEnd=-1;}clearTimeout(window.scrollEnd);window.scrollEnd=setTimeout(function(){b.windowScrollEvent.fire();},1);}else{b.windowScrollEvent.fire();}}};b.windowResizeHandler=function(o){if(k.ie){if(!window.resizeEnd){window.resizeEnd=-1;}clearTimeout(window.resizeEnd);window.resizeEnd=setTimeout(function(){b.windowResizeEvent.fire();},100);}else{b.windowResizeEvent.fire();}};b._initialized=null;if(b._initialized===null){n.on(window,"scroll",b.windowScrollHandler);n.on(window,"resize",b.windowResizeHandler);b._initialized=true;}b._TRIGGER_MAP={"windowScroll":b.windowScrollEvent,"windowResize":b.windowResizeEvent,"textResize":g.textResizeEvent};YAHOO.extend(b,g,{CONTEXT_TRIGGERS:[],init:function(p,o){b.superclass.init.call(this,p);this.beforeInitEvent.fire(b);f.addClass(this.element,b.CSS_OVERLAY);if(o){this.cfg.applyConfig(o,true);}if(this.platform=="mac"&&k.gecko){if(!d.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)){this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);}if(!d.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)){this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);}}this.initEvent.fire(b);},initEvents:function(){b.superclass.initEvents.call(this);var o=m.LIST;this.beforeMoveEvent=this.createEvent(a.BEFORE_MOVE);this.beforeMoveEvent.signature=o;this.moveEvent=this.createEvent(a.MOVE);this.moveEvent.signature=o;},initDefaultConfig:function(){b.superclass.initDefaultConfig.call(this);var o=this.cfg;o.addProperty(l.X.key,{handler:this.configX,validator:l.X.validator,suppressEvent:l.X.suppressEvent,supercedes:l.X.supercedes});o.addProperty(l.Y.key,{handler:this.configY,validator:l.Y.validator,suppressEvent:l.Y.suppressEvent,supercedes:l.Y.supercedes});
+o.addProperty(l.XY.key,{handler:this.configXY,suppressEvent:l.XY.suppressEvent,supercedes:l.XY.supercedes});o.addProperty(l.CONTEXT.key,{handler:this.configContext,suppressEvent:l.CONTEXT.suppressEvent,supercedes:l.CONTEXT.supercedes});o.addProperty(l.FIXED_CENTER.key,{handler:this.configFixedCenter,value:l.FIXED_CENTER.value,validator:l.FIXED_CENTER.validator,supercedes:l.FIXED_CENTER.supercedes});o.addProperty(l.WIDTH.key,{handler:this.configWidth,suppressEvent:l.WIDTH.suppressEvent,supercedes:l.WIDTH.supercedes});o.addProperty(l.HEIGHT.key,{handler:this.configHeight,suppressEvent:l.HEIGHT.suppressEvent,supercedes:l.HEIGHT.supercedes});o.addProperty(l.AUTO_FILL_HEIGHT.key,{handler:this.configAutoFillHeight,value:l.AUTO_FILL_HEIGHT.value,validator:this._validateAutoFill,supercedes:l.AUTO_FILL_HEIGHT.supercedes});o.addProperty(l.ZINDEX.key,{handler:this.configzIndex,value:l.ZINDEX.value});o.addProperty(l.CONSTRAIN_TO_VIEWPORT.key,{handler:this.configConstrainToViewport,value:l.CONSTRAIN_TO_VIEWPORT.value,validator:l.CONSTRAIN_TO_VIEWPORT.validator,supercedes:l.CONSTRAIN_TO_VIEWPORT.supercedes});o.addProperty(l.IFRAME.key,{handler:this.configIframe,value:l.IFRAME.value,validator:l.IFRAME.validator,supercedes:l.IFRAME.supercedes});o.addProperty(l.PREVENT_CONTEXT_OVERLAP.key,{value:l.PREVENT_CONTEXT_OVERLAP.value,validator:l.PREVENT_CONTEXT_OVERLAP.validator,supercedes:l.PREVENT_CONTEXT_OVERLAP.supercedes});},moveTo:function(o,p){this.cfg.setProperty("xy",[o,p]);},hideMacGeckoScrollbars:function(){f.replaceClass(this.element,"show-scrollbars","hide-scrollbars");},showMacGeckoScrollbars:function(){f.replaceClass(this.element,"hide-scrollbars","show-scrollbars");},_setDomVisibility:function(o){f.setStyle(this.element,"visibility",(o)?"visible":"hidden");var p=b.CSS_HIDDEN;if(o){f.removeClass(this.element,p);}else{f.addClass(this.element,p);}},configVisible:function(x,w,t){var p=w[0],B=f.getStyle(this.element,"visibility"),o=this._cachedEffects||this._createEffects(this.cfg.getProperty("effect")),A=(this.platform=="mac"&&k.gecko),y=d.alreadySubscribed,q,v,s,r,u,z;if(B=="inherit"){v=this.element.parentNode;while(v.nodeType!=9&&v.nodeType!=11){B=f.getStyle(v,"visibility");if(B!="inherit"){break;}v=v.parentNode;}if(B=="inherit"){B="visible";}}if(p){if(A){this.showMacGeckoScrollbars();}if(o){if(p){if(B!="visible"||B===""||this._fadingOut){if(this.beforeShowEvent.fire()){z=o.length;for(s=0;s<z;s++){q=o[s];if(s===0&&!y(q.animateInCompleteEvent,this.showEvent.fire,this.showEvent)){q.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true);}q.animateIn();}}}}}else{if(B!="visible"||B===""){if(this.beforeShowEvent.fire()){this._setDomVisibility(true);this.cfg.refireEvent("iframe");this.showEvent.fire();}}else{this._setDomVisibility(true);}}}else{if(A){this.hideMacGeckoScrollbars();}if(o){if(B=="visible"||this._fadingIn){if(this.beforeHideEvent.fire()){z=o.length;for(r=0;r<z;r++){u=o[r];if(r===0&&!y(u.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)){u.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true);}u.animateOut();}}}else{if(B===""){this._setDomVisibility(false);}}}else{if(B=="visible"||B===""){if(this.beforeHideEvent.fire()){this._setDomVisibility(false);this.hideEvent.fire();}}else{this._setDomVisibility(false);}}}},doCenterOnDOMEvent:function(){var o=this.cfg,p=o.getProperty("fixedcenter");if(o.getProperty("visible")){if(p&&(p!==c||this.fitsInViewport())){this.center();}}},fitsInViewport:function(){var s=b.VIEWPORT_OFFSET,q=this.element,t=q.offsetWidth,r=q.offsetHeight,o=f.getViewportWidth(),p=f.getViewportHeight();return((t+s<o)&&(r+s<p));},configFixedCenter:function(s,q,t){var u=q[0],p=d.alreadySubscribed,r=b.windowResizeEvent,o=b.windowScrollEvent;if(u){this.center();if(!p(this.beforeShowEvent,this.center)){this.beforeShowEvent.subscribe(this.center);}if(!p(r,this.doCenterOnDOMEvent,this)){r.subscribe(this.doCenterOnDOMEvent,this,true);}if(!p(o,this.doCenterOnDOMEvent,this)){o.subscribe(this.doCenterOnDOMEvent,this,true);}}else{this.beforeShowEvent.unsubscribe(this.center);r.unsubscribe(this.doCenterOnDOMEvent,this);o.unsubscribe(this.doCenterOnDOMEvent,this);}},configHeight:function(r,p,s){var o=p[0],q=this.element;f.setStyle(q,"height",o);this.cfg.refireEvent("iframe");},configAutoFillHeight:function(t,s,p){var v=s[0],q=this.cfg,u="autofillheight",w="height",r=q.getProperty(u),o=this._autoFillOnHeightChange;q.unsubscribeFromConfigEvent(w,o);g.textResizeEvent.unsubscribe(o);this.changeContentEvent.unsubscribe(o);if(r&&v!==r&&this[r]){f.setStyle(this[r],w,"");}if(v){v=i.trim(v.toLowerCase());q.subscribeToConfigEvent(w,o,this[v],this);g.textResizeEvent.subscribe(o,this[v],this);this.changeContentEvent.subscribe(o,this[v],this);q.setProperty(u,v,true);}},configWidth:function(r,o,s){var q=o[0],p=this.element;f.setStyle(p,"width",q);this.cfg.refireEvent("iframe");},configzIndex:function(q,o,r){var s=o[0],p=this.element;if(!s){s=f.getStyle(p,"zIndex");if(!s||isNaN(s)){s=0;}}if(this.iframe||this.cfg.getProperty("iframe")===true){if(s<=0){s=1;}}f.setStyle(p,"zIndex",s);this.cfg.setProperty("zIndex",s,true);if(this.iframe){this.stackIframe();}},configXY:function(q,p,r){var t=p[0],o=t[0],s=t[1];this.cfg.setProperty("x",o);this.cfg.setProperty("y",s);this.beforeMoveEvent.fire([o,s]);o=this.cfg.getProperty("x");s=this.cfg.getProperty("y");this.cfg.refireEvent("iframe");this.moveEvent.fire([o,s]);},configX:function(q,p,r){var o=p[0],s=this.cfg.getProperty("y");this.cfg.setProperty("x",o,true);this.cfg.setProperty("y",s,true);this.beforeMoveEvent.fire([o,s]);o=this.cfg.getProperty("x");s=this.cfg.getProperty("y");f.setX(this.element,o,true);this.cfg.setProperty("xy",[o,s],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([o,s]);},configY:function(q,p,r){var o=this.cfg.getProperty("x"),s=p[0];this.cfg.setProperty("x",o,true);this.cfg.setProperty("y",s,true);this.beforeMoveEvent.fire([o,s]);o=this.cfg.getProperty("x");s=this.cfg.getProperty("y");f.setY(this.element,s,true);
+this.cfg.setProperty("xy",[o,s],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([o,s]);},showIframe:function(){var p=this.iframe,o;if(p){o=this.element.parentNode;if(o!=p.parentNode){this._addToParent(o,p);}p.style.display="block";}},hideIframe:function(){if(this.iframe){this.iframe.style.display="none";}},syncIframe:function(){var o=this.iframe,q=this.element,s=b.IFRAME_OFFSET,p=(s*2),r;if(o){o.style.width=(q.offsetWidth+p+"px");o.style.height=(q.offsetHeight+p+"px");r=this.cfg.getProperty("xy");if(!i.isArray(r)||(isNaN(r[0])||isNaN(r[1]))){this.syncPosition();r=this.cfg.getProperty("xy");}f.setXY(o,[(r[0]-s),(r[1]-s)]);}},stackIframe:function(){if(this.iframe){var o=f.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(o)&&!isNaN(o)){f.setStyle(this.iframe,"zIndex",(o-1));}}},configIframe:function(r,q,s){var o=q[0];function t(){var v=this.iframe,w=this.element,x;if(!v){if(!j){j=document.createElement("iframe");if(this.isSecure){j.src=b.IFRAME_SRC;}if(k.ie){j.style.filter="alpha(opacity=0)";j.frameBorder=0;}else{j.style.opacity="0";}j.style.position="absolute";j.style.border="none";j.style.margin="0";j.style.padding="0";j.style.display="none";j.tabIndex=-1;j.className=b.CSS_IFRAME;}v=j.cloneNode(false);v.id=this.id+"_f";x=w.parentNode;var u=x||document.body;this._addToParent(u,v);this.iframe=v;}this.showIframe();this.syncIframe();this.stackIframe();if(!this._hasIframeEventListeners){this.showEvent.subscribe(this.showIframe);this.hideEvent.subscribe(this.hideIframe);this.changeContentEvent.subscribe(this.syncIframe);this._hasIframeEventListeners=true;}}function p(){t.call(this);this.beforeShowEvent.unsubscribe(p);this._iframeDeferred=false;}if(o){if(this.cfg.getProperty("visible")){t.call(this);}else{if(!this._iframeDeferred){this.beforeShowEvent.subscribe(p);this._iframeDeferred=true;}}}else{this.hideIframe();if(this._hasIframeEventListeners){this.showEvent.unsubscribe(this.showIframe);this.hideEvent.unsubscribe(this.hideIframe);this.changeContentEvent.unsubscribe(this.syncIframe);this._hasIframeEventListeners=false;}}},_primeXYFromDOM:function(){if(YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))){this.syncPosition();this.cfg.refireEvent("xy");this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);}},configConstrainToViewport:function(p,o,q){var r=o[0];if(r){if(!d.alreadySubscribed(this.beforeMoveEvent,this.enforceConstraints,this)){this.beforeMoveEvent.subscribe(this.enforceConstraints,this,true);}if(!d.alreadySubscribed(this.beforeShowEvent,this._primeXYFromDOM)){this.beforeShowEvent.subscribe(this._primeXYFromDOM);}}else{this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);this.beforeMoveEvent.unsubscribe(this.enforceConstraints,this);}},configContext:function(u,t,q){var x=t[0],r,o,v,s,p,w=this.CONTEXT_TRIGGERS;if(x){r=x[0];o=x[1];v=x[2];s=x[3];p=x[4];if(w&&w.length>0){s=(s||[]).concat(w);}if(r){if(typeof r=="string"){this.cfg.setProperty("context",[document.getElementById(r),o,v,s,p],true);}if(o&&v){this.align(o,v,p);}if(this._contextTriggers){this._processTriggers(this._contextTriggers,e,this._alignOnTrigger);}if(s){this._processTriggers(s,h,this._alignOnTrigger);this._contextTriggers=s;}}}},_alignOnTrigger:function(p,o){this.align();},_findTriggerCE:function(o){var p=null;if(o instanceof m){p=o;}else{if(b._TRIGGER_MAP[o]){p=b._TRIGGER_MAP[o];}}return p;},_processTriggers:function(s,v,r){var q,u;for(var p=0,o=s.length;p<o;++p){q=s[p];u=this._findTriggerCE(q);if(u){u[v](r,this,true);}else{this[v](q,r);}}},align:function(p,w,s){var v=this.cfg.getProperty("context"),t=this,o,q,u;function r(z,A){var y=null,x=null;switch(p){case b.TOP_LEFT:y=A;x=z;break;case b.TOP_RIGHT:y=A-q.offsetWidth;x=z;break;case b.BOTTOM_LEFT:y=A;x=z-q.offsetHeight;break;case b.BOTTOM_RIGHT:y=A-q.offsetWidth;x=z-q.offsetHeight;break;}if(y!==null&&x!==null){if(s){y+=s[0];x+=s[1];}t.moveTo(y,x);}}if(v){o=v[0];q=this.element;t=this;if(!p){p=v[1];}if(!w){w=v[2];}if(!s&&v[4]){s=v[4];}if(q&&o){u=f.getRegion(o);switch(w){case b.TOP_LEFT:r(u.top,u.left);break;case b.TOP_RIGHT:r(u.top,u.right);break;case b.BOTTOM_LEFT:r(u.bottom,u.left);break;case b.BOTTOM_RIGHT:r(u.bottom,u.right);break;}}}},enforceConstraints:function(p,o,q){var s=o[0];var r=this.getConstrainedXY(s[0],s[1]);this.cfg.setProperty("x",r[0],true);this.cfg.setProperty("y",r[1],true);this.cfg.setProperty("xy",r,true);},_getConstrainedPos:function(y,p){var t=this.element,r=b.VIEWPORT_OFFSET,A=(y=="x"),z=(A)?t.offsetWidth:t.offsetHeight,s=(A)?f.getViewportWidth():f.getViewportHeight(),D=(A)?f.getDocumentScrollLeft():f.getDocumentScrollTop(),C=(A)?b.PREVENT_OVERLAP_X:b.PREVENT_OVERLAP_Y,o=this.cfg.getProperty("context"),u=(z+r<s),w=this.cfg.getProperty("preventcontextoverlap")&&o&&C[(o[1]+o[2])],v=D+r,B=D+s-z-r,q=p;if(p<v||p>B){if(w){q=this._preventOverlap(y,o[0],z,s,D);}else{if(u){if(p<v){q=v;}else{if(p>B){q=B;}}}else{q=v;}}}return q;},_preventOverlap:function(y,w,z,u,C){var A=(y=="x"),t=b.VIEWPORT_OFFSET,s=this,q=((A)?f.getX(w):f.getY(w))-C,o=(A)?w.offsetWidth:w.offsetHeight,p=q-t,r=(u-(q+o))-t,D=false,v=function(){var x;if((s.cfg.getProperty(y)-C)>q){x=(q-z);}else{x=(q+o);}s.cfg.setProperty(y,(x+C),true);return x;},B=function(){var E=((s.cfg.getProperty(y)-C)>q)?r:p,x;if(z>E){if(D){v();}else{v();D=true;x=B();}}return x;};B();return this.cfg.getProperty(y);},getConstrainedX:function(o){return this._getConstrainedPos("x",o);},getConstrainedY:function(o){return this._getConstrainedPos("y",o);},getConstrainedXY:function(o,p){return[this.getConstrainedX(o),this.getConstrainedY(p)];},center:function(){var r=b.VIEWPORT_OFFSET,s=this.element.offsetWidth,q=this.element.offsetHeight,p=f.getViewportWidth(),t=f.getViewportHeight(),o,u;if(s<p){o=(p/2)-(s/2)+f.getDocumentScrollLeft();}else{o=r+f.getDocumentScrollLeft();}if(q<t){u=(t/2)-(q/2)+f.getDocumentScrollTop();}else{u=r+f.getDocumentScrollTop();}this.cfg.setProperty("xy",[parseInt(o,10),parseInt(u,10)]);this.cfg.refireEvent("iframe");if(k.webkit){this.forceContainerRedraw();}},syncPosition:function(){var o=f.getXY(this.element);
+this.cfg.setProperty("x",o[0],true);this.cfg.setProperty("y",o[1],true);this.cfg.setProperty("xy",o,true);},onDomResize:function(q,p){var o=this;b.superclass.onDomResize.call(this,q,p);setTimeout(function(){o.syncPosition();o.cfg.refireEvent("iframe");o.cfg.refireEvent("context");},0);},_getComputedHeight:(function(){if(document.defaultView&&document.defaultView.getComputedStyle){return function(p){var o=null;if(p.ownerDocument&&p.ownerDocument.defaultView){var q=p.ownerDocument.defaultView.getComputedStyle(p,"");if(q){o=parseInt(q.height,10);}}return(i.isNumber(o))?o:null;};}else{return function(p){var o=null;if(p.style.pixelHeight){o=p.style.pixelHeight;}return(i.isNumber(o))?o:null;};}})(),_validateAutoFillHeight:function(o){return(!o)||(i.isString(o)&&b.STD_MOD_RE.test(o));},_autoFillOnHeightChange:function(r,p,q){var o=this.cfg.getProperty("height");if((o&&o!=="auto")||(o===0)){this.fillHeight(q);}},_getPreciseHeight:function(p){var o=p.offsetHeight;if(p.getBoundingClientRect){var q=p.getBoundingClientRect();o=q.bottom-q.top;}return o;},fillHeight:function(r){if(r){var p=this.innerElement||this.element,o=[this.header,this.body,this.footer],v,w=0,x=0,t=0,q=false;for(var u=0,s=o.length;u<s;u++){v=o[u];if(v){if(r!==v){x+=this._getPreciseHeight(v);}else{q=true;}}}if(q){if(k.ie||k.opera){f.setStyle(r,"height",0+"px");}w=this._getComputedHeight(p);if(w===null){f.addClass(p,"yui-override-padding");w=p.clientHeight;f.removeClass(p,"yui-override-padding");}t=Math.max(w-x,0);f.setStyle(r,"height",t+"px");if(r.offsetHeight!=t){t=Math.max(t-(r.offsetHeight-t),0);}f.setStyle(r,"height",t+"px");}}},bringToTop:function(){var s=[],r=this.element;function v(z,y){var B=f.getStyle(z,"zIndex"),A=f.getStyle(y,"zIndex"),x=(!B||isNaN(B))?0:parseInt(B,10),w=(!A||isNaN(A))?0:parseInt(A,10);if(x>w){return -1;}else{if(x<w){return 1;}else{return 0;}}}function q(y){var x=f.hasClass(y,b.CSS_OVERLAY),w=YAHOO.widget.Panel;if(x&&!f.isAncestor(r,y)){if(w&&f.hasClass(y,w.CSS_PANEL)){s[s.length]=y.parentNode;}else{s[s.length]=y;}}}f.getElementsBy(q,"div",document.body);s.sort(v);var o=s[0],u;if(o){u=f.getStyle(o,"zIndex");if(!isNaN(u)){var t=false;if(o!=r){t=true;}else{if(s.length>1){var p=f.getStyle(s[1],"zIndex");if(!isNaN(p)&&(u==p)){t=true;}}}if(t){this.cfg.setProperty("zindex",(parseInt(u,10)+2));}}}},destroy:function(o){if(this.iframe){this.iframe.parentNode.removeChild(this.iframe);}this.iframe=null;b.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent,this);b.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent,this);g.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);if(this._contextTriggers){this._processTriggers(this._contextTriggers,e,this._alignOnTrigger);}b.superclass.destroy.call(this,o);},forceContainerRedraw:function(){var o=this;f.addClass(o.element,"yui-force-redraw");setTimeout(function(){f.removeClass(o.element,"yui-force-redraw");},0);},toString:function(){return"Overlay "+this.id;}});}());(function(){YAHOO.widget.OverlayManager=function(g){this.init(g);};var d=YAHOO.widget.Overlay,c=YAHOO.util.Event,e=YAHOO.util.Dom,b=YAHOO.util.Config,f=YAHOO.util.CustomEvent,a=YAHOO.widget.OverlayManager;a.CSS_FOCUSED="focused";a.prototype={constructor:a,overlays:null,initDefaultConfig:function(){this.cfg.addProperty("overlays",{suppressEvent:true});this.cfg.addProperty("focusevent",{value:"mousedown"});},init:function(i){this.cfg=new b(this);this.initDefaultConfig();if(i){this.cfg.applyConfig(i,true);}this.cfg.fireQueue();var h=null;this.getActive=function(){return h;};this.focus=function(j){var k=this.find(j);if(k){k.focus();}};this.remove=function(k){var m=this.find(k),j;if(m){if(h==m){h=null;}var l=(m.element===null&&m.cfg===null)?true:false;if(!l){j=e.getStyle(m.element,"zIndex");m.cfg.setProperty("zIndex",-1000,true);}this.overlays.sort(this.compareZIndexDesc);this.overlays=this.overlays.slice(0,(this.overlays.length-1));m.hideEvent.unsubscribe(m.blur);m.destroyEvent.unsubscribe(this._onOverlayDestroy,m);m.focusEvent.unsubscribe(this._onOverlayFocusHandler,m);m.blurEvent.unsubscribe(this._onOverlayBlurHandler,m);if(!l){c.removeListener(m.element,this.cfg.getProperty("focusevent"),this._onOverlayElementFocus);m.cfg.setProperty("zIndex",j,true);m.cfg.setProperty("manager",null);}if(m.focusEvent._managed){m.focusEvent=null;}if(m.blurEvent._managed){m.blurEvent=null;}if(m.focus._managed){m.focus=null;}if(m.blur._managed){m.blur=null;}}};this.blurAll=function(){var k=this.overlays.length,j;if(k>0){j=k-1;do{this.overlays[j].blur();}while(j--);}};this._manageBlur=function(j){var k=false;if(h==j){e.removeClass(h.element,a.CSS_FOCUSED);h=null;k=true;}return k;};this._manageFocus=function(j){var k=false;if(h!=j){if(h){h.blur();}h=j;this.bringToTop(h);e.addClass(h.element,a.CSS_FOCUSED);k=true;}return k;};var g=this.cfg.getProperty("overlays");if(!this.overlays){this.overlays=[];}if(g){this.register(g);this.overlays.sort(this.compareZIndexDesc);}},_onOverlayElementFocus:function(i){var g=c.getTarget(i),h=this.close;if(h&&(g==h||e.isAncestor(h,g))){this.blur();}else{this.focus();}},_onOverlayDestroy:function(h,g,i){this.remove(i);},_onOverlayFocusHandler:function(h,g,i){this._manageFocus(i);},_onOverlayBlurHandler:function(h,g,i){this._manageBlur(i);},_bindFocus:function(g){var h=this;if(!g.focusEvent){g.focusEvent=g.createEvent("focus");g.focusEvent.signature=f.LIST;g.focusEvent._managed=true;}else{g.focusEvent.subscribe(h._onOverlayFocusHandler,g,h);}if(!g.focus){c.on(g.element,h.cfg.getProperty("focusevent"),h._onOverlayElementFocus,null,g);g.focus=function(){if(h._manageFocus(this)){if(this.cfg.getProperty("visible")&&this.focusFirst){this.focusFirst();}this.focusEvent.fire();}};g.focus._managed=true;}},_bindBlur:function(g){var h=this;if(!g.blurEvent){g.blurEvent=g.createEvent("blur");g.blurEvent.signature=f.LIST;g.focusEvent._managed=true;}else{g.blurEvent.subscribe(h._onOverlayBlurHandler,g,h);}if(!g.blur){g.blur=function(){if(h._manageBlur(this)){this.blurEvent.fire();}};g.blur._managed=true;}g.hideEvent.subscribe(g.blur);
+},_bindDestroy:function(g){var h=this;g.destroyEvent.subscribe(h._onOverlayDestroy,g,h);},_syncZIndex:function(g){var h=e.getStyle(g.element,"zIndex");if(!isNaN(h)){g.cfg.setProperty("zIndex",parseInt(h,10));}else{g.cfg.setProperty("zIndex",0);}},register:function(g){var k=false,h,j;if(g instanceof d){g.cfg.addProperty("manager",{value:this});this._bindFocus(g);this._bindBlur(g);this._bindDestroy(g);this._syncZIndex(g);this.overlays.push(g);this.bringToTop(g);k=true;}else{if(g instanceof Array){for(h=0,j=g.length;h<j;h++){k=this.register(g[h])||k;}}}return k;},bringToTop:function(m){var i=this.find(m),l,g,j;if(i){j=this.overlays;j.sort(this.compareZIndexDesc);g=j[0];if(g){l=e.getStyle(g.element,"zIndex");if(!isNaN(l)){var k=false;if(g!==i){k=true;}else{if(j.length>1){var h=e.getStyle(j[1].element,"zIndex");if(!isNaN(h)&&(l==h)){k=true;}}}if(k){i.cfg.setProperty("zindex",(parseInt(l,10)+2));}}j.sort(this.compareZIndexDesc);}}},find:function(g){var l=g instanceof d,j=this.overlays,p=j.length,k=null,m,h;if(l||typeof g=="string"){for(h=p-1;h>=0;h--){m=j[h];if((l&&(m===g))||(m.id==g)){k=m;break;}}}return k;},compareZIndexDesc:function(j,i){var h=(j.cfg)?j.cfg.getProperty("zIndex"):null,g=(i.cfg)?i.cfg.getProperty("zIndex"):null;if(h===null&&g===null){return 0;}else{if(h===null){return 1;}else{if(g===null){return -1;}else{if(h>g){return -1;}else{if(h<g){return 1;}else{return 0;}}}}}},showAll:function(){var h=this.overlays,j=h.length,g;for(g=j-1;g>=0;g--){h[g].show();}},hideAll:function(){var h=this.overlays,j=h.length,g;for(g=j-1;g>=0;g--){h[g].hide();}},toString:function(){return"OverlayManager";}};}());(function(){YAHOO.widget.Tooltip=function(p,o){YAHOO.widget.Tooltip.superclass.constructor.call(this,p,o);};var e=YAHOO.lang,n=YAHOO.util.Event,m=YAHOO.util.CustomEvent,c=YAHOO.util.Dom,j=YAHOO.widget.Tooltip,h=YAHOO.env.ua,g=(h.ie&&(h.ie<=6||document.compatMode=="BackCompat")),f,i={"PREVENT_OVERLAP":{key:"preventoverlap",value:true,validator:e.isBoolean,supercedes:["x","y","xy"]},"SHOW_DELAY":{key:"showdelay",value:200,validator:e.isNumber},"AUTO_DISMISS_DELAY":{key:"autodismissdelay",value:5000,validator:e.isNumber},"HIDE_DELAY":{key:"hidedelay",value:250,validator:e.isNumber},"TEXT":{key:"text",suppressEvent:true},"CONTAINER":{key:"container"},"DISABLED":{key:"disabled",value:false,suppressEvent:true},"XY_OFFSET":{key:"xyoffset",value:[0,25],suppressEvent:true}},a={"CONTEXT_MOUSE_OVER":"contextMouseOver","CONTEXT_MOUSE_OUT":"contextMouseOut","CONTEXT_TRIGGER":"contextTrigger"};j.CSS_TOOLTIP="yui-tt";function k(q,o){var p=this.cfg,r=p.getProperty("width");if(r==o){p.setProperty("width",q);}}function d(p,o){if("_originalWidth" in this){k.call(this,this._originalWidth,this._forcedWidth);}var q=document.body,u=this.cfg,t=u.getProperty("width"),r,s;if((!t||t=="auto")&&(u.getProperty("container")!=q||u.getProperty("x")>=c.getViewportWidth()||u.getProperty("y")>=c.getViewportHeight())){s=this.element.cloneNode(true);s.style.visibility="hidden";s.style.top="0px";s.style.left="0px";q.appendChild(s);r=(s.offsetWidth+"px");q.removeChild(s);s=null;u.setProperty("width",r);u.refireEvent("xy");this._originalWidth=t||"";this._forcedWidth=r;}}function b(p,o,q){this.render(q);}function l(){n.onDOMReady(b,this.cfg.getProperty("container"),this);}YAHOO.extend(j,YAHOO.widget.Overlay,{init:function(p,o){j.superclass.init.call(this,p);this.beforeInitEvent.fire(j);c.addClass(this.element,j.CSS_TOOLTIP);if(o){this.cfg.applyConfig(o,true);}this.cfg.queueProperty("visible",false);this.cfg.queueProperty("constraintoviewport",true);this.setBody("");this.subscribe("changeContent",d);this.subscribe("init",l);this.subscribe("render",this.onRender);this.initEvent.fire(j);},initEvents:function(){j.superclass.initEvents.call(this);var o=m.LIST;this.contextMouseOverEvent=this.createEvent(a.CONTEXT_MOUSE_OVER);this.contextMouseOverEvent.signature=o;this.contextMouseOutEvent=this.createEvent(a.CONTEXT_MOUSE_OUT);this.contextMouseOutEvent.signature=o;this.contextTriggerEvent=this.createEvent(a.CONTEXT_TRIGGER);this.contextTriggerEvent.signature=o;},initDefaultConfig:function(){j.superclass.initDefaultConfig.call(this);this.cfg.addProperty(i.PREVENT_OVERLAP.key,{value:i.PREVENT_OVERLAP.value,validator:i.PREVENT_OVERLAP.validator,supercedes:i.PREVENT_OVERLAP.supercedes});this.cfg.addProperty(i.SHOW_DELAY.key,{handler:this.configShowDelay,value:200,validator:i.SHOW_DELAY.validator});this.cfg.addProperty(i.AUTO_DISMISS_DELAY.key,{handler:this.configAutoDismissDelay,value:i.AUTO_DISMISS_DELAY.value,validator:i.AUTO_DISMISS_DELAY.validator});this.cfg.addProperty(i.HIDE_DELAY.key,{handler:this.configHideDelay,value:i.HIDE_DELAY.value,validator:i.HIDE_DELAY.validator});this.cfg.addProperty(i.TEXT.key,{handler:this.configText,suppressEvent:i.TEXT.suppressEvent});this.cfg.addProperty(i.CONTAINER.key,{handler:this.configContainer,value:document.body});this.cfg.addProperty(i.DISABLED.key,{handler:this.configContainer,value:i.DISABLED.value,supressEvent:i.DISABLED.suppressEvent});this.cfg.addProperty(i.XY_OFFSET.key,{value:i.XY_OFFSET.value.concat(),supressEvent:i.XY_OFFSET.suppressEvent});},configText:function(p,o,q){var r=o[0];if(r){this.setBody(r);}},configContainer:function(q,p,r){var o=p[0];if(typeof o=="string"){this.cfg.setProperty("container",document.getElementById(o),true);}},_removeEventListeners:function(){var r=this._context,o,q,p;if(r){o=r.length;if(o>0){p=o-1;do{q=r[p];n.removeListener(q,"mouseover",this.onContextMouseOver);n.removeListener(q,"mousemove",this.onContextMouseMove);n.removeListener(q,"mouseout",this.onContextMouseOut);}while(p--);}}},configContext:function(t,p,u){var s=p[0],v,o,r,q;if(s){if(!(s instanceof Array)){if(typeof s=="string"){this.cfg.setProperty("context",[document.getElementById(s)],true);}else{this.cfg.setProperty("context",[s],true);}s=this.cfg.getProperty("context");}this._removeEventListeners();this._context=s;v=this._context;if(v){o=v.length;if(o>0){q=o-1;do{r=v[q];n.on(r,"mouseover",this.onContextMouseOver,this);
+n.on(r,"mousemove",this.onContextMouseMove,this);n.on(r,"mouseout",this.onContextMouseOut,this);}while(q--);}}}},onContextMouseMove:function(p,o){o.pageX=n.getPageX(p);o.pageY=n.getPageY(p);},onContextMouseOver:function(q,p){var o=this;if(o.title){p._tempTitle=o.title;o.title="";}if(p.fireEvent("contextMouseOver",o,q)!==false&&!p.cfg.getProperty("disabled")){if(p.hideProcId){clearTimeout(p.hideProcId);p.hideProcId=null;}n.on(o,"mousemove",p.onContextMouseMove,p);p.showProcId=p.doShow(q,o);}},onContextMouseOut:function(q,p){var o=this;if(p._tempTitle){o.title=p._tempTitle;p._tempTitle=null;}if(p.showProcId){clearTimeout(p.showProcId);p.showProcId=null;}if(p.hideProcId){clearTimeout(p.hideProcId);p.hideProcId=null;}p.fireEvent("contextMouseOut",o,q);p.hideProcId=setTimeout(function(){p.hide();},p.cfg.getProperty("hidedelay"));},doShow:function(r,o){var t=this.cfg.getProperty("xyoffset"),p=t[0],s=t[1],q=this;if(h.opera&&o.tagName&&o.tagName.toUpperCase()=="A"){s+=12;}return setTimeout(function(){var u=q.cfg.getProperty("text");if(q._tempTitle&&(u===""||YAHOO.lang.isUndefined(u)||YAHOO.lang.isNull(u))){q.setBody(q._tempTitle);}else{q.cfg.refireEvent("text");}q.moveTo(q.pageX+p,q.pageY+s);if(q.cfg.getProperty("preventoverlap")){q.preventOverlap(q.pageX,q.pageY);}n.removeListener(o,"mousemove",q.onContextMouseMove);q.contextTriggerEvent.fire(o);q.show();q.hideProcId=q.doHide();},this.cfg.getProperty("showdelay"));},doHide:function(){var o=this;return setTimeout(function(){o.hide();},this.cfg.getProperty("autodismissdelay"));},preventOverlap:function(s,r){var o=this.element.offsetHeight,q=new YAHOO.util.Point(s,r),p=c.getRegion(this.element);p.top-=5;p.left-=5;p.right+=5;p.bottom+=5;if(p.contains(q)){this.cfg.setProperty("y",(r-o-5));}},onRender:function(s,r){function t(){var w=this.element,v=this.underlay;if(v){v.style.width=(w.offsetWidth+6)+"px";v.style.height=(w.offsetHeight+1)+"px";}}function p(){c.addClass(this.underlay,"yui-tt-shadow-visible");if(h.ie){this.forceUnderlayRedraw();}}function o(){c.removeClass(this.underlay,"yui-tt-shadow-visible");}function u(){var x=this.underlay,w,v,z,y;if(!x){w=this.element;v=YAHOO.widget.Module;z=h.ie;y=this;if(!f){f=document.createElement("div");f.className="yui-tt-shadow";}x=f.cloneNode(false);w.appendChild(x);this.underlay=x;this._shadow=this.underlay;p.call(this);this.subscribe("beforeShow",p);this.subscribe("hide",o);if(g){window.setTimeout(function(){t.call(y);},0);this.cfg.subscribeToConfigEvent("width",t);this.cfg.subscribeToConfigEvent("height",t);this.subscribe("changeContent",t);v.textResizeEvent.subscribe(t,this,true);this.subscribe("destroy",function(){v.textResizeEvent.unsubscribe(t,this);});}}}function q(){u.call(this);this.unsubscribe("beforeShow",q);}if(this.cfg.getProperty("visible")){u.call(this);}else{this.subscribe("beforeShow",q);}},forceUnderlayRedraw:function(){var o=this;c.addClass(o.underlay,"yui-force-redraw");setTimeout(function(){c.removeClass(o.underlay,"yui-force-redraw");},0);},destroy:function(){this._removeEventListeners();j.superclass.destroy.call(this);},toString:function(){return"Tooltip "+this.id;}});}());(function(){YAHOO.widget.Panel=function(v,u){YAHOO.widget.Panel.superclass.constructor.call(this,v,u);};var s=null;var e=YAHOO.lang,f=YAHOO.util,a=f.Dom,t=f.Event,m=f.CustomEvent,k=YAHOO.util.KeyListener,i=f.Config,h=YAHOO.widget.Overlay,o=YAHOO.widget.Panel,l=YAHOO.env.ua,p=(l.ie&&(l.ie<=6||document.compatMode=="BackCompat")),g,q,c,d={"BEFORE_SHOW_MASK":"beforeShowMask","BEFORE_HIDE_MASK":"beforeHideMask","SHOW_MASK":"showMask","HIDE_MASK":"hideMask","DRAG":"drag"},n={"CLOSE":{key:"close",value:true,validator:e.isBoolean,supercedes:["visible"]},"DRAGGABLE":{key:"draggable",value:(f.DD?true:false),validator:e.isBoolean,supercedes:["visible"]},"DRAG_ONLY":{key:"dragonly",value:false,validator:e.isBoolean,supercedes:["draggable"]},"UNDERLAY":{key:"underlay",value:"shadow",supercedes:["visible"]},"MODAL":{key:"modal",value:false,validator:e.isBoolean,supercedes:["visible","zindex"]},"KEY_LISTENERS":{key:"keylisteners",suppressEvent:true,supercedes:["visible"]},"STRINGS":{key:"strings",supercedes:["close"],validator:e.isObject,value:{close:"Close"}}};o.CSS_PANEL="yui-panel";o.CSS_PANEL_CONTAINER="yui-panel-container";o.FOCUSABLE=["a","button","select","textarea","input","iframe"];function j(v,u){if(!this.header&&this.cfg.getProperty("draggable")){this.setHeader("&#160;");}}function r(v,u,w){var z=w[0],x=w[1],y=this.cfg,A=y.getProperty("width");if(A==x){y.setProperty("width",z);}this.unsubscribe("hide",r,w);}function b(v,u){var y,x,w;if(p){y=this.cfg;x=y.getProperty("width");if(!x||x=="auto"){w=(this.element.offsetWidth+"px");y.setProperty("width",w);this.subscribe("hide",r,[(x||""),w]);}}}YAHOO.extend(o,h,{init:function(v,u){o.superclass.init.call(this,v);this.beforeInitEvent.fire(o);a.addClass(this.element,o.CSS_PANEL);this.buildWrapper();if(u){this.cfg.applyConfig(u,true);}this.subscribe("showMask",this._addFocusHandlers);this.subscribe("hideMask",this._removeFocusHandlers);this.subscribe("beforeRender",j);this.subscribe("render",function(){this.setFirstLastFocusable();this.subscribe("changeContent",this.setFirstLastFocusable);});this.subscribe("show",this._focusOnShow);this.initEvent.fire(o);},_onElementFocus:function(z){if(s===this){var y=t.getTarget(z),x=document.documentElement,v=(y!==x&&y!==window);if(v&&y!==this.element&&y!==this.mask&&!a.isAncestor(this.element,y)){try{this._focusFirstModal();}catch(w){try{if(v&&y!==document.body){y.blur();}}catch(u){}}}}},_focusFirstModal:function(){var u=this.firstElement;if(u){u.focus();}else{if(this._modalFocus){this._modalFocus.focus();}else{this.innerElement.focus();}}},_addFocusHandlers:function(v,u){if(!this.firstElement){if(l.webkit||l.opera){if(!this._modalFocus){this._createHiddenFocusElement();}}else{this.innerElement.tabIndex=0;}}this._setTabLoop(this.firstElement,this.lastElement);t.onFocus(document.documentElement,this._onElementFocus,this,true);s=this;},_createHiddenFocusElement:function(){var u=document.createElement("button");
+u.style.height="1px";u.style.width="1px";u.style.position="absolute";u.style.left="-10000em";u.style.opacity=0;u.tabIndex=-1;this.innerElement.appendChild(u);this._modalFocus=u;},_removeFocusHandlers:function(v,u){t.removeFocusListener(document.documentElement,this._onElementFocus,this);if(s==this){s=null;}},_focusOnShow:function(v,u,w){if(u&&u[1]){t.stopEvent(u[1]);}if(!this.focusFirst(v,u,w)){if(this.cfg.getProperty("modal")){this._focusFirstModal();}}},focusFirst:function(w,u,z){var v=this.firstElement,y=false;if(u&&u[1]){t.stopEvent(u[1]);}if(v){try{v.focus();y=true;}catch(x){}}return y;},focusLast:function(w,u,z){var v=this.lastElement,y=false;if(u&&u[1]){t.stopEvent(u[1]);}if(v){try{v.focus();y=true;}catch(x){}}return y;},_setTabLoop:function(u,v){this.setTabLoop(u,v);},setTabLoop:function(x,z){var v=this.preventBackTab,w=this.preventTabOut,u=this.showEvent,y=this.hideEvent;if(v){v.disable();u.unsubscribe(v.enable,v);y.unsubscribe(v.disable,v);v=this.preventBackTab=null;}if(w){w.disable();u.unsubscribe(w.enable,w);y.unsubscribe(w.disable,w);w=this.preventTabOut=null;}if(x){this.preventBackTab=new k(x,{shift:true,keys:9},{fn:this.focusLast,scope:this,correctScope:true});v=this.preventBackTab;u.subscribe(v.enable,v,true);y.subscribe(v.disable,v,true);}if(z){this.preventTabOut=new k(z,{shift:false,keys:9},{fn:this.focusFirst,scope:this,correctScope:true});w=this.preventTabOut;u.subscribe(w.enable,w,true);y.subscribe(w.disable,w,true);}},getFocusableElements:function(v){v=v||this.innerElement;var x={},u=this;for(var w=0;w<o.FOCUSABLE.length;w++){x[o.FOCUSABLE[w]]=true;}return a.getElementsBy(function(y){return u._testIfFocusable(y,x);},null,v);},_testIfFocusable:function(u,v){if(u.focus&&u.type!=="hidden"&&!u.disabled&&v[u.tagName.toLowerCase()]){return true;}return false;},setFirstLastFocusable:function(){this.firstElement=null;this.lastElement=null;var u=this.getFocusableElements();this.focusableElements=u;if(u.length>0){this.firstElement=u[0];this.lastElement=u[u.length-1];}if(this.cfg.getProperty("modal")){this._setTabLoop(this.firstElement,this.lastElement);}},initEvents:function(){o.superclass.initEvents.call(this);var u=m.LIST;this.showMaskEvent=this.createEvent(d.SHOW_MASK);this.showMaskEvent.signature=u;this.beforeShowMaskEvent=this.createEvent(d.BEFORE_SHOW_MASK);this.beforeShowMaskEvent.signature=u;this.hideMaskEvent=this.createEvent(d.HIDE_MASK);this.hideMaskEvent.signature=u;this.beforeHideMaskEvent=this.createEvent(d.BEFORE_HIDE_MASK);this.beforeHideMaskEvent.signature=u;this.dragEvent=this.createEvent(d.DRAG);this.dragEvent.signature=u;},initDefaultConfig:function(){o.superclass.initDefaultConfig.call(this);this.cfg.addProperty(n.CLOSE.key,{handler:this.configClose,value:n.CLOSE.value,validator:n.CLOSE.validator,supercedes:n.CLOSE.supercedes});this.cfg.addProperty(n.DRAGGABLE.key,{handler:this.configDraggable,value:(f.DD)?true:false,validator:n.DRAGGABLE.validator,supercedes:n.DRAGGABLE.supercedes});this.cfg.addProperty(n.DRAG_ONLY.key,{value:n.DRAG_ONLY.value,validator:n.DRAG_ONLY.validator,supercedes:n.DRAG_ONLY.supercedes});this.cfg.addProperty(n.UNDERLAY.key,{handler:this.configUnderlay,value:n.UNDERLAY.value,supercedes:n.UNDERLAY.supercedes});this.cfg.addProperty(n.MODAL.key,{handler:this.configModal,value:n.MODAL.value,validator:n.MODAL.validator,supercedes:n.MODAL.supercedes});this.cfg.addProperty(n.KEY_LISTENERS.key,{handler:this.configKeyListeners,suppressEvent:n.KEY_LISTENERS.suppressEvent,supercedes:n.KEY_LISTENERS.supercedes});this.cfg.addProperty(n.STRINGS.key,{value:n.STRINGS.value,handler:this.configStrings,validator:n.STRINGS.validator,supercedes:n.STRINGS.supercedes});},configClose:function(y,v,z){var A=v[0],x=this.close,u=this.cfg.getProperty("strings"),w;if(A){if(!x){if(!c){c=document.createElement("a");c.className="container-close";c.href="#";}x=c.cloneNode(true);w=this.innerElement.firstChild;if(w){this.innerElement.insertBefore(x,w);}else{this.innerElement.appendChild(x);}x.innerHTML=(u&&u.close)?u.close:"&#160;";t.on(x,"click",this._doClose,this,true);this.close=x;}else{x.style.display="block";}}else{if(x){x.style.display="none";}}},_doClose:function(u){t.preventDefault(u);this.hide();},configDraggable:function(v,u,w){var x=u[0];if(x){if(!f.DD){this.cfg.setProperty("draggable",false);return;}if(this.header){a.setStyle(this.header,"cursor","move");this.registerDragDrop();}this.subscribe("beforeShow",b);}else{if(this.dd){this.dd.unreg();}if(this.header){a.setStyle(this.header,"cursor","auto");}this.unsubscribe("beforeShow",b);}},configUnderlay:function(D,C,z){var B=(this.platform=="mac"&&l.gecko),E=C[0].toLowerCase(),v=this.underlay,w=this.element;function x(){var F=false;if(!v){if(!q){q=document.createElement("div");q.className="underlay";}v=q.cloneNode(false);this.element.appendChild(v);this.underlay=v;if(p){this.sizeUnderlay();this.cfg.subscribeToConfigEvent("width",this.sizeUnderlay);this.cfg.subscribeToConfigEvent("height",this.sizeUnderlay);this.changeContentEvent.subscribe(this.sizeUnderlay);YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay,this,true);}if(l.webkit&&l.webkit<420){this.changeContentEvent.subscribe(this.forceUnderlayRedraw);}F=true;}}function A(){var F=x.call(this);if(!F&&p){this.sizeUnderlay();}this._underlayDeferred=false;this.beforeShowEvent.unsubscribe(A);}function y(){if(this._underlayDeferred){this.beforeShowEvent.unsubscribe(A);this._underlayDeferred=false;}if(v){this.cfg.unsubscribeFromConfigEvent("width",this.sizeUnderlay);this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);this.changeContentEvent.unsubscribe(this.sizeUnderlay);this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay,this,true);this.element.removeChild(v);this.underlay=null;}}switch(E){case"shadow":a.removeClass(w,"matte");a.addClass(w,"shadow");break;case"matte":if(!B){y.call(this);}a.removeClass(w,"shadow");a.addClass(w,"matte");break;default:if(!B){y.call(this);
+}a.removeClass(w,"shadow");a.removeClass(w,"matte");break;}if((E=="shadow")||(B&&!v)){if(this.cfg.getProperty("visible")){var u=x.call(this);if(!u&&p){this.sizeUnderlay();}}else{if(!this._underlayDeferred){this.beforeShowEvent.subscribe(A);this._underlayDeferred=true;}}}},configModal:function(v,u,x){var w=u[0];if(w){if(!this._hasModalityEventListeners){this.subscribe("beforeShow",this.buildMask);this.subscribe("beforeShow",this.bringToTop);this.subscribe("beforeShow",this.showMask);this.subscribe("hide",this.hideMask);h.windowResizeEvent.subscribe(this.sizeMask,this,true);this._hasModalityEventListeners=true;}}else{if(this._hasModalityEventListeners){if(this.cfg.getProperty("visible")){this.hideMask();this.removeMask();}this.unsubscribe("beforeShow",this.buildMask);this.unsubscribe("beforeShow",this.bringToTop);this.unsubscribe("beforeShow",this.showMask);this.unsubscribe("hide",this.hideMask);h.windowResizeEvent.unsubscribe(this.sizeMask,this);this._hasModalityEventListeners=false;}}},removeMask:function(){var v=this.mask,u;if(v){this.hideMask();u=v.parentNode;if(u){u.removeChild(v);}this.mask=null;}},configKeyListeners:function(x,u,A){var w=u[0],z,y,v;if(w){if(w instanceof Array){y=w.length;for(v=0;v<y;v++){z=w[v];if(!i.alreadySubscribed(this.showEvent,z.enable,z)){this.showEvent.subscribe(z.enable,z,true);}if(!i.alreadySubscribed(this.hideEvent,z.disable,z)){this.hideEvent.subscribe(z.disable,z,true);this.destroyEvent.subscribe(z.disable,z,true);}}}else{if(!i.alreadySubscribed(this.showEvent,w.enable,w)){this.showEvent.subscribe(w.enable,w,true);}if(!i.alreadySubscribed(this.hideEvent,w.disable,w)){this.hideEvent.subscribe(w.disable,w,true);this.destroyEvent.subscribe(w.disable,w,true);}}}},configStrings:function(v,u,w){var x=e.merge(n.STRINGS.value,u[0]);this.cfg.setProperty(n.STRINGS.key,x,true);},configHeight:function(x,v,y){var u=v[0],w=this.innerElement;a.setStyle(w,"height",u);this.cfg.refireEvent("iframe");},_autoFillOnHeightChange:function(x,v,w){o.superclass._autoFillOnHeightChange.apply(this,arguments);if(p){var u=this;setTimeout(function(){u.sizeUnderlay();},0);}},configWidth:function(x,u,y){var w=u[0],v=this.innerElement;a.setStyle(v,"width",w);this.cfg.refireEvent("iframe");},configzIndex:function(v,u,x){o.superclass.configzIndex.call(this,v,u,x);if(this.mask||this.cfg.getProperty("modal")===true){var w=a.getStyle(this.element,"zIndex");if(!w||isNaN(w)){w=0;}if(w===0){this.cfg.setProperty("zIndex",1);}else{this.stackMask();}}},buildWrapper:function(){var w=this.element.parentNode,u=this.element,v=document.createElement("div");v.className=o.CSS_PANEL_CONTAINER;v.id=u.id+"_c";if(w){w.insertBefore(v,u);}v.appendChild(u);this.element=v;this.innerElement=u;a.setStyle(this.innerElement,"visibility","inherit");},sizeUnderlay:function(){var v=this.underlay,u;if(v){u=this.element;v.style.width=u.offsetWidth+"px";v.style.height=u.offsetHeight+"px";}},registerDragDrop:function(){var v=this;if(this.header){if(!f.DD){return;}var u=(this.cfg.getProperty("dragonly")===true);this.dd=new f.DD(this.element.id,this.id,{dragOnly:u});if(!this.header.id){this.header.id=this.id+"_h";}this.dd.startDrag=function(){var x,z,w,C,B,A;if(YAHOO.env.ua.ie==6){a.addClass(v.element,"drag");}if(v.cfg.getProperty("constraintoviewport")){var y=h.VIEWPORT_OFFSET;x=v.element.offsetHeight;z=v.element.offsetWidth;w=a.getViewportWidth();C=a.getViewportHeight();B=a.getDocumentScrollLeft();A=a.getDocumentScrollTop();if(x+y<C){this.minY=A+y;this.maxY=A+C-x-y;}else{this.minY=A+y;this.maxY=A+y;}if(z+y<w){this.minX=B+y;this.maxX=B+w-z-y;}else{this.minX=B+y;this.maxX=B+y;}this.constrainX=true;this.constrainY=true;}else{this.constrainX=false;this.constrainY=false;}v.dragEvent.fire("startDrag",arguments);};this.dd.onDrag=function(){v.syncPosition();v.cfg.refireEvent("iframe");if(this.platform=="mac"&&YAHOO.env.ua.gecko){this.showMacGeckoScrollbars();}v.dragEvent.fire("onDrag",arguments);};this.dd.endDrag=function(){if(YAHOO.env.ua.ie==6){a.removeClass(v.element,"drag");}v.dragEvent.fire("endDrag",arguments);v.moveEvent.fire(v.cfg.getProperty("xy"));};this.dd.setHandleElId(this.header.id);this.dd.addInvalidHandleType("INPUT");this.dd.addInvalidHandleType("SELECT");this.dd.addInvalidHandleType("TEXTAREA");}},buildMask:function(){var u=this.mask;if(!u){if(!g){g=document.createElement("div");g.className="mask";g.innerHTML="&#160;";}u=g.cloneNode(true);u.id=this.id+"_mask";document.body.insertBefore(u,document.body.firstChild);this.mask=u;if(YAHOO.env.ua.gecko&&this.platform=="mac"){a.addClass(this.mask,"block-scrollbars");}this.stackMask();}},hideMask:function(){if(this.cfg.getProperty("modal")&&this.mask&&this.beforeHideMaskEvent.fire()){this.mask.style.display="none";a.removeClass(document.body,"masked");this.hideMaskEvent.fire();}},showMask:function(){if(this.cfg.getProperty("modal")&&this.mask&&this.beforeShowMaskEvent.fire()){a.addClass(document.body,"masked");this.sizeMask();this.mask.style.display="block";this.showMaskEvent.fire();}},sizeMask:function(){if(this.mask){var v=this.mask,w=a.getViewportWidth(),u=a.getViewportHeight();if(v.offsetHeight>u){v.style.height=u+"px";}if(v.offsetWidth>w){v.style.width=w+"px";}v.style.height=a.getDocumentHeight()+"px";v.style.width=a.getDocumentWidth()+"px";}},stackMask:function(){if(this.mask){var u=a.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(u)&&!isNaN(u)){a.setStyle(this.mask,"zIndex",u-1);}}},render:function(u){return o.superclass.render.call(this,u,this.innerElement);},_renderHeader:function(u){u=u||this.innerElement;o.superclass._renderHeader.call(this,u);},_renderBody:function(u){u=u||this.innerElement;o.superclass._renderBody.call(this,u);},_renderFooter:function(u){u=u||this.innerElement;o.superclass._renderFooter.call(this,u);},destroy:function(u){h.windowResizeEvent.unsubscribe(this.sizeMask,this);this.removeMask();if(this.close){t.purgeElement(this.close);}o.superclass.destroy.call(this,u);},forceUnderlayRedraw:function(){var v=this.underlay;a.addClass(v,"yui-force-redraw");
+setTimeout(function(){a.removeClass(v,"yui-force-redraw");},0);},toString:function(){return"Panel "+this.id;}});}());(function(){YAHOO.widget.Dialog=function(j,i){YAHOO.widget.Dialog.superclass.constructor.call(this,j,i);};var b=YAHOO.util.Event,g=YAHOO.util.CustomEvent,e=YAHOO.util.Dom,a=YAHOO.widget.Dialog,f=YAHOO.lang,h={"BEFORE_SUBMIT":"beforeSubmit","SUBMIT":"submit","MANUAL_SUBMIT":"manualSubmit","ASYNC_SUBMIT":"asyncSubmit","FORM_SUBMIT":"formSubmit","CANCEL":"cancel"},c={"POST_METHOD":{key:"postmethod",value:"async"},"POST_DATA":{key:"postdata",value:null},"BUTTONS":{key:"buttons",value:"none",supercedes:["visible"]},"HIDEAFTERSUBMIT":{key:"hideaftersubmit",value:true}};a.CSS_DIALOG="yui-dialog";function d(){var m=this._aButtons,k,l,j;if(f.isArray(m)){k=m.length;if(k>0){j=k-1;do{l=m[j];if(YAHOO.widget.Button&&l instanceof YAHOO.widget.Button){l.destroy();}else{if(l.tagName.toUpperCase()=="BUTTON"){b.purgeElement(l);b.purgeElement(l,false);}}}while(j--);}}}YAHOO.extend(a,YAHOO.widget.Panel,{form:null,initDefaultConfig:function(){a.superclass.initDefaultConfig.call(this);this.callback={success:null,failure:null,argument:null};this.cfg.addProperty(c.POST_METHOD.key,{handler:this.configPostMethod,value:c.POST_METHOD.value,validator:function(i){if(i!="form"&&i!="async"&&i!="none"&&i!="manual"){return false;}else{return true;}}});this.cfg.addProperty(c.POST_DATA.key,{value:c.POST_DATA.value});this.cfg.addProperty(c.HIDEAFTERSUBMIT.key,{value:c.HIDEAFTERSUBMIT.value});this.cfg.addProperty(c.BUTTONS.key,{handler:this.configButtons,value:c.BUTTONS.value,supercedes:c.BUTTONS.supercedes});},initEvents:function(){a.superclass.initEvents.call(this);var i=g.LIST;this.beforeSubmitEvent=this.createEvent(h.BEFORE_SUBMIT);this.beforeSubmitEvent.signature=i;this.submitEvent=this.createEvent(h.SUBMIT);this.submitEvent.signature=i;this.manualSubmitEvent=this.createEvent(h.MANUAL_SUBMIT);this.manualSubmitEvent.signature=i;this.asyncSubmitEvent=this.createEvent(h.ASYNC_SUBMIT);this.asyncSubmitEvent.signature=i;this.formSubmitEvent=this.createEvent(h.FORM_SUBMIT);this.formSubmitEvent.signature=i;this.cancelEvent=this.createEvent(h.CANCEL);this.cancelEvent.signature=i;},init:function(j,i){a.superclass.init.call(this,j);this.beforeInitEvent.fire(a);e.addClass(this.element,a.CSS_DIALOG);this.cfg.setProperty("visible",false);if(i){this.cfg.applyConfig(i,true);}this.beforeHideEvent.subscribe(this.blurButtons,this,true);this.subscribe("changeBody",this.registerForm);this.initEvent.fire(a);},doSubmit:function(){var q=YAHOO.util.Connect,r=this.form,l=false,o=false,s,n,m,j;switch(this.cfg.getProperty("postmethod")){case"async":s=r.elements;n=s.length;if(n>0){m=n-1;do{if(s[m].type=="file"){l=true;break;}}while(m--);}if(l&&YAHOO.env.ua.ie&&this.isSecure){o=true;}j=this._getFormAttributes(r);q.setForm(r,l,o);var k=this.cfg.getProperty("postdata");var p=q.asyncRequest(j.method,j.action,this.callback,k);this.asyncSubmitEvent.fire(p);break;case"form":r.submit();this.formSubmitEvent.fire();break;case"none":case"manual":this.manualSubmitEvent.fire();break;}},_getFormAttributes:function(k){var i={method:null,action:null};if(k){if(k.getAttributeNode){var j=k.getAttributeNode("action");var l=k.getAttributeNode("method");if(j){i.action=j.value;}if(l){i.method=l.value;}}else{i.action=k.getAttribute("action");i.method=k.getAttribute("method");}}i.method=(f.isString(i.method)?i.method:"POST").toUpperCase();i.action=f.isString(i.action)?i.action:"";return i;},registerForm:function(){var i=this.element.getElementsByTagName("form")[0];if(this.form){if(this.form==i&&e.isAncestor(this.element,this.form)){return;}else{b.purgeElement(this.form);this.form=null;}}if(!i){i=document.createElement("form");i.name="frm_"+this.id;this.body.appendChild(i);}if(i){this.form=i;b.on(i,"submit",this._submitHandler,this,true);}},_submitHandler:function(i){b.stopEvent(i);this.submit();this.form.blur();},setTabLoop:function(i,j){i=i||this.firstButton;j=j||this.lastButton;a.superclass.setTabLoop.call(this,i,j);},_setTabLoop:function(i,j){i=i||this.firstButton;j=this.lastButton||j;this.setTabLoop(i,j);},setFirstLastFocusable:function(){a.superclass.setFirstLastFocusable.call(this);var k,j,m,n=this.focusableElements;this.firstFormElement=null;this.lastFormElement=null;if(this.form&&n&&n.length>0){j=n.length;for(k=0;k<j;++k){m=n[k];if(this.form===m.form){this.firstFormElement=m;break;}}for(k=j-1;k>=0;--k){m=n[k];if(this.form===m.form){this.lastFormElement=m;break;}}}},configClose:function(j,i,k){a.superclass.configClose.apply(this,arguments);},_doClose:function(i){b.preventDefault(i);this.cancel();},configButtons:function(t,s,n){var o=YAHOO.widget.Button,v=s[0],l=this.innerElement,u,q,k,r,p,j,m;d.call(this);this._aButtons=null;if(f.isArray(v)){p=document.createElement("span");p.className="button-group";r=v.length;this._aButtons=[];this.defaultHtmlButton=null;for(m=0;m<r;m++){u=v[m];if(o){k=new o({label:u.text,type:u.type});k.appendTo(p);q=k.get("element");if(u.isDefault){k.addClass("default");this.defaultHtmlButton=q;}if(f.isFunction(u.handler)){k.set("onclick",{fn:u.handler,obj:this,scope:this});}else{if(f.isObject(u.handler)&&f.isFunction(u.handler.fn)){k.set("onclick",{fn:u.handler.fn,obj:((!f.isUndefined(u.handler.obj))?u.handler.obj:this),scope:(u.handler.scope||this)});}}this._aButtons[this._aButtons.length]=k;}else{q=document.createElement("button");q.setAttribute("type","button");if(u.isDefault){q.className="default";this.defaultHtmlButton=q;}q.innerHTML=u.text;if(f.isFunction(u.handler)){b.on(q,"click",u.handler,this,true);}else{if(f.isObject(u.handler)&&f.isFunction(u.handler.fn)){b.on(q,"click",u.handler.fn,((!f.isUndefined(u.handler.obj))?u.handler.obj:this),(u.handler.scope||this));}}p.appendChild(q);this._aButtons[this._aButtons.length]=q;}u.htmlButton=q;if(m===0){this.firstButton=q;}if(m==(r-1)){this.lastButton=q;}}this.setFooter(p);j=this.footer;if(e.inDocument(this.element)&&!e.isAncestor(l,j)){l.appendChild(j);}this.buttonSpan=p;}else{p=this.buttonSpan;
+j=this.footer;if(p&&j){j.removeChild(p);this.buttonSpan=null;this.firstButton=null;this.lastButton=null;this.defaultHtmlButton=null;}}this.changeContentEvent.fire();},getButtons:function(){return this._aButtons||null;},focusFirst:function(k,i,n){var j=this.firstFormElement,m=false;if(i&&i[1]){b.stopEvent(i[1]);if(i[0]===9&&this.firstElement){j=this.firstElement;}}if(j){try{j.focus();m=true;}catch(l){}}else{if(this.defaultHtmlButton){m=this.focusDefaultButton();}else{m=this.focusFirstButton();}}return m;},focusLast:function(k,i,n){var o=this.cfg.getProperty("buttons"),j=this.lastFormElement,m=false;if(i&&i[1]){b.stopEvent(i[1]);if(i[0]===9&&this.lastElement){j=this.lastElement;}}if(o&&f.isArray(o)){m=this.focusLastButton();}else{if(j){try{j.focus();m=true;}catch(l){}}}return m;},_getButton:function(j){var i=YAHOO.widget.Button;if(i&&j&&j.nodeName&&j.id){j=i.getButton(j.id)||j;}return j;},focusDefaultButton:function(){var i=this._getButton(this.defaultHtmlButton),k=false;if(i){try{i.focus();k=true;}catch(j){}}return k;},blurButtons:function(){var o=this.cfg.getProperty("buttons"),l,n,k,j;if(o&&f.isArray(o)){l=o.length;if(l>0){j=(l-1);do{n=o[j];if(n){k=this._getButton(n.htmlButton);if(k){try{k.blur();}catch(m){}}}}while(j--);}}},focusFirstButton:function(){var m=this.cfg.getProperty("buttons"),k,i,l=false;if(m&&f.isArray(m)){k=m[0];if(k){i=this._getButton(k.htmlButton);if(i){try{i.focus();l=true;}catch(j){}}}}return l;},focusLastButton:function(){var n=this.cfg.getProperty("buttons"),j,l,i,m=false;if(n&&f.isArray(n)){j=n.length;if(j>0){l=n[(j-1)];if(l){i=this._getButton(l.htmlButton);if(i){try{i.focus();m=true;}catch(k){}}}}}return m;},configPostMethod:function(j,i,k){this.registerForm();},validate:function(){return true;},submit:function(){if(this.validate()){if(this.beforeSubmitEvent.fire()){this.doSubmit();this.submitEvent.fire();if(this.cfg.getProperty("hideaftersubmit")){this.hide();}return true;}else{return false;}}else{return false;}},cancel:function(){this.cancelEvent.fire();this.hide();},getData:function(){var A=this.form,k,t,w,m,u,r,q,j,x,l,y,B,p,C,o,z,v;function s(n){var i=n.tagName.toUpperCase();return((i=="INPUT"||i=="TEXTAREA"||i=="SELECT")&&n.name==m);}if(A){k=A.elements;t=k.length;w={};for(z=0;z<t;z++){m=k[z].name;u=e.getElementsBy(s,"*",A);r=u.length;if(r>0){if(r==1){u=u[0];q=u.type;j=u.tagName.toUpperCase();switch(j){case"INPUT":if(q=="checkbox"){w[m]=u.checked;}else{if(q!="radio"){w[m]=u.value;}}break;case"TEXTAREA":w[m]=u.value;break;case"SELECT":x=u.options;l=x.length;y=[];for(v=0;v<l;v++){B=x[v];if(B.selected){o=B.attributes.value;y[y.length]=(o&&o.specified)?B.value:B.text;}}w[m]=y;break;}}else{q=u[0].type;switch(q){case"radio":for(v=0;v<r;v++){p=u[v];if(p.checked){w[m]=p.value;break;}}break;case"checkbox":y=[];for(v=0;v<r;v++){C=u[v];if(C.checked){y[y.length]=C.value;}}w[m]=y;break;}}}}}return w;},destroy:function(i){d.call(this);this._aButtons=null;var j=this.element.getElementsByTagName("form"),k;if(j.length>0){k=j[0];if(k){b.purgeElement(k);if(k.parentNode){k.parentNode.removeChild(k);}this.form=null;}}a.superclass.destroy.call(this,i);},toString:function(){return"Dialog "+this.id;}});}());(function(){YAHOO.widget.SimpleDialog=function(e,d){YAHOO.widget.SimpleDialog.superclass.constructor.call(this,e,d);};var c=YAHOO.util.Dom,b=YAHOO.widget.SimpleDialog,a={"ICON":{key:"icon",value:"none",suppressEvent:true},"TEXT":{key:"text",value:"",suppressEvent:true,supercedes:["icon"]}};b.ICON_BLOCK="blckicon";b.ICON_ALARM="alrticon";b.ICON_HELP="hlpicon";b.ICON_INFO="infoicon";b.ICON_WARN="warnicon";b.ICON_TIP="tipicon";b.ICON_CSS_CLASSNAME="yui-icon";b.CSS_SIMPLEDIALOG="yui-simple-dialog";YAHOO.extend(b,YAHOO.widget.Dialog,{initDefaultConfig:function(){b.superclass.initDefaultConfig.call(this);this.cfg.addProperty(a.ICON.key,{handler:this.configIcon,value:a.ICON.value,suppressEvent:a.ICON.suppressEvent});this.cfg.addProperty(a.TEXT.key,{handler:this.configText,value:a.TEXT.value,suppressEvent:a.TEXT.suppressEvent,supercedes:a.TEXT.supercedes});},init:function(e,d){b.superclass.init.call(this,e);this.beforeInitEvent.fire(b);c.addClass(this.element,b.CSS_SIMPLEDIALOG);this.cfg.queueProperty("postmethod","manual");if(d){this.cfg.applyConfig(d,true);}this.beforeRenderEvent.subscribe(function(){if(!this.body){this.setBody("");}},this,true);this.initEvent.fire(b);},registerForm:function(){b.superclass.registerForm.call(this);var e=this.form.ownerDocument,d=e.createElement("input");d.type="hidden";d.name=this.id;d.value="";this.form.appendChild(d);},configIcon:function(k,j,h){var d=j[0],e=this.body,f=b.ICON_CSS_CLASSNAME,l,i,g;if(d&&d!="none"){l=c.getElementsByClassName(f,"*",e);if(l.length===1){i=l[0];g=i.parentNode;if(g){g.removeChild(i);i=null;}}if(d.indexOf(".")==-1){i=document.createElement("span");i.className=(f+" "+d);i.innerHTML="&#160;";}else{i=document.createElement("img");i.src=(this.imageRoot+d);i.className=f;}if(i){e.insertBefore(i,e.firstChild);}}},configText:function(e,d,f){var g=d[0];if(g){this.setBody(g);this.cfg.refireEvent("icon");}},toString:function(){return"SimpleDialog "+this.id;}});}());(function(){YAHOO.widget.ContainerEffect=function(e,h,g,d,f){if(!f){f=YAHOO.util.Anim;}this.overlay=e;this.attrIn=h;this.attrOut=g;this.targetElement=d||e.element;this.animClass=f;};var b=YAHOO.util.Dom,c=YAHOO.util.CustomEvent,a=YAHOO.widget.ContainerEffect;a.FADE=function(d,f){var g=YAHOO.util.Easing,i={attributes:{opacity:{from:0,to:1}},duration:f,method:g.easeIn},e={attributes:{opacity:{to:0}},duration:f,method:g.easeOut},h=new a(d,i,e,d.element);h.handleUnderlayStart=function(){var k=this.overlay.underlay;if(k&&YAHOO.env.ua.ie){var j=(k.filters&&k.filters.length>0);if(j){b.addClass(d.element,"yui-effect-fade");}}};h.handleUnderlayComplete=function(){var j=this.overlay.underlay;if(j&&YAHOO.env.ua.ie){b.removeClass(d.element,"yui-effect-fade");}};h.handleStartAnimateIn=function(k,j,l){l.overlay._fadingIn=true;b.addClass(l.overlay.element,"hide-select");if(!l.overlay.underlay){l.overlay.cfg.refireEvent("underlay");
+}l.handleUnderlayStart();l.overlay._setDomVisibility(true);b.setStyle(l.overlay.element,"opacity",0);};h.handleCompleteAnimateIn=function(k,j,l){l.overlay._fadingIn=false;b.removeClass(l.overlay.element,"hide-select");if(l.overlay.element.style.filter){l.overlay.element.style.filter=null;}l.handleUnderlayComplete();l.overlay.cfg.refireEvent("iframe");l.animateInCompleteEvent.fire();};h.handleStartAnimateOut=function(k,j,l){l.overlay._fadingOut=true;b.addClass(l.overlay.element,"hide-select");l.handleUnderlayStart();};h.handleCompleteAnimateOut=function(k,j,l){l.overlay._fadingOut=false;b.removeClass(l.overlay.element,"hide-select");if(l.overlay.element.style.filter){l.overlay.element.style.filter=null;}l.overlay._setDomVisibility(false);b.setStyle(l.overlay.element,"opacity",1);l.handleUnderlayComplete();l.overlay.cfg.refireEvent("iframe");l.animateOutCompleteEvent.fire();};h.init();return h;};a.SLIDE=function(f,d){var i=YAHOO.util.Easing,l=f.cfg.getProperty("x")||b.getX(f.element),k=f.cfg.getProperty("y")||b.getY(f.element),m=b.getClientWidth(),h=f.element.offsetWidth,j={attributes:{points:{to:[l,k]}},duration:d,method:i.easeIn},e={attributes:{points:{to:[(m+25),k]}},duration:d,method:i.easeOut},g=new a(f,j,e,f.element,YAHOO.util.Motion);g.handleStartAnimateIn=function(o,n,p){p.overlay.element.style.left=((-25)-h)+"px";p.overlay.element.style.top=k+"px";};g.handleTweenAnimateIn=function(q,p,r){var s=b.getXY(r.overlay.element),o=s[0],n=s[1];if(b.getStyle(r.overlay.element,"visibility")=="hidden"&&o<l){r.overlay._setDomVisibility(true);}r.overlay.cfg.setProperty("xy",[o,n],true);r.overlay.cfg.refireEvent("iframe");};g.handleCompleteAnimateIn=function(o,n,p){p.overlay.cfg.setProperty("xy",[l,k],true);p.startX=l;p.startY=k;p.overlay.cfg.refireEvent("iframe");p.animateInCompleteEvent.fire();};g.handleStartAnimateOut=function(o,n,r){var p=b.getViewportWidth(),s=b.getXY(r.overlay.element),q=s[1];r.animOut.attributes.points.to=[(p+25),q];};g.handleTweenAnimateOut=function(p,o,q){var s=b.getXY(q.overlay.element),n=s[0],r=s[1];q.overlay.cfg.setProperty("xy",[n,r],true);q.overlay.cfg.refireEvent("iframe");};g.handleCompleteAnimateOut=function(o,n,p){p.overlay._setDomVisibility(false);p.overlay.cfg.setProperty("xy",[l,k]);p.animateOutCompleteEvent.fire();};g.init();return g;};a.prototype={init:function(){this.beforeAnimateInEvent=this.createEvent("beforeAnimateIn");this.beforeAnimateInEvent.signature=c.LIST;this.beforeAnimateOutEvent=this.createEvent("beforeAnimateOut");this.beforeAnimateOutEvent.signature=c.LIST;this.animateInCompleteEvent=this.createEvent("animateInComplete");this.animateInCompleteEvent.signature=c.LIST;this.animateOutCompleteEvent=this.createEvent("animateOutComplete");this.animateOutCompleteEvent.signature=c.LIST;this.animIn=new this.animClass(this.targetElement,this.attrIn.attributes,this.attrIn.duration,this.attrIn.method);this.animIn.onStart.subscribe(this.handleStartAnimateIn,this);this.animIn.onTween.subscribe(this.handleTweenAnimateIn,this);this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,this);this.animOut=new this.animClass(this.targetElement,this.attrOut.attributes,this.attrOut.duration,this.attrOut.method);this.animOut.onStart.subscribe(this.handleStartAnimateOut,this);this.animOut.onTween.subscribe(this.handleTweenAnimateOut,this);this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,this);},animateIn:function(){this._stopAnims(this.lastFrameOnStop);this.beforeAnimateInEvent.fire();this.animIn.animate();},animateOut:function(){this._stopAnims(this.lastFrameOnStop);this.beforeAnimateOutEvent.fire();this.animOut.animate();},lastFrameOnStop:true,_stopAnims:function(d){if(this.animOut&&this.animOut.isAnimated()){this.animOut.stop(d);}if(this.animIn&&this.animIn.isAnimated()){this.animIn.stop(d);}},handleStartAnimateIn:function(e,d,f){},handleTweenAnimateIn:function(e,d,f){},handleCompleteAnimateIn:function(e,d,f){},handleStartAnimateOut:function(e,d,f){},handleTweenAnimateOut:function(e,d,f){},handleCompleteAnimateOut:function(e,d,f){},toString:function(){var d="ContainerEffect";if(this.overlay){d+=" ["+this.overlay.toString()+"]";}return d;}};YAHOO.lang.augmentProto(a,YAHOO.util.EventProvider);})();YAHOO.register("container",YAHOO.widget.Module,{version:"2.9.0",build:"2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+var Y=YAHOO,Y_DOM=YAHOO.util.Dom,EMPTY_ARRAY=[],Y_UA=Y.env.ua,Y_Lang=Y.lang,Y_DOC=document,Y_DOCUMENT_ELEMENT=Y_DOC.documentElement,Y_DOM_inDoc=Y_DOM.inDocument,Y_mix=Y_Lang.augmentObject,Y_guid=Y_DOM.generateId,Y_getDoc=function(a){var b=Y_DOC;if(a){b=(a.nodeType===9)?a:a.ownerDocument||a.document||Y_DOC;}return b;},Y_Array=function(g,d){var c,b,h=d||0;try{return Array.prototype.slice.call(g,h);}catch(f){b=[];c=g.length;for(;h<c;h++){b.push(g[h]);}return b;}},Y_DOM_allById=function(f,a){a=a||Y_DOC;var b=[],c=[],d,e;if(a.querySelectorAll){c=a.querySelectorAll('[id="'+f+'"]');}else{if(a.all){b=a.all(f);if(b){if(b.nodeName){if(b.id===f){c.push(b);b=EMPTY_ARRAY;}else{b=[b];}}if(b.length){for(d=0;e=b[d++];){if(e.id===f||(e.attributes&&e.attributes.id&&e.attributes.id.value===f)){c.push(e);}}}}}else{c=[Y_getDoc(a).getElementById(f)];}}return c;};var COMPARE_DOCUMENT_POSITION="compareDocumentPosition",OWNER_DOCUMENT="ownerDocument",Selector={_foundCache:[],useNative:true,_compare:("sourceIndex" in Y_DOCUMENT_ELEMENT)?function(f,e){var d=f.sourceIndex,c=e.sourceIndex;if(d===c){return 0;}else{if(d>c){return 1;}}return -1;}:(Y_DOCUMENT_ELEMENT[COMPARE_DOCUMENT_POSITION]?function(b,a){if(b[COMPARE_DOCUMENT_POSITION](a)&4){return -1;}else{return 1;}}:function(e,d){var c,a,b;if(e&&d){c=e[OWNER_DOCUMENT].createRange();c.setStart(e,0);a=d[OWNER_DOCUMENT].createRange();a.setStart(d,0);b=c.compareBoundaryPoints(1,a);}return b;}),_sort:function(a){if(a){a=Y_Array(a,0,true);if(a.sort){a.sort(Selector._compare);}}return a;},_deDupe:function(a){var b=[],c,d;for(c=0;(d=a[c++]);){if(!d._found){b[b.length]=d;d._found=true;}}for(c=0;(d=b[c++]);){d._found=null;d.removeAttribute("_found");}return b;},query:function(b,j,k,a){if(j&&typeof j=="string"){j=Y_DOM.get(j);if(!j){return(k)?null:[];}}else{j=j||Y_DOC;}var f=[],c=(Selector.useNative&&Y_DOC.querySelector&&!a),e=[[b,j]],g,l,d,h=(c)?Selector._nativeQuery:Selector._bruteQuery;if(b&&h){if(!a&&(!c||j.tagName)){e=Selector._splitQueries(b,j);}for(d=0;(g=e[d++]);){l=h(g[0],g[1],k);if(!k){l=Y_Array(l,0,true);}if(l){f=f.concat(l);}}if(e.length>1){f=Selector._sort(Selector._deDupe(f));}}return(k)?(f[0]||null):f;},_splitQueries:function(c,f){var b=c.split(","),d=[],g="",e,a;if(f){if(f.tagName){f.id=f.id||Y_guid();g='[id="'+f.id+'"] ';}for(e=0,a=b.length;e<a;++e){c=g+b[e];d.push([c,f]);}}return d;},_nativeQuery:function(a,b,c){if(Y_UA.webkit&&a.indexOf(":checked")>-1&&(Selector.pseudos&&Selector.pseudos.checked)){return Selector.query(a,b,c,true);}try{return b["querySelector"+(c?"":"All")](a);}catch(d){return Selector.query(a,b,c,true);}},filter:function(b,a){var c=[],d,e;if(b&&a){for(d=0;(e=b[d++]);){if(Selector.test(e,a)){c[c.length]=e;}}}else{}return c;},test:function(c,d,k){var g=false,b=d.split(","),a=false,l,o,h,n,f,e,m;if(c&&c.tagName){if(!k&&!Y_DOM_inDoc(c)){l=c.parentNode;if(l){k=l;}else{n=c[OWNER_DOCUMENT].createDocumentFragment();n.appendChild(c);k=n;a=true;}}k=k||c[OWNER_DOCUMENT];if(!c.id){c.id=Y_guid();}for(f=0;(m=b[f++]);){m+='[id="'+c.id+'"]';h=Selector.query(m,k);for(e=0;o=h[e++];){if(o===c){g=true;break;}}if(g){break;}}if(a){n.removeChild(c);}}return g;}};YAHOO.util.Selector=Selector;var PARENT_NODE="parentNode",TAG_NAME="tagName",ATTRIBUTES="attributes",COMBINATOR="combinator",PSEUDOS="pseudos",SelectorCSS2={_reRegExpTokens:/([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,SORT_RESULTS:true,_children:function(e,a){var b=e.children,d,c=[],f,g;if(e.children&&a&&e.children.tags){c=e.children.tags(a);}else{if((!b&&e[TAG_NAME])||(b&&a)){f=b||e.childNodes;b=[];for(d=0;(g=f[d++]);){if(g.tagName){if(!a||a===g.tagName){b.push(g);}}}}}return b||[];},_re:{attr:/(\[[^\]]*\])/g,esc:/\\[:\[\]\(\)#\.\'\>+~"]/gi,pseudos:/(\([^\)]*\))/g},shorthand:{"\\#(-?[_a-z]+[-\\w\\uE000]*)":"[id=$1]","\\.(-?[_a-z]+[-\\w\\uE000]*)":"[className~=$1]"},operators:{"":function(b,a){return !!b.getAttribute(a);},"~=":"(?:^|\\s+){val}(?:\\s+|$)","|=":"^{val}(?:-|$)"},pseudos:{"first-child":function(a){return Selector._children(a[PARENT_NODE])[0]===a;}},_bruteQuery:function(f,j,l){var g=[],a=[],i=Selector._tokenize(f),e=i[i.length-1],k=Y_getDoc(j),c,b,h,d;if(e){b=e.id;h=e.className;d=e.tagName||"*";if(j.getElementsByTagName){if(b&&(j.all||(j.nodeType===9||Y_DOM_inDoc(j)))){a=Y_DOM_allById(b,j);}else{if(h){a=j.getElementsByClassName(h);}else{a=j.getElementsByTagName(d);}}}else{c=j.firstChild;while(c){if(c.tagName){a.push(c);}c=c.nextSilbing||c.firstChild;}}if(a.length){g=Selector._filterNodes(a,i,l);}}return g;},_filterNodes:function(l,f,h){var r=0,q,s=f.length,k=s-1,e=[],o=l[0],v=o,t=Selector.getters,d,p,c,g,a,m,b,u;for(r=0;(v=o=l[r++]);){k=s-1;g=null;testLoop:while(v&&v.tagName){c=f[k];b=c.tests;q=b.length;if(q&&!a){while((u=b[--q])){d=u[1];if(t[u[0]]){m=t[u[0]](v,u[0]);}else{m=v[u[0]];if(m===undefined&&v.getAttribute){m=v.getAttribute(u[0]);}}if((d==="="&&m!==u[2])||(typeof d!=="string"&&d.test&&!d.test(m))||(!d.test&&typeof d==="function"&&!d(v,u[0],u[2]))){if((v=v[g])){while(v&&(!v.tagName||(c.tagName&&c.tagName!==v.tagName))){v=v[g];}}continue testLoop;}}}k--;if(!a&&(p=c.combinator)){g=p.axis;v=v[g];while(v&&!v.tagName){v=v[g];}if(p.direct){g=null;}}else{e.push(o);if(h){return e;}break;}}}o=v=null;return e;},combinators:{" ":{axis:"parentNode"},">":{axis:"parentNode",direct:true},"+":{axis:"previousSibling",direct:true}},_parsers:[{name:ATTRIBUTES,re:/^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,fn:function(d,e){var c=d[2]||"",a=Selector.operators,b=(d[3])?d[3].replace(/\\/g,""):"",f;if((d[1]==="id"&&c==="=")||(d[1]==="className"&&Y_DOCUMENT_ELEMENT.getElementsByClassName&&(c==="~="||c==="="))){e.prefilter=d[1];d[3]=b;e[d[1]]=(d[1]==="id")?d[3]:b;}if(c in a){f=a[c];if(typeof f==="string"){d[3]=b.replace(Selector._reRegExpTokens,"\\$1");f=new RegExp(f.replace("{val}",d[3]));}d[2]=f;}if(!e.last||e.prefilter!==d[1]){return d.slice(1);}}},{name:TAG_NAME,re:/^((?:-?[_a-z]+[\w-]*)|\*)/i,fn:function(b,c){var a=b[1].toUpperCase();c.tagName=a;if(a!=="*"&&(!c.last||c.prefilter)){return[TAG_NAME,"=",a];
+}if(!c.prefilter){c.prefilter="tagName";}}},{name:COMBINATOR,re:/^\s*([>+~]|\s)\s*/,fn:function(a,b){}},{name:PSEUDOS,re:/^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,fn:function(a,b){var c=Selector[PSEUDOS][a[1]];if(c){if(a[2]){a[2]=a[2].replace(/\\/g,"");}return[a[2],c];}else{return false;}}}],_getToken:function(a){return{tagName:null,id:null,className:null,attributes:{},combinator:null,tests:[]};},_tokenize:function(c){c=c||"";c=Selector._replaceShorthand(Y_Lang.trim(c));var b=Selector._getToken(),h=c,g=[],j=false,e,f,d,a;outer:do{j=false;for(d=0;(a=Selector._parsers[d++]);){if((e=a.re.exec(c))){if(a.name!==COMBINATOR){b.selector=c;}c=c.replace(e[0],"");if(!c.length){b.last=true;}if(Selector._attrFilters[e[1]]){e[1]=Selector._attrFilters[e[1]];}f=a.fn(e,b);if(f===false){j=false;break outer;}else{if(f){b.tests.push(f);}}if(!c.length||a.name===COMBINATOR){g.push(b);b=Selector._getToken(b);if(a.name===COMBINATOR){b.combinator=Selector.combinators[e[1]];}}j=true;}}}while(j&&c.length);if(!j||c.length){g=[];}return g;},_replaceShorthand:function(b){var d=Selector.shorthand,c=b.match(Selector._re.esc),e,h,g,f,a;if(c){b=b.replace(Selector._re.esc,"\uE000");}e=b.match(Selector._re.attr);h=b.match(Selector._re.pseudos);if(e){b=b.replace(Selector._re.attr,"\uE001");}if(h){b=b.replace(Selector._re.pseudos,"\uE002");}for(g in d){if(d.hasOwnProperty(g)){b=b.replace(new RegExp(g,"gi"),d[g]);}}if(e){for(f=0,a=e.length;f<a;++f){b=b.replace(/\uE001/,e[f]);}}if(h){for(f=0,a=h.length;f<a;++f){b=b.replace(/\uE002/,h[f]);}}b=b.replace(/\[/g,"\uE003");b=b.replace(/\]/g,"\uE004");b=b.replace(/\(/g,"\uE005");b=b.replace(/\)/g,"\uE006");if(c){for(f=0,a=c.length;f<a;++f){b=b.replace("\uE000",c[f]);}}return b;},_attrFilters:{"class":"className","for":"htmlFor"},getters:{href:function(b,a){return Y_DOM.getAttribute(b,a);}}};Y_mix(Selector,SelectorCSS2,true);Selector.getters.src=Selector.getters.rel=Selector.getters.href;if(Selector.useNative&&Y_DOC.querySelector){Selector.shorthand["\\.([^\\s\\\\(\\[:]*)"]="[class~=$1]";}Selector._reNth=/^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;Selector._getNth=function(d,o,q,h){Selector._reNth.test(o);var m=parseInt(RegExp.$1,10),c=RegExp.$2,j=RegExp.$3,k=parseInt(RegExp.$4,10)||0,p=[],l=Selector._children(d.parentNode,q),f;if(j){m=2;f="+";c="n";k=(j==="odd")?1:0;}else{if(isNaN(m)){m=(c)?1:0;}}if(m===0){if(h){k=l.length-k+1;}if(l[k-1]===d){return true;}else{return false;}}else{if(m<0){h=!!h;m=Math.abs(m);}}if(!h){for(var e=k-1,g=l.length;e<g;e+=m){if(e>=0&&l[e]===d){return true;}}}else{for(var e=l.length-k,g=l.length;e>=0;e-=m){if(e<g&&l[e]===d){return true;}}}return false;};Y_mix(Selector.pseudos,{"root":function(a){return a===a.ownerDocument.documentElement;},"nth-child":function(a,b){return Selector._getNth(a,b);},"nth-last-child":function(a,b){return Selector._getNth(a,b,null,true);},"nth-of-type":function(a,b){return Selector._getNth(a,b,a.tagName);},"nth-last-of-type":function(a,b){return Selector._getNth(a,b,a.tagName,true);},"last-child":function(b){var a=Selector._children(b.parentNode);return a[a.length-1]===b;},"first-of-type":function(a){return Selector._children(a.parentNode,a.tagName)[0]===a;},"last-of-type":function(b){var a=Selector._children(b.parentNode,b.tagName);return a[a.length-1]===b;},"only-child":function(b){var a=Selector._children(b.parentNode);return a.length===1&&a[0]===b;},"only-of-type":function(b){var a=Selector._children(b.parentNode,b.tagName);return a.length===1&&a[0]===b;},"empty":function(a){return a.childNodes.length===0;},"not":function(a,b){return !Selector.test(a,b);},"contains":function(a,b){var c=a.innerText||a.textContent||"";return c.indexOf(b)>-1;},"checked":function(a){return(a.checked===true||a.selected===true);},enabled:function(a){return(a.disabled!==undefined&&!a.disabled);},disabled:function(a){return(a.disabled);}});Y_mix(Selector.operators,{"^=":"^{val}","!=":function(b,a,c){return b[a]!==c;},"$=":"{val}$","*=":"{val}"});Selector.combinators["~"]={axis:"previousSibling"};YAHOO.register("selector",YAHOO.util.Selector,{version:"2.9.0",build:"2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+(function(){var A=YAHOO.util.Event,C=YAHOO.lang,B=[],D=function(H,E,F){var G;if(!H||H===F){G=false;}else{G=YAHOO.util.Selector.test(H,E)?H:D(H.parentNode,E,F);}return G;};C.augmentObject(A,{_createDelegate:function(F,E,G,H){return function(I){var J=this,N=A.getTarget(I),L=E,P=(J.nodeType===9),Q,K,O,M;if(C.isFunction(E)){Q=E(N);}else{if(C.isString(E)){if(!P){O=J.id;if(!O){O=A.generateId(J);}M=("#"+O+" ");L=(M+E).replace(/,/gi,(","+M));}if(YAHOO.util.Selector.test(N,L)){Q=N;}else{if(YAHOO.util.Selector.test(N,((L.replace(/,/gi," *,"))+" *"))){Q=D(N,L,J);}}}}if(Q){K=Q;if(H){if(H===true){K=G;}else{K=H;}}return F.call(K,I,Q,J,G);}};},delegate:function(F,J,L,G,H,I){var E=J,K,M;if(C.isString(G)&&!YAHOO.util.Selector){return false;}if(J=="mouseenter"||J=="mouseleave"){if(!A._createMouseDelegate){return false;}E=A._getType(J);K=A._createMouseDelegate(L,H,I);M=A._createDelegate(function(P,O,N){return K.call(O,P,N);},G,H,I);}else{M=A._createDelegate(L,G,H,I);}B.push([F,E,L,M]);return A.on(F,E,M);},removeDelegate:function(F,J,I){var K=J,H=false,G,E;if(J=="mouseenter"||J=="mouseleave"){K=A._getType(J);}G=A._getCacheIndex(B,F,K,I);if(G>=0){E=B[G];}if(F&&E){H=A.removeListener(E[0],E[1],E[3]);if(H){delete B[G][2];delete B[G][3];B.splice(G,1);}}return H;}});}());YAHOO.register("event-delegate",YAHOO.util.Event,{version:"2.9.0",build:"2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+(function(){var l=YAHOO.lang,isFunction=l.isFunction,isObject=l.isObject,isArray=l.isArray,_toStr=Object.prototype.toString,Native=(YAHOO.env.ua.caja?window:this).JSON,_UNICODE_EXCEPTIONS=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_ESCAPES=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,_VALUES=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,_BRACKETS=/(?:^|:|,)(?:\s*\[)+/g,_UNSAFE=/[^\],:{}\s]/,_SPECIAL_CHARS=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_CHARS={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},UNDEFINED="undefined",OBJECT="object",NULL="null",STRING="string",NUMBER="number",BOOLEAN="boolean",DATE="date",_allowable={"undefined":UNDEFINED,"string":STRING,"[object String]":STRING,"number":NUMBER,"[object Number]":NUMBER,"boolean":BOOLEAN,"[object Boolean]":BOOLEAN,"[object Date]":DATE,"[object RegExp]":OBJECT},EMPTY="",OPEN_O="{",CLOSE_O="}",OPEN_A="[",CLOSE_A="]",COMMA=",",COMMA_CR=",\n",CR="\n",COLON=":",COLON_SP=": ",QUOTE='"';Native=_toStr.call(Native)==="[object JSON]"&&Native;function _char(c){if(!_CHARS[c]){_CHARS[c]="\\u"+("0000"+(+(c.charCodeAt(0))).toString(16)).slice(-4);}return _CHARS[c];}function _revive(data,reviver){var walk=function(o,key){var k,v,value=o[key];if(value&&typeof value==="object"){for(k in value){if(l.hasOwnProperty(value,k)){v=walk(value,k);if(v===undefined){delete value[k];}else{value[k]=v;}}}}return reviver.call(o,key,value);};return typeof reviver==="function"?walk({"":data},""):data;}function _prepare(s){return s.replace(_UNICODE_EXCEPTIONS,_char);}function _isSafe(str){return l.isString(str)&&!_UNSAFE.test(str.replace(_ESCAPES,"@").replace(_VALUES,"]").replace(_BRACKETS,""));}function _parse(s,reviver){s=_prepare(s);if(_isSafe(s)){return _revive(eval("("+s+")"),reviver);}throw new SyntaxError("JSON.parse");}function _type(o){var t=typeof o;return _allowable[t]||_allowable[_toStr.call(o)]||(t===OBJECT?(o?OBJECT:NULL):UNDEFINED);}function _string(s){return QUOTE+s.replace(_SPECIAL_CHARS,_char)+QUOTE;}function _indent(s,space){return s.replace(/^/gm,space);}function _stringify(o,w,space){if(o===undefined){return undefined;}var replacer=isFunction(w)?w:null,format=_toStr.call(space).match(/String|Number/)||[],_date=YAHOO.lang.JSON.dateToString,stack=[],tmp,i,len;if(replacer||!isArray(w)){w=undefined;}if(w){tmp={};for(i=0,len=w.length;i<len;++i){tmp[w[i]]=true;}w=tmp;}space=format[0]==="Number"?new Array(Math.min(Math.max(0,space),10)+1).join(" "):(space||EMPTY).slice(0,10);function _serialize(h,key){var value=h[key],t=_type(value),a=[],colon=space?COLON_SP:COLON,arr,i,keys,k,v;if(isObject(value)&&isFunction(value.toJSON)){value=value.toJSON(key);}else{if(t===DATE){value=_date(value);}}if(isFunction(replacer)){value=replacer.call(h,key,value);}if(value!==h[key]){t=_type(value);}switch(t){case DATE:case OBJECT:break;case STRING:return _string(value);case NUMBER:return isFinite(value)?value+EMPTY:NULL;case BOOLEAN:return value+EMPTY;case NULL:return NULL;default:return undefined;}for(i=stack.length-1;i>=0;--i){if(stack[i]===value){throw new Error("JSON.stringify. Cyclical reference");}}arr=isArray(value);stack.push(value);if(arr){for(i=value.length-1;i>=0;--i){a[i]=_serialize(value,i)||NULL;}}else{keys=w||value;i=0;for(k in keys){if(l.hasOwnProperty(keys,k)){v=_serialize(value,k);if(v){a[i++]=_string(k)+colon+v;}}}}stack.pop();if(space&&a.length){return arr?OPEN_A+CR+_indent(a.join(COMMA_CR),space)+CR+CLOSE_A:OPEN_O+CR+_indent(a.join(COMMA_CR),space)+CR+CLOSE_O;}else{return arr?OPEN_A+a.join(COMMA)+CLOSE_A:OPEN_O+a.join(COMMA)+CLOSE_O;}}return _serialize({"":o},"");}YAHOO.lang.JSON={useNativeParse:!!Native,useNativeStringify:!!Native,isSafe:function(s){return _isSafe(_prepare(s));},parse:function(s,reviver){if(typeof s!=="string"){s+="";}return Native&&YAHOO.lang.JSON.useNativeParse?Native.parse(s,reviver):_parse(s,reviver);},stringify:function(o,w,space){return Native&&YAHOO.lang.JSON.useNativeStringify?Native.stringify(o,w,space):_stringify(o,w,space);},dateToString:function(d){function _zeroPad(v){return v<10?"0"+v:v;}return d.getUTCFullYear()+"-"+_zeroPad(d.getUTCMonth()+1)+"-"+_zeroPad(d.getUTCDate())+"T"+_zeroPad(d.getUTCHours())+COLON+_zeroPad(d.getUTCMinutes())+COLON+_zeroPad(d.getUTCSeconds())+"Z";},stringToDate:function(str){var m=str.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?Z$/);if(m){var d=new Date();d.setUTCFullYear(m[1],m[2]-1,m[3]);d.setUTCHours(m[4],m[5],m[6],(m[7]||0));return d;}return str;}};YAHOO.lang.JSON.isValid=YAHOO.lang.JSON.isSafe;})();YAHOO.register("json",YAHOO.lang.JSON,{version:"2.9.0",build:"2800"});/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+(function(){var b=YAHOO.util.Event,g=YAHOO.lang,e=b.addListener,f=b.removeListener,c=b.getListeners,d=[],h={mouseenter:"mouseover",mouseleave:"mouseout"},a=function(n,m,l){var j=b._getCacheIndex(d,n,m,l),i,k;if(j>=0){i=d[j];}if(n&&i){k=f.call(b,i[0],m,i[3]);if(k){delete d[j][2];delete d[j][3];d.splice(j,1);}}return k;};g.augmentObject(b._specialTypes,h);g.augmentObject(b,{_createMouseDelegate:function(i,j,k){return function(q,m){var p=this,l=b.getRelatedTarget(q),o,n;if(p!=l&&!YAHOO.util.Dom.isAncestor(p,l)){o=p;if(k){if(k===true){o=j;}else{o=k;}}n=[q,j];if(m){n.splice(1,0,p,m);}return i.apply(o,n);}};},addListener:function(m,l,k,n,o){var i,j;if(h[l]){i=b._createMouseDelegate(k,n,o);i.mouseDelegate=true;d.push([m,l,k,i]);j=e.call(b,m,l,i);}else{j=e.apply(b,arguments);}return j;},removeListener:function(l,k,j){var i;if(h[k]){i=a.apply(b,arguments);}else{i=f.apply(b,arguments);}return i;},getListeners:function(p,o){var n=[],r,m=(o==="mouseover"||o==="mouseout"),q,k,j;if(o&&(m||h[o])){r=c.call(b,p,this._getType(o));if(r){for(k=r.length-1;k>-1;k--){j=r[k];q=j.fn.mouseDelegate;if((h[o]&&q)||(m&&!q)){n.push(j);}}}}else{n=c.apply(b,arguments);}return(n&&n.length)?n:null;}},true);b.on=b.addListener;}());YAHOO.register("event-mouseenter",YAHOO.util.Event,{version:"2.9.0",build:"2800"});
\ No newline at end of file
--- a/rhodecode/public/js/yui2a.js	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.2r1
-*/
-if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=(""+A[C]).split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules,B,H,G,F,C;if(!I[A]){I[A]={versions:[],builds:[]};}B=I[A];H=D.version;G=D.build;F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var D=function(H){var I=0;return parseFloat(H.replace(/\./g,function(){return(I++==1)?"":".";}));},G=navigator,F={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0,caja:G.cajaVersion,secure:false,os:null},C=navigator&&navigator.userAgent,E=window&&window.location,B=E&&E.href,A;F.secure=B&&(B.toLowerCase().indexOf("https")===0);if(C){if((/windows|win32/i).test(C)){F.os="windows";}else{if((/macintosh/i).test(C)){F.os="macintosh";}}if((/KHTML/).test(C)){F.webkit=1;}A=C.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){F.webkit=D(A[1]);if(/ Mobile\//.test(C)){F.mobile="Apple";}else{A=C.match(/NokiaN[^\/]*/);if(A){F.mobile=A[0];}}A=C.match(/AdobeAIR\/([^\s]*)/);if(A){F.air=A[0];}}if(!F.webkit){A=C.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){F.opera=D(A[1]);A=C.match(/Opera Mini[^;]*/);if(A){F.mobile=A[0];}}else{A=C.match(/MSIE\s([^;]*)/);if(A&&A[1]){F.ie=D(A[1]);}else{A=C.match(/Gecko\/([^\s]*)/);if(A){F.gecko=1;A=C.match(/rv:([^\s\)]*)/);if(A&&A[1]){F.gecko=D(A[1]);}}}}}}return F;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C++){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{};(function(){var B=YAHOO.lang,A=Object.prototype,H="[object Array]",C="[object Function]",G="[object Object]",E=[],F=["toString","valueOf"],D={isArray:function(I){return A.toString.apply(I)===H;},isBoolean:function(I){return typeof I==="boolean";},isFunction:function(I){return(typeof I==="function")||A.toString.apply(I)===C;},isNull:function(I){return I===null;},isNumber:function(I){return typeof I==="number"&&isFinite(I);},isObject:function(I){return(I&&(typeof I==="object"||B.isFunction(I)))||false;},isString:function(I){return typeof I==="string";},isUndefined:function(I){return typeof I==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(K,J){var I,M,L;for(I=0;I<F.length;I=I+1){M=F[I];L=J[M];if(B.isFunction(L)&&L!=A[M]){K[M]=L;}}}:function(){},extend:function(L,M,K){if(!M||!L){throw new Error("extend failed, please check that "+"all dependencies are included.");}var J=function(){},I;J.prototype=M.prototype;L.prototype=new J();L.prototype.constructor=L;L.superclass=M.prototype;if(M.prototype.constructor==A.constructor){M.prototype.constructor=M;}if(K){for(I in K){if(B.hasOwnProperty(K,I)){L.prototype[I]=K[I];}}B._IEEnumFix(L.prototype,K);}},augmentObject:function(M,L){if(!L||!M){throw new Error("Absorb failed, verify dependencies.");}var I=arguments,K,N,J=I[2];if(J&&J!==true){for(K=2;K<I.length;K=K+1){M[I[K]]=L[I[K]];}}else{for(N in L){if(J||!(N in M)){M[N]=L[N];}}B._IEEnumFix(M,L);}},augmentProto:function(L,K){if(!K||!L){throw new Error("Augment failed, verify dependencies.");}var I=[L.prototype,K.prototype],J;for(J=2;J<arguments.length;J=J+1){I.push(arguments[J]);}B.augmentObject.apply(this,I);},dump:function(I,N){var K,M,P=[],Q="{...}",J="f(){...}",O=", ",L=" => ";if(!B.isObject(I)){return I+"";}else{if(I instanceof Date||("nodeType" in I&&"tagName" in I)){return I;}else{if(B.isFunction(I)){return J;}}}N=(B.isNumber(N))?N:3;if(B.isArray(I)){P.push("[");for(K=0,M=I.length;K<M;K=K+1){if(B.isObject(I[K])){P.push((N>0)?B.dump(I[K],N-1):Q);}else{P.push(I[K]);}P.push(O);}if(P.length>1){P.pop();}P.push("]");}else{P.push("{");for(K in I){if(B.hasOwnProperty(I,K)){P.push(K+L);if(B.isObject(I[K])){P.push((N>0)?B.dump(I[K],N-1):Q);}else{P.push(I[K]);}P.push(O);}}if(P.length>1){P.pop();}P.push("}");}return P.join("");},substitute:function(Y,J,R){var N,M,L,U,V,X,T=[],K,O="dump",S=" ",I="{",W="}",Q,P;for(;;){N=Y.lastIndexOf(I);if(N<0){break;}M=Y.indexOf(W,N);if(N+1>=M){break;}K=Y.substring(N+1,M);U=K;X=null;L=U.indexOf(S);if(L>-1){X=U.substring(L+1);U=U.substring(0,L);}V=J[U];if(R){V=R(U,V,X);}if(B.isObject(V)){if(B.isArray(V)){V=B.dump(V,parseInt(X,10));}else{X=X||"";Q=X.indexOf(O);if(Q>-1){X=X.substring(4);}P=V.toString();if(P===G||Q>-1){V=B.dump(V,parseInt(X,10));}else{V=P;}}}else{if(!B.isString(V)&&!B.isNumber(V)){V="~-"+T.length+"-~";T[T.length]=K;}}Y=Y.substring(0,N)+V+Y.substring(M+1);}for(N=T.length-1;N>=0;N=N-1){Y=Y.replace(new RegExp("~-"+N+"-~"),"{"+T[N]+"}","g");}return Y;},trim:function(I){try{return I.replace(/^\s+|\s+$/g,"");}catch(J){return I;}},merge:function(){var L={},J=arguments,I=J.length,K;for(K=0;K<I;K=K+1){B.augmentObject(L,J[K],true);}return L;},later:function(P,J,Q,L,M){P=P||0;J=J||{};var K=Q,O=L,N,I;if(B.isString(Q)){K=J[Q];}if(!K){throw new TypeError("method undefined");}if(O&&!B.isArray(O)){O=[L];}N=function(){K.apply(J,O||E);};I=(M)?setInterval(N,P):setTimeout(N,P);return{interval:M,cancel:function(){if(this.interval){clearInterval(I);}else{clearTimeout(I);}}};},isValue:function(I){return(B.isObject(I)||B.isString(I)||B.isNumber(I)||B.isBoolean(I));}};B.hasOwnProperty=(A.hasOwnProperty)?function(I,J){return I&&I.hasOwnProperty(J);}:function(I,J){return !B.isUndefined(I[J])&&I.constructor.prototype[J]!==I[J];};D.augmentObject(B,D,true);YAHOO.util.Lang=B;B.augment=B.augmentProto;YAHOO.augment=B.augmentProto;YAHOO.extend=B.extend;})();YAHOO.register("yahoo",YAHOO,{version:"2.8.2r1",build:"7"});
-YAHOO.util.Get=function(){var M={},L=0,R=0,E=false,N=YAHOO.env.ua,S=YAHOO.lang;var J=function(W,T,X){var U=X||window,Y=U.document,Z=Y.createElement(W);for(var V in T){if(T[V]&&YAHOO.lang.hasOwnProperty(T,V)){Z.setAttribute(V,T[V]);}}return Z;};var I=function(U,V,T){var W={id:"yui__dyn_"+(R++),type:"text/css",rel:"stylesheet",href:U};if(T){S.augmentObject(W,T);}return J("link",W,V);};var P=function(U,V,T){var W={id:"yui__dyn_"+(R++),type:"text/javascript",src:U};if(T){S.augmentObject(W,T);}return J("script",W,V);};var A=function(T,U){return{tId:T.tId,win:T.win,data:T.data,nodes:T.nodes,msg:U,purge:function(){D(this.tId);}};};var B=function(T,W){var U=M[W],V=(S.isString(T))?U.win.document.getElementById(T):T;if(!V){Q(W,"target node not found: "+T);}return V;};var Q=function(W,V){var T=M[W];if(T.onFailure){var U=T.scope||T.win;T.onFailure.call(U,A(T,V));}};var C=function(W){var T=M[W];T.finished=true;if(T.aborted){var V="transaction "+W+" was aborted";Q(W,V);return;}if(T.onSuccess){var U=T.scope||T.win;T.onSuccess.call(U,A(T));}};var O=function(V){var T=M[V];if(T.onTimeout){var U=T.scope||T;T.onTimeout.call(U,A(T));}};var G=function(V,Z){var U=M[V];if(U.timer){U.timer.cancel();}if(U.aborted){var X="transaction "+V+" was aborted";Q(V,X);return;}if(Z){U.url.shift();if(U.varName){U.varName.shift();}}else{U.url=(S.isString(U.url))?[U.url]:U.url;if(U.varName){U.varName=(S.isString(U.varName))?[U.varName]:U.varName;}}var c=U.win,b=c.document,a=b.getElementsByTagName("head")[0],W;if(U.url.length===0){if(U.type==="script"&&N.webkit&&N.webkit<420&&!U.finalpass&&!U.varName){var Y=P(null,U.win,U.attributes);Y.innerHTML='YAHOO.util.Get._finalize("'+V+'");';U.nodes.push(Y);a.appendChild(Y);}else{C(V);}return;}var T=U.url[0];if(!T){U.url.shift();return G(V);}if(U.timeout){U.timer=S.later(U.timeout,U,O,V);}if(U.type==="script"){W=P(T,c,U.attributes);}else{W=I(T,c,U.attributes);}F(U.type,W,V,T,c,U.url.length);U.nodes.push(W);if(U.insertBefore){var e=B(U.insertBefore,V);if(e){e.parentNode.insertBefore(W,e);}}else{a.appendChild(W);}if((N.webkit||N.gecko)&&U.type==="css"){G(V,T);}};var K=function(){if(E){return;}E=true;for(var T in M){var U=M[T];if(U.autopurge&&U.finished){D(U.tId);delete M[T];}}E=false;};var D=function(Z){if(M[Z]){var T=M[Z],U=T.nodes,X=U.length,c=T.win.document,a=c.getElementsByTagName("head")[0],V,Y,W,b;if(T.insertBefore){V=B(T.insertBefore,Z);if(V){a=V.parentNode;}}for(Y=0;Y<X;Y=Y+1){W=U[Y];if(W.clearAttributes){W.clearAttributes();}else{for(b in W){delete W[b];}}a.removeChild(W);}T.nodes=[];}};var H=function(U,T,V){var X="q"+(L++);V=V||{};if(L%YAHOO.util.Get.PURGE_THRESH===0){K();}M[X]=S.merge(V,{tId:X,type:U,url:T,finished:false,aborted:false,nodes:[]});var W=M[X];W.win=W.win||window;W.scope=W.scope||W.win;W.autopurge=("autopurge" in W)?W.autopurge:(U==="script")?true:false;if(V.charset){W.attributes=W.attributes||{};W.attributes.charset=V.charset;}S.later(0,W,G,X);return{tId:X};};var F=function(c,X,W,U,Y,Z,b){var a=b||G;if(N.ie){X.onreadystatechange=function(){var d=this.readyState;if("loaded"===d||"complete"===d){X.onreadystatechange=null;a(W,U);}};}else{if(N.webkit){if(c==="script"){if(N.webkit>=420){X.addEventListener("load",function(){a(W,U);});}else{var T=M[W];if(T.varName){var V=YAHOO.util.Get.POLL_FREQ;T.maxattempts=YAHOO.util.Get.TIMEOUT/V;T.attempts=0;T._cache=T.varName[0].split(".");T.timer=S.later(V,T,function(j){var f=this._cache,e=f.length,d=this.win,g;for(g=0;g<e;g=g+1){d=d[f[g]];if(!d){this.attempts++;if(this.attempts++>this.maxattempts){var h="Over retry limit, giving up";T.timer.cancel();Q(W,h);}else{}return;}}T.timer.cancel();a(W,U);},null,true);}else{S.later(YAHOO.util.Get.POLL_FREQ,null,a,[W,U]);}}}}else{X.onload=function(){a(W,U);};}}};return{POLL_FREQ:10,PURGE_THRESH:20,TIMEOUT:2000,_finalize:function(T){S.later(0,null,C,T);},abort:function(U){var V=(S.isString(U))?U:U.tId;var T=M[V];if(T){T.aborted=true;}},script:function(T,U){return H("script",T,U);},css:function(T,U){return H("css",T,U);}};}();YAHOO.register("get",YAHOO.util.Get,{version:"2.8.2r1",build:"7"});(function(){var Y=YAHOO,util=Y.util,lang=Y.lang,env=Y.env,PROV="_provides",SUPER="_supersedes",REQ="expanded",AFTER="_after";var YUI={dupsAllowed:{"yahoo":true,"get":true},info:{"root":"2.8.2r1/build/","base":"http://yui.yahooapis.com/2.8.2r1/build/","comboBase":"http://yui.yahooapis.com/combo?","skin":{"defaultSkin":"sam","base":"assets/skins/","path":"skin.css","after":["reset","fonts","grids","base"],"rollup":3},dupsAllowed:["yahoo","get"],"moduleInfo":{"animation":{"type":"js","path":"animation/animation-min.js","requires":["dom","event"]},"autocomplete":{"type":"js","path":"autocomplete/autocomplete-min.js","requires":["dom","event","datasource"],"optional":["connection","animation"],"skinnable":true},"base":{"type":"css","path":"base/base-min.css","after":["reset","fonts","grids"]},"button":{"type":"js","path":"button/button-min.js","requires":["element"],"optional":["menu"],"skinnable":true},"calendar":{"type":"js","path":"calendar/calendar-min.js","requires":["event","dom"],supersedes:["datemeth"],"skinnable":true},"carousel":{"type":"js","path":"carousel/carousel-min.js","requires":["element"],"optional":["animation"],"skinnable":true},"charts":{"type":"js","path":"charts/charts-min.js","requires":["element","json","datasource","swf"]},"colorpicker":{"type":"js","path":"colorpicker/colorpicker-min.js","requires":["slider","element"],"optional":["animation"],"skinnable":true},"connection":{"type":"js","path":"connection/connection-min.js","requires":["event"],"supersedes":["connectioncore"]},"connectioncore":{"type":"js","path":"connection/connection_core-min.js","requires":["event"],"pkg":"connection"},"container":{"type":"js","path":"container/container-min.js","requires":["dom","event"],"optional":["dragdrop","animation","connection"],"supersedes":["containercore"],"skinnable":true},"containercore":{"type":"js","path":"container/container_core-min.js","requires":["dom","event"],"pkg":"container"},"cookie":{"type":"js","path":"cookie/cookie-min.js","requires":["yahoo"]},"datasource":{"type":"js","path":"datasource/datasource-min.js","requires":["event"],"optional":["connection"]},"datatable":{"type":"js","path":"datatable/datatable-min.js","requires":["element","datasource"],"optional":["calendar","dragdrop","paginator"],"skinnable":true},datemath:{"type":"js","path":"datemath/datemath-min.js","requires":["yahoo"]},"dom":{"type":"js","path":"dom/dom-min.js","requires":["yahoo"]},"dragdrop":{"type":"js","path":"dragdrop/dragdrop-min.js","requires":["dom","event"]},"editor":{"type":"js","path":"editor/editor-min.js","requires":["menu","element","button"],"optional":["animation","dragdrop"],"supersedes":["simpleeditor"],"skinnable":true},"element":{"type":"js","path":"element/element-min.js","requires":["dom","event"],"optional":["event-mouseenter","event-delegate"]},"element-delegate":{"type":"js","path":"element-delegate/element-delegate-min.js","requires":["element"]},"event":{"type":"js","path":"event/event-min.js","requires":["yahoo"]},"event-simulate":{"type":"js","path":"event-simulate/event-simulate-min.js","requires":["event"]},"event-delegate":{"type":"js","path":"event-delegate/event-delegate-min.js","requires":["event"],"optional":["selector"]},"event-mouseenter":{"type":"js","path":"event-mouseenter/event-mouseenter-min.js","requires":["dom","event"]},"fonts":{"type":"css","path":"fonts/fonts-min.css"},"get":{"type":"js","path":"get/get-min.js","requires":["yahoo"]},"grids":{"type":"css","path":"grids/grids-min.css","requires":["fonts"],"optional":["reset"]},"history":{"type":"js","path":"history/history-min.js","requires":["event"]},"imagecropper":{"type":"js","path":"imagecropper/imagecropper-min.js","requires":["dragdrop","element","resize"],"skinnable":true},"imageloader":{"type":"js","path":"imageloader/imageloader-min.js","requires":["event","dom"]},"json":{"type":"js","path":"json/json-min.js","requires":["yahoo"]},"layout":{"type":"js","path":"layout/layout-min.js","requires":["element"],"optional":["animation","dragdrop","resize","selector"],"skinnable":true},"logger":{"type":"js","path":"logger/logger-min.js","requires":["event","dom"],"optional":["dragdrop"],"skinnable":true},"menu":{"type":"js","path":"menu/menu-min.js","requires":["containercore"],"skinnable":true},"paginator":{"type":"js","path":"paginator/paginator-min.js","requires":["element"],"skinnable":true},"profiler":{"type":"js","path":"profiler/profiler-min.js","requires":["yahoo"]},"profilerviewer":{"type":"js","path":"profilerviewer/profilerviewer-min.js","requires":["profiler","yuiloader","element"],"skinnable":true},"progressbar":{"type":"js","path":"progressbar/progressbar-min.js","requires":["element"],"optional":["animation"],"skinnable":true},"reset":{"type":"css","path":"reset/reset-min.css"},"reset-fonts-grids":{"type":"css","path":"reset-fonts-grids/reset-fonts-grids.css","supersedes":["reset","fonts","grids","reset-fonts"],"rollup":4},"reset-fonts":{"type":"css","path":"reset-fonts/reset-fonts.css","supersedes":["reset","fonts"],"rollup":2},"resize":{"type":"js","path":"resize/resize-min.js","requires":["dragdrop","element"],"optional":["animation"],"skinnable":true},"selector":{"type":"js","path":"selector/selector-min.js","requires":["yahoo","dom"]},"simpleeditor":{"type":"js","path":"editor/simpleeditor-min.js","requires":["element"],"optional":["containercore","menu","button","animation","dragdrop"],"skinnable":true,"pkg":"editor"},"slider":{"type":"js","path":"slider/slider-min.js","requires":["dragdrop"],"optional":["animation"],"skinnable":true},"storage":{"type":"js","path":"storage/storage-min.js","requires":["yahoo","event","cookie"],"optional":["swfstore"]},"stylesheet":{"type":"js","path":"stylesheet/stylesheet-min.js","requires":["yahoo"]},"swf":{"type":"js","path":"swf/swf-min.js","requires":["element"],"supersedes":["swfdetect"]},"swfdetect":{"type":"js","path":"swfdetect/swfdetect-min.js","requires":["yahoo"]},"swfstore":{"type":"js","path":"swfstore/swfstore-min.js","requires":["element","cookie","swf"]},"tabview":{"type":"js","path":"tabview/tabview-min.js","requires":["element"],"optional":["connection"],"skinnable":true},"treeview":{"type":"js","path":"treeview/treeview-min.js","requires":["event","dom"],"optional":["json","animation","calendar"],"skinnable":true},"uploader":{"type":"js","path":"uploader/uploader-min.js","requires":["element"]},"utilities":{"type":"js","path":"utilities/utilities.js","supersedes":["yahoo","event","dragdrop","animation","dom","connection","element","yahoo-dom-event","get","yuiloader","yuiloader-dom-event"],"rollup":8},"yahoo":{"type":"js","path":"yahoo/yahoo-min.js"},"yahoo-dom-event":{"type":"js","path":"yahoo-dom-event/yahoo-dom-event.js","supersedes":["yahoo","event","dom"],"rollup":3},"yuiloader":{"type":"js","path":"yuiloader/yuiloader-min.js","supersedes":["yahoo","get"]},"yuiloader-dom-event":{"type":"js","path":"yuiloader-dom-event/yuiloader-dom-event.js","supersedes":["yahoo","dom","event","get","yuiloader","yahoo-dom-event"],"rollup":5},"yuitest":{"type":"js","path":"yuitest/yuitest-min.js","requires":["logger"],"optional":["event-simulate"],"skinnable":true}}},ObjectUtil:{appendArray:function(o,a){if(a){for(var i=0;
-i<a.length;i=i+1){o[a[i]]=true;}}},keys:function(o,ordered){var a=[],i;for(i in o){if(lang.hasOwnProperty(o,i)){a.push(i);}}return a;}},ArrayUtil:{appendArray:function(a1,a2){Array.prototype.push.apply(a1,a2);},indexOf:function(a,val){for(var i=0;i<a.length;i=i+1){if(a[i]===val){return i;}}return -1;},toObject:function(a){var o={};for(var i=0;i<a.length;i=i+1){o[a[i]]=true;}return o;},uniq:function(a){return YUI.ObjectUtil.keys(YUI.ArrayUtil.toObject(a));}}};YAHOO.util.YUILoader=function(o){this._internalCallback=null;this._useYahooListener=false;this.onSuccess=null;this.onFailure=Y.log;this.onProgress=null;this.onTimeout=null;this.scope=this;this.data=null;this.insertBefore=null;this.charset=null;this.varName=null;this.base=YUI.info.base;this.comboBase=YUI.info.comboBase;this.combine=false;this.root=YUI.info.root;this.timeout=0;this.ignore=null;this.force=null;this.allowRollup=true;this.filter=null;this.required={};this.moduleInfo=lang.merge(YUI.info.moduleInfo);this.rollups=null;this.loadOptional=false;this.sorted=[];this.loaded={};this.dirty=true;this.inserted={};var self=this;env.listeners.push(function(m){if(self._useYahooListener){self.loadNext(m.name);}});this.skin=lang.merge(YUI.info.skin);this._config(o);};Y.util.YUILoader.prototype={FILTERS:{RAW:{"searchExp":"-min\\.js","replaceStr":".js"},DEBUG:{"searchExp":"-min\\.js","replaceStr":"-debug.js"}},SKIN_PREFIX:"skin-",_config:function(o){if(o){for(var i in o){if(lang.hasOwnProperty(o,i)){if(i=="require"){this.require(o[i]);}else{this[i]=o[i];}}}}var f=this.filter;if(lang.isString(f)){f=f.toUpperCase();if(f==="DEBUG"){this.require("logger");}if(!Y.widget.LogWriter){Y.widget.LogWriter=function(){return Y;};}this.filter=this.FILTERS[f];}},addModule:function(o){if(!o||!o.name||!o.type||(!o.path&&!o.fullpath)){return false;}o.ext=("ext" in o)?o.ext:true;o.requires=o.requires||[];this.moduleInfo[o.name]=o;this.dirty=true;return true;},require:function(what){var a=(typeof what==="string")?arguments:what;this.dirty=true;YUI.ObjectUtil.appendArray(this.required,a);},_addSkin:function(skin,mod){var name=this.formatSkin(skin),info=this.moduleInfo,sinf=this.skin,ext=info[mod]&&info[mod].ext;if(!info[name]){this.addModule({"name":name,"type":"css","path":sinf.base+skin+"/"+sinf.path,"after":sinf.after,"rollup":sinf.rollup,"ext":ext});}if(mod){name=this.formatSkin(skin,mod);if(!info[name]){var mdef=info[mod],pkg=mdef.pkg||mod;this.addModule({"name":name,"type":"css","after":sinf.after,"path":pkg+"/"+sinf.base+skin+"/"+mod+".css","ext":ext});}}return name;},getRequires:function(mod){if(!mod){return[];}if(!this.dirty&&mod.expanded){return mod.expanded;}mod.requires=mod.requires||[];var i,d=[],r=mod.requires,o=mod.optional,info=this.moduleInfo,m;for(i=0;i<r.length;i=i+1){d.push(r[i]);m=info[r[i]];YUI.ArrayUtil.appendArray(d,this.getRequires(m));}if(o&&this.loadOptional){for(i=0;i<o.length;i=i+1){d.push(o[i]);YUI.ArrayUtil.appendArray(d,this.getRequires(info[o[i]]));}}mod.expanded=YUI.ArrayUtil.uniq(d);return mod.expanded;},getProvides:function(name,notMe){var addMe=!(notMe),ckey=(addMe)?PROV:SUPER,m=this.moduleInfo[name],o={};if(!m){return o;}if(m[ckey]){return m[ckey];}var s=m.supersedes,done={},me=this;var add=function(mm){if(!done[mm]){done[mm]=true;lang.augmentObject(o,me.getProvides(mm));}};if(s){for(var i=0;i<s.length;i=i+1){add(s[i]);}}m[SUPER]=o;m[PROV]=lang.merge(o);m[PROV][name]=true;return m[ckey];},calculate:function(o){if(o||this.dirty){this._config(o);this._setup();this._explode();if(this.allowRollup){this._rollup();}this._reduce();this._sort();this.dirty=false;}},_setup:function(){var info=this.moduleInfo,name,i,j;for(name in info){if(lang.hasOwnProperty(info,name)){var m=info[name];if(m&&m.skinnable){var o=this.skin.overrides,smod;if(o&&o[name]){for(i=0;i<o[name].length;i=i+1){smod=this._addSkin(o[name][i],name);}}else{smod=this._addSkin(this.skin.defaultSkin,name);}m.requires.push(smod);}}}var l=lang.merge(this.inserted);if(!this._sandbox){l=lang.merge(l,env.modules);}if(this.ignore){YUI.ObjectUtil.appendArray(l,this.ignore);}if(this.force){for(i=0;i<this.force.length;i=i+1){if(this.force[i] in l){delete l[this.force[i]];}}}for(j in l){if(lang.hasOwnProperty(l,j)){lang.augmentObject(l,this.getProvides(j));}}this.loaded=l;},_explode:function(){var r=this.required,i,mod;for(i in r){if(lang.hasOwnProperty(r,i)){mod=this.moduleInfo[i];if(mod){var req=this.getRequires(mod);if(req){YUI.ObjectUtil.appendArray(r,req);}}}}},_skin:function(){},formatSkin:function(skin,mod){var s=this.SKIN_PREFIX+skin;if(mod){s=s+"-"+mod;}return s;},parseSkin:function(mod){if(mod.indexOf(this.SKIN_PREFIX)===0){var a=mod.split("-");return{skin:a[1],module:a[2]};}return null;},_rollup:function(){var i,j,m,s,rollups={},r=this.required,roll,info=this.moduleInfo;if(this.dirty||!this.rollups){for(i in info){if(lang.hasOwnProperty(info,i)){m=info[i];if(m&&m.rollup){rollups[i]=m;}}}this.rollups=rollups;}for(;;){var rolled=false;for(i in rollups){if(!r[i]&&!this.loaded[i]){m=info[i];s=m.supersedes;roll=false;if(!m.rollup){continue;}var skin=(m.ext)?false:this.parseSkin(i),c=0;if(skin){for(j in r){if(lang.hasOwnProperty(r,j)){if(i!==j&&this.parseSkin(j)){c++;roll=(c>=m.rollup);if(roll){break;}}}}}else{for(j=0;j<s.length;j=j+1){if(this.loaded[s[j]]&&(!YUI.dupsAllowed[s[j]])){roll=false;break;}else{if(r[s[j]]){c++;roll=(c>=m.rollup);if(roll){break;}}}}}if(roll){r[i]=true;rolled=true;this.getRequires(m);}}}if(!rolled){break;}}},_reduce:function(){var i,j,s,m,r=this.required;for(i in r){if(i in this.loaded){delete r[i];}else{var skinDef=this.parseSkin(i);if(skinDef){if(!skinDef.module){var skin_pre=this.SKIN_PREFIX+skinDef.skin;for(j in r){if(lang.hasOwnProperty(r,j)){m=this.moduleInfo[j];var ext=m&&m.ext;if(!ext&&j!==i&&j.indexOf(skin_pre)>-1){delete r[j];}}}}}else{m=this.moduleInfo[i];s=m&&m.supersedes;if(s){for(j=0;j<s.length;j=j+1){if(s[j] in r){delete r[s[j]];}}}}}}},_onFailure:function(msg){YAHOO.log("Failure","info","loader");var f=this.onFailure;if(f){f.call(this.scope,{msg:"failure: "+msg,data:this.data,success:false});
-}},_onTimeout:function(){YAHOO.log("Timeout","info","loader");var f=this.onTimeout;if(f){f.call(this.scope,{msg:"timeout",data:this.data,success:false});}},_sort:function(){var s=[],info=this.moduleInfo,loaded=this.loaded,checkOptional=!this.loadOptional,me=this;var requires=function(aa,bb){var mm=info[aa];if(loaded[bb]||!mm){return false;}var ii,rr=mm.expanded,after=mm.after,other=info[bb],optional=mm.optional;if(rr&&YUI.ArrayUtil.indexOf(rr,bb)>-1){return true;}if(after&&YUI.ArrayUtil.indexOf(after,bb)>-1){return true;}if(checkOptional&&optional&&YUI.ArrayUtil.indexOf(optional,bb)>-1){return true;}var ss=info[bb]&&info[bb].supersedes;if(ss){for(ii=0;ii<ss.length;ii=ii+1){if(requires(aa,ss[ii])){return true;}}}if(mm.ext&&mm.type=="css"&&!other.ext&&other.type=="css"){return true;}return false;};for(var i in this.required){if(lang.hasOwnProperty(this.required,i)){s.push(i);}}var p=0;for(;;){var l=s.length,a,b,j,k,moved=false;for(j=p;j<l;j=j+1){a=s[j];for(k=j+1;k<l;k=k+1){if(requires(a,s[k])){b=s.splice(k,1);s.splice(j,0,b[0]);moved=true;break;}}if(moved){break;}else{p=p+1;}}if(!moved){break;}}this.sorted=s;},toString:function(){var o={type:"YUILoader",base:this.base,filter:this.filter,required:this.required,loaded:this.loaded,inserted:this.inserted};lang.dump(o,1);},_combine:function(){this._combining=[];var self=this,s=this.sorted,len=s.length,js=this.comboBase,css=this.comboBase,target,startLen=js.length,i,m,type=this.loadType;YAHOO.log("type "+type);for(i=0;i<len;i=i+1){m=this.moduleInfo[s[i]];if(m&&!m.ext&&(!type||type===m.type)){target=this.root+m.path;target+="&";if(m.type=="js"){js+=target;}else{css+=target;}this._combining.push(s[i]);}}if(this._combining.length){YAHOO.log("Attempting to combine: "+this._combining,"info","loader");var callback=function(o){var c=this._combining,len=c.length,i,m;for(i=0;i<len;i=i+1){this.inserted[c[i]]=true;}this.loadNext(o.data);},loadScript=function(){if(js.length>startLen){YAHOO.util.Get.script(self._filter(js),{data:self._loading,onSuccess:callback,onFailure:self._onFailure,onTimeout:self._onTimeout,insertBefore:self.insertBefore,charset:self.charset,timeout:self.timeout,scope:self});}};if(css.length>startLen){YAHOO.util.Get.css(this._filter(css),{data:this._loading,onSuccess:loadScript,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,scope:self});}else{loadScript();}return;}else{this.loadNext(this._loading);}},insert:function(o,type){this.calculate(o);this._loading=true;this.loadType=type;if(this.combine){return this._combine();}if(!type){var self=this;this._internalCallback=function(){self._internalCallback=null;self.insert(null,"js");};this.insert(null,"css");return;}this.loadNext();},sandbox:function(o,type){this._config(o);if(!this.onSuccess){throw new Error("You must supply an onSuccess handler for your sandbox");}this._sandbox=true;var self=this;if(!type||type!=="js"){this._internalCallback=function(){self._internalCallback=null;self.sandbox(null,"js");};this.insert(null,"css");return;}if(!util.Connect){var ld=new YAHOO.util.YUILoader();ld.insert({base:this.base,filter:this.filter,require:"connection",insertBefore:this.insertBefore,charset:this.charset,onSuccess:function(){this.sandbox(null,"js");},scope:this},"js");return;}this._scriptText=[];this._loadCount=0;this._stopCount=this.sorted.length;this._xhr=[];this.calculate();var s=this.sorted,l=s.length,i,m,url;for(i=0;i<l;i=i+1){m=this.moduleInfo[s[i]];if(!m){this._onFailure("undefined module "+m);for(var j=0;j<this._xhr.length;j=j+1){this._xhr[j].abort();}return;}if(m.type!=="js"){this._loadCount++;continue;}url=m.fullpath;url=(url)?this._filter(url):this._url(m.path);var xhrData={success:function(o){var idx=o.argument[0],name=o.argument[2];this._scriptText[idx]=o.responseText;if(this.onProgress){this.onProgress.call(this.scope,{name:name,scriptText:o.responseText,xhrResponse:o,data:this.data});}this._loadCount++;if(this._loadCount>=this._stopCount){var v=this.varName||"YAHOO";var t="(function() {\n";var b="\nreturn "+v+";\n})();";var ref=eval(t+this._scriptText.join("\n")+b);this._pushEvents(ref);if(ref){this.onSuccess.call(this.scope,{reference:ref,data:this.data});}else{this._onFailure.call(this.varName+" reference failure");}}},failure:function(o){this.onFailure.call(this.scope,{msg:"XHR failure",xhrResponse:o,data:this.data});},scope:this,argument:[i,url,s[i]]};this._xhr.push(util.Connect.asyncRequest("GET",url,xhrData));}},loadNext:function(mname){if(!this._loading){return;}if(mname){if(mname!==this._loading){return;}this.inserted[mname]=true;if(this.onProgress){this.onProgress.call(this.scope,{name:mname,data:this.data});}}var s=this.sorted,len=s.length,i,m;for(i=0;i<len;i=i+1){if(s[i] in this.inserted){continue;}if(s[i]===this._loading){return;}m=this.moduleInfo[s[i]];if(!m){this.onFailure.call(this.scope,{msg:"undefined module "+m,data:this.data});return;}if(!this.loadType||this.loadType===m.type){this._loading=s[i];var fn=(m.type==="css")?util.Get.css:util.Get.script,url=m.fullpath,self=this,c=function(o){self.loadNext(o.data);};url=(url)?this._filter(url):this._url(m.path);if(env.ua.webkit&&env.ua.webkit<420&&m.type==="js"&&!m.varName){c=null;this._useYahooListener=true;}fn(url,{data:s[i],onSuccess:c,onFailure:this._onFailure,onTimeout:this._onTimeout,insertBefore:this.insertBefore,charset:this.charset,timeout:this.timeout,varName:m.varName,scope:self});return;}}this._loading=null;if(this._internalCallback){var f=this._internalCallback;this._internalCallback=null;f.call(this);}else{if(this.onSuccess){this._pushEvents();this.onSuccess.call(this.scope,{data:this.data});}}},_pushEvents:function(ref){var r=ref||YAHOO;if(r.util&&r.util.Event){r.util.Event._load();}},_filter:function(str){var f=this.filter;return(f)?str.replace(new RegExp(f.searchExp,"g"),f.replaceStr):str;},_url:function(path){return this._filter((this.base||"")+path);}};})();YAHOO.register("yuiloader",YAHOO.util.YUILoader,{version:"2.8.2r1",build:"7"});
-(function(){YAHOO.env._id_counter=YAHOO.env._id_counter||0;var E=YAHOO.util,L=YAHOO.lang,m=YAHOO.env.ua,A=YAHOO.lang.trim,d={},h={},N=/^t(?:able|d|h)$/i,X=/color$/i,K=window.document,W=K.documentElement,e="ownerDocument",n="defaultView",v="documentElement",t="compatMode",b="offsetLeft",P="offsetTop",u="offsetParent",Z="parentNode",l="nodeType",C="tagName",O="scrollLeft",i="scrollTop",Q="getBoundingClientRect",w="getComputedStyle",a="currentStyle",M="CSS1Compat",c="BackCompat",g="class",F="className",J="",B=" ",s="(?:^|\\s)",k="(?= |$)",U="g",p="position",f="fixed",V="relative",j="left",o="top",r="medium",q="borderLeftWidth",R="borderTopWidth",D=m.opera,I=m.webkit,H=m.gecko,T=m.ie;E.Dom={CUSTOM_ATTRIBUTES:(!W.hasAttribute)?{"for":"htmlFor","class":F}:{"htmlFor":"for","className":g},DOT_ATTRIBUTES:{},get:function(z){var AB,x,AA,y,Y,G;if(z){if(z[l]||z.item){return z;}if(typeof z==="string"){AB=z;z=K.getElementById(z);G=(z)?z.attributes:null;if(z&&G&&G.id&&G.id.value===AB){return z;}else{if(z&&K.all){z=null;x=K.all[AB];for(y=0,Y=x.length;y<Y;++y){if(x[y].id===AB){return x[y];}}}}return z;}if(YAHOO.util.Element&&z instanceof YAHOO.util.Element){z=z.get("element");}if("length" in z){AA=[];for(y=0,Y=z.length;y<Y;++y){AA[AA.length]=E.Dom.get(z[y]);}return AA;}return z;}return null;},getComputedStyle:function(G,Y){if(window[w]){return G[e][n][w](G,null)[Y];}else{if(G[a]){return E.Dom.IE_ComputedStyle.get(G,Y);}}},getStyle:function(G,Y){return E.Dom.batch(G,E.Dom._getStyle,Y);},_getStyle:function(){if(window[w]){return function(G,y){y=(y==="float")?y="cssFloat":E.Dom._toCamel(y);var x=G.style[y],Y;if(!x){Y=G[e][n][w](G,null);if(Y){x=Y[y];}}return x;};}else{if(W[a]){return function(G,y){var x;switch(y){case"opacity":x=100;try{x=G.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(z){try{x=G.filters("alpha").opacity;}catch(Y){}}return x/100;case"float":y="styleFloat";default:y=E.Dom._toCamel(y);x=G[a]?G[a][y]:null;return(G.style[y]||x);}};}}}(),setStyle:function(G,Y,x){E.Dom.batch(G,E.Dom._setStyle,{prop:Y,val:x});},_setStyle:function(){if(T){return function(Y,G){var x=E.Dom._toCamel(G.prop),y=G.val;if(Y){switch(x){case"opacity":if(L.isString(Y.style.filter)){Y.style.filter="alpha(opacity="+y*100+")";if(!Y[a]||!Y[a].hasLayout){Y.style.zoom=1;}}break;case"float":x="styleFloat";default:Y.style[x]=y;}}else{}};}else{return function(Y,G){var x=E.Dom._toCamel(G.prop),y=G.val;if(Y){if(x=="float"){x="cssFloat";}Y.style[x]=y;}else{}};}}(),getXY:function(G){return E.Dom.batch(G,E.Dom._getXY);},_canPosition:function(G){return(E.Dom._getStyle(G,"display")!=="none"&&E.Dom._inDoc(G));},_getXY:function(){if(K[v][Q]){return function(y){var z,Y,AA,AF,AE,AD,AC,G,x,AB=Math.floor,AG=false;if(E.Dom._canPosition(y)){AA=y[Q]();AF=y[e];z=E.Dom.getDocumentScrollLeft(AF);Y=E.Dom.getDocumentScrollTop(AF);AG=[AB(AA[j]),AB(AA[o])];if(T&&m.ie<8){AE=2;AD=2;AC=AF[t];if(m.ie===6){if(AC!==c){AE=0;AD=0;}}if((AC===c)){G=S(AF[v],q);x=S(AF[v],R);if(G!==r){AE=parseInt(G,10);}if(x!==r){AD=parseInt(x,10);}}AG[0]-=AE;AG[1]-=AD;}if((Y||z)){AG[0]+=z;AG[1]+=Y;}AG[0]=AB(AG[0]);AG[1]=AB(AG[1]);}else{}return AG;};}else{return function(y){var x,Y,AA,AB,AC,z=false,G=y;if(E.Dom._canPosition(y)){z=[y[b],y[P]];x=E.Dom.getDocumentScrollLeft(y[e]);Y=E.Dom.getDocumentScrollTop(y[e]);AC=((H||m.webkit>519)?true:false);while((G=G[u])){z[0]+=G[b];z[1]+=G[P];if(AC){z=E.Dom._calcBorders(G,z);}}if(E.Dom._getStyle(y,p)!==f){G=y;while((G=G[Z])&&G[C]){AA=G[i];AB=G[O];if(H&&(E.Dom._getStyle(G,"overflow")!=="visible")){z=E.Dom._calcBorders(G,z);}if(AA||AB){z[0]-=AB;z[1]-=AA;}}z[0]+=x;z[1]+=Y;}else{if(D){z[0]-=x;z[1]-=Y;}else{if(I||H){z[0]+=x;z[1]+=Y;}}}z[0]=Math.floor(z[0]);z[1]=Math.floor(z[1]);}else{}return z;};}}(),getX:function(G){var Y=function(x){return E.Dom.getXY(x)[0];};return E.Dom.batch(G,Y,E.Dom,true);},getY:function(G){var Y=function(x){return E.Dom.getXY(x)[1];};return E.Dom.batch(G,Y,E.Dom,true);},setXY:function(G,x,Y){E.Dom.batch(G,E.Dom._setXY,{pos:x,noRetry:Y});},_setXY:function(G,z){var AA=E.Dom._getStyle(G,p),y=E.Dom.setStyle,AD=z.pos,Y=z.noRetry,AB=[parseInt(E.Dom.getComputedStyle(G,j),10),parseInt(E.Dom.getComputedStyle(G,o),10)],AC,x;if(AA=="static"){AA=V;y(G,p,AA);}AC=E.Dom._getXY(G);if(!AD||AC===false){return false;}if(isNaN(AB[0])){AB[0]=(AA==V)?0:G[b];}if(isNaN(AB[1])){AB[1]=(AA==V)?0:G[P];}if(AD[0]!==null){y(G,j,AD[0]-AC[0]+AB[0]+"px");}if(AD[1]!==null){y(G,o,AD[1]-AC[1]+AB[1]+"px");}if(!Y){x=E.Dom._getXY(G);if((AD[0]!==null&&x[0]!=AD[0])||(AD[1]!==null&&x[1]!=AD[1])){E.Dom._setXY(G,{pos:AD,noRetry:true});}}},setX:function(Y,G){E.Dom.setXY(Y,[G,null]);},setY:function(G,Y){E.Dom.setXY(G,[null,Y]);},getRegion:function(G){var Y=function(x){var y=false;if(E.Dom._canPosition(x)){y=E.Region.getRegion(x);}else{}return y;};return E.Dom.batch(G,Y,E.Dom,true);},getClientWidth:function(){return E.Dom.getViewportWidth();},getClientHeight:function(){return E.Dom.getViewportHeight();},getElementsByClassName:function(AB,AF,AC,AE,x,AD){AF=AF||"*";AC=(AC)?E.Dom.get(AC):null||K;if(!AC){return[];}var Y=[],G=AC.getElementsByTagName(AF),z=E.Dom.hasClass;for(var y=0,AA=G.length;y<AA;++y){if(z(G[y],AB)){Y[Y.length]=G[y];}}if(AE){E.Dom.batch(Y,AE,x,AD);}return Y;},hasClass:function(Y,G){return E.Dom.batch(Y,E.Dom._hasClass,G);},_hasClass:function(x,Y){var G=false,y;if(x&&Y){y=E.Dom._getAttribute(x,F)||J;if(Y.exec){G=Y.test(y);}else{G=Y&&(B+y+B).indexOf(B+Y+B)>-1;}}else{}return G;},addClass:function(Y,G){return E.Dom.batch(Y,E.Dom._addClass,G);},_addClass:function(x,Y){var G=false,y;if(x&&Y){y=E.Dom._getAttribute(x,F)||J;if(!E.Dom._hasClass(x,Y)){E.Dom.setAttribute(x,F,A(y+B+Y));G=true;}}else{}return G;},removeClass:function(Y,G){return E.Dom.batch(Y,E.Dom._removeClass,G);},_removeClass:function(y,x){var Y=false,AA,z,G;if(y&&x){AA=E.Dom._getAttribute(y,F)||J;E.Dom.setAttribute(y,F,AA.replace(E.Dom._getClassRegex(x),J));z=E.Dom._getAttribute(y,F);if(AA!==z){E.Dom.setAttribute(y,F,A(z));Y=true;if(E.Dom._getAttribute(y,F)===""){G=(y.hasAttribute&&y.hasAttribute(g))?g:F;
-y.removeAttribute(G);}}}else{}return Y;},replaceClass:function(x,Y,G){return E.Dom.batch(x,E.Dom._replaceClass,{from:Y,to:G});},_replaceClass:function(y,x){var Y,AB,AA,G=false,z;if(y&&x){AB=x.from;AA=x.to;if(!AA){G=false;}else{if(!AB){G=E.Dom._addClass(y,x.to);}else{if(AB!==AA){z=E.Dom._getAttribute(y,F)||J;Y=(B+z.replace(E.Dom._getClassRegex(AB),B+AA)).split(E.Dom._getClassRegex(AA));Y.splice(1,0,B+AA);E.Dom.setAttribute(y,F,A(Y.join(J)));G=true;}}}}else{}return G;},generateId:function(G,x){x=x||"yui-gen";var Y=function(y){if(y&&y.id){return y.id;}var z=x+YAHOO.env._id_counter++;if(y){if(y[e]&&y[e].getElementById(z)){return E.Dom.generateId(y,z+x);}y.id=z;}return z;};return E.Dom.batch(G,Y,E.Dom,true)||Y.apply(E.Dom,arguments);},isAncestor:function(Y,x){Y=E.Dom.get(Y);x=E.Dom.get(x);var G=false;if((Y&&x)&&(Y[l]&&x[l])){if(Y.contains&&Y!==x){G=Y.contains(x);}else{if(Y.compareDocumentPosition){G=!!(Y.compareDocumentPosition(x)&16);}}}else{}return G;},inDocument:function(G,Y){return E.Dom._inDoc(E.Dom.get(G),Y);},_inDoc:function(Y,x){var G=false;if(Y&&Y[C]){x=x||Y[e];G=E.Dom.isAncestor(x[v],Y);}else{}return G;},getElementsBy:function(Y,AF,AB,AD,y,AC,AE){AF=AF||"*";AB=(AB)?E.Dom.get(AB):null||K;if(!AB){return[];}var x=[],G=AB.getElementsByTagName(AF);for(var z=0,AA=G.length;z<AA;++z){if(Y(G[z])){if(AE){x=G[z];break;}else{x[x.length]=G[z];}}}if(AD){E.Dom.batch(x,AD,y,AC);}return x;},getElementBy:function(x,G,Y){return E.Dom.getElementsBy(x,G,Y,null,null,null,true);},batch:function(x,AB,AA,z){var y=[],Y=(z)?AA:window;x=(x&&(x[C]||x.item))?x:E.Dom.get(x);if(x&&AB){if(x[C]||x.length===undefined){return AB.call(Y,x,AA);}for(var G=0;G<x.length;++G){y[y.length]=AB.call(Y,x[G],AA);}}else{return false;}return y;},getDocumentHeight:function(){var Y=(K[t]!=M||I)?K.body.scrollHeight:W.scrollHeight,G=Math.max(Y,E.Dom.getViewportHeight());return G;},getDocumentWidth:function(){var Y=(K[t]!=M||I)?K.body.scrollWidth:W.scrollWidth,G=Math.max(Y,E.Dom.getViewportWidth());return G;},getViewportHeight:function(){var G=self.innerHeight,Y=K[t];if((Y||T)&&!D){G=(Y==M)?W.clientHeight:K.body.clientHeight;}return G;},getViewportWidth:function(){var G=self.innerWidth,Y=K[t];if(Y||T){G=(Y==M)?W.clientWidth:K.body.clientWidth;}return G;},getAncestorBy:function(G,Y){while((G=G[Z])){if(E.Dom._testElement(G,Y)){return G;}}return null;},getAncestorByClassName:function(Y,G){Y=E.Dom.get(Y);if(!Y){return null;}var x=function(y){return E.Dom.hasClass(y,G);};return E.Dom.getAncestorBy(Y,x);},getAncestorByTagName:function(Y,G){Y=E.Dom.get(Y);if(!Y){return null;}var x=function(y){return y[C]&&y[C].toUpperCase()==G.toUpperCase();};return E.Dom.getAncestorBy(Y,x);},getPreviousSiblingBy:function(G,Y){while(G){G=G.previousSibling;if(E.Dom._testElement(G,Y)){return G;}}return null;},getPreviousSibling:function(G){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getPreviousSiblingBy(G);},getNextSiblingBy:function(G,Y){while(G){G=G.nextSibling;if(E.Dom._testElement(G,Y)){return G;}}return null;},getNextSibling:function(G){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getNextSiblingBy(G);},getFirstChildBy:function(G,x){var Y=(E.Dom._testElement(G.firstChild,x))?G.firstChild:null;return Y||E.Dom.getNextSiblingBy(G.firstChild,x);},getFirstChild:function(G,Y){G=E.Dom.get(G);if(!G){return null;}return E.Dom.getFirstChildBy(G);},getLastChildBy:function(G,x){if(!G){return null;}var Y=(E.Dom._testElement(G.lastChild,x))?G.lastChild:null;return Y||E.Dom.getPreviousSiblingBy(G.lastChild,x);},getLastChild:function(G){G=E.Dom.get(G);return E.Dom.getLastChildBy(G);},getChildrenBy:function(Y,y){var x=E.Dom.getFirstChildBy(Y,y),G=x?[x]:[];E.Dom.getNextSiblingBy(x,function(z){if(!y||y(z)){G[G.length]=z;}return false;});return G;},getChildren:function(G){G=E.Dom.get(G);if(!G){}return E.Dom.getChildrenBy(G);},getDocumentScrollLeft:function(G){G=G||K;return Math.max(G[v].scrollLeft,G.body.scrollLeft);},getDocumentScrollTop:function(G){G=G||K;return Math.max(G[v].scrollTop,G.body.scrollTop);},insertBefore:function(Y,G){Y=E.Dom.get(Y);G=E.Dom.get(G);if(!Y||!G||!G[Z]){return null;}return G[Z].insertBefore(Y,G);},insertAfter:function(Y,G){Y=E.Dom.get(Y);G=E.Dom.get(G);if(!Y||!G||!G[Z]){return null;}if(G.nextSibling){return G[Z].insertBefore(Y,G.nextSibling);}else{return G[Z].appendChild(Y);}},getClientRegion:function(){var x=E.Dom.getDocumentScrollTop(),Y=E.Dom.getDocumentScrollLeft(),y=E.Dom.getViewportWidth()+Y,G=E.Dom.getViewportHeight()+x;return new E.Region(x,y,G,Y);},setAttribute:function(Y,G,x){E.Dom.batch(Y,E.Dom._setAttribute,{attr:G,val:x});},_setAttribute:function(x,Y){var G=E.Dom._toCamel(Y.attr),y=Y.val;if(x&&x.setAttribute){if(E.Dom.DOT_ATTRIBUTES[G]){x[G]=y;}else{G=E.Dom.CUSTOM_ATTRIBUTES[G]||G;x.setAttribute(G,y);}}else{}},getAttribute:function(Y,G){return E.Dom.batch(Y,E.Dom._getAttribute,G);},_getAttribute:function(Y,G){var x;G=E.Dom.CUSTOM_ATTRIBUTES[G]||G;if(Y&&Y.getAttribute){x=Y.getAttribute(G,2);}else{}return x;},_toCamel:function(Y){var x=d;function G(y,z){return z.toUpperCase();}return x[Y]||(x[Y]=Y.indexOf("-")===-1?Y:Y.replace(/-([a-z])/gi,G));},_getClassRegex:function(Y){var G;if(Y!==undefined){if(Y.exec){G=Y;}else{G=h[Y];if(!G){Y=Y.replace(E.Dom._patterns.CLASS_RE_TOKENS,"\\$1");G=h[Y]=new RegExp(s+Y+k,U);}}}return G;},_patterns:{ROOT_TAG:/^body|html$/i,CLASS_RE_TOKENS:/([\.\(\)\^\$\*\+\?\|\[\]\{\}\\])/g},_testElement:function(G,Y){return G&&G[l]==1&&(!Y||Y(G));},_calcBorders:function(x,y){var Y=parseInt(E.Dom[w](x,R),10)||0,G=parseInt(E.Dom[w](x,q),10)||0;if(H){if(N.test(x[C])){Y=0;G=0;}}y[0]+=G;y[1]+=Y;return y;}};var S=E.Dom[w];if(m.opera){E.Dom[w]=function(Y,G){var x=S(Y,G);if(X.test(G)){x=E.Dom.Color.toRGB(x);}return x;};}if(m.webkit){E.Dom[w]=function(Y,G){var x=S(Y,G);if(x==="rgba(0, 0, 0, 0)"){x="transparent";}return x;};}if(m.ie&&m.ie>=8&&K.documentElement.hasAttribute){E.Dom.DOT_ATTRIBUTES.type=true;}})();YAHOO.util.Region=function(C,D,A,B){this.top=C;this.y=C;this[1]=C;this.right=D;this.bottom=A;this.left=B;this.x=B;this[0]=B;
-this.width=this.right-this.left;this.height=this.bottom-this.top;};YAHOO.util.Region.prototype.contains=function(A){return(A.left>=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top),D=Math.min(this.right,E.right),A=Math.min(this.bottom,E.bottom),B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top),D=Math.max(this.right,E.right),A=Math.max(this.bottom,E.bottom),B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+", height: "+this.height+", width: "+this.width+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D),C=F[1],E=F[0]+D.offsetWidth,A=F[1]+D.offsetHeight,B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}YAHOO.util.Point.superclass.constructor.call(this,B,A,B,A);};YAHOO.extend(YAHOO.util.Point,YAHOO.util.Region);(function(){var B=YAHOO.util,A="clientTop",F="clientLeft",J="parentNode",K="right",W="hasLayout",I="px",U="opacity",L="auto",D="borderLeftWidth",G="borderTopWidth",P="borderRightWidth",V="borderBottomWidth",S="visible",Q="transparent",N="height",E="width",H="style",T="currentStyle",R=/^width|height$/,O=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,M={get:function(X,Z){var Y="",a=X[T][Z];if(Z===U){Y=B.Dom.getStyle(X,U);}else{if(!a||(a.indexOf&&a.indexOf(I)>-1)){Y=a;}else{if(B.Dom.IE_COMPUTED[Z]){Y=B.Dom.IE_COMPUTED[Z](X,Z);}else{if(O.test(a)){Y=B.Dom.IE.ComputedStyle.getPixel(X,Z);}else{Y=a;}}}}return Y;},getOffset:function(Z,e){var b=Z[T][e],X=e.charAt(0).toUpperCase()+e.substr(1),c="offset"+X,Y="pixel"+X,a="",d;if(b==L){d=Z[c];if(d===undefined){a=0;}a=d;if(R.test(e)){Z[H][e]=d;if(Z[c]>d){a=d-(Z[c]-d);}Z[H][e]=L;}}else{if(!Z[H][Y]&&!Z[H][e]){Z[H][e]=b;}a=Z[H][Y];}return a+I;},getBorderWidth:function(X,Z){var Y=null;if(!X[T][W]){X[H].zoom=1;}switch(Z){case G:Y=X[A];break;case V:Y=X.offsetHeight-X.clientHeight-X[A];break;case D:Y=X[F];break;case P:Y=X.offsetWidth-X.clientWidth-X[F];break;}return Y+I;},getPixel:function(Y,X){var a=null,b=Y[T][K],Z=Y[T][X];Y[H][K]=Z;a=Y[H].pixelRight;Y[H][K]=b;return a+I;},getMargin:function(Y,X){var Z;if(Y[T][X]==L){Z=0+I;}else{Z=B.Dom.IE.ComputedStyle.getPixel(Y,X);}return Z;},getVisibility:function(Y,X){var Z;while((Z=Y[T])&&Z[X]=="inherit"){Y=Y[J];}return(Z)?Z[X]:S;},getColor:function(Y,X){return B.Dom.Color.toRGB(Y[T][X])||Q;},getBorderColor:function(Y,X){var Z=Y[T],a=Z[X]||Z.color;return B.Dom.Color.toRGB(B.Dom.Color.toHex(a));}},C={};C.top=C.right=C.bottom=C.left=C[E]=C[N]=M.getOffset;C.color=M.getColor;C[G]=C[P]=C[V]=C[D]=M.getBorderWidth;C.marginTop=C.marginRight=C.marginBottom=C.marginLeft=M.getMargin;C.visibility=M.getVisibility;C.borderColor=C.borderTopColor=C.borderRightColor=C.borderBottomColor=C.borderLeftColor=M.getBorderColor;B.Dom.IE_COMPUTED=C;B.Dom.IE_ComputedStyle=M;})();(function(){var C="toString",A=parseInt,B=RegExp,D=YAHOO.util;D.Dom.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(E){if(!D.Dom.Color.re_RGB.test(E)){E=D.Dom.Color.toHex(E);}if(D.Dom.Color.re_hex.exec(E)){E="rgb("+[A(B.$1,16),A(B.$2,16),A(B.$3,16)].join(", ")+")";}return E;},toHex:function(H){H=D.Dom.Color.KEYWORDS[H]||H;if(D.Dom.Color.re_RGB.exec(H)){var G=(B.$1.length===1)?"0"+B.$1:Number(B.$1),F=(B.$2.length===1)?"0"+B.$2:Number(B.$2),E=(B.$3.length===1)?"0"+B.$3:Number(B.$3);H=[G[C](16),F[C](16),E[C](16)].join("");}if(H.length<6){H=H.replace(D.Dom.Color.re_hex3,"$1$1");}if(H!=="transparent"&&H.indexOf("#")<0){H="#"+H;}return H.toLowerCase();}};}());YAHOO.register("dom",YAHOO.util.Dom,{version:"2.8.2r1",build:"7"});YAHOO.util.CustomEvent=function(D,C,B,A,E){this.type=D;this.scope=C||window;this.silent=B;this.fireOnce=E;this.fired=false;this.firedWith=null;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var F="_YUICEOnSubscribe";if(D!==F){this.subscribeEvent=new YAHOO.util.CustomEvent(F,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,D){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,D);}var A=new YAHOO.util.Subscriber(B,C,D);if(this.fireOnce&&this.fired){this.notify(A,this.firedWith);}else{this.subscribers.push(A);}},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){this.lastError=null;var H=[],A=this.subscribers.length;var D=[].slice.call(arguments,0),C=true,F,B=false;if(this.fireOnce){if(this.fired){return true;}else{this.firedWith=D;}}this.fired=true;if(!A&&this.silent){return true;}if(!this.silent){}var E=this.subscribers.slice();for(F=0;F<A;++F){var G=E[F];if(!G){B=true;}else{C=this.notify(G,D);if(false===C){if(!this.silent){}break;}}}return(C!==false);},notify:function(F,C){var B,H=null,E=F.getScope(this.scope),A=YAHOO.util.Event.throwErrors;if(!this.silent){}if(this.signature==YAHOO.util.CustomEvent.FLAT){if(C.length>0){H=C[0];}try{B=F.fn.call(E,H,F.obj);}catch(G){this.lastError=G;if(A){throw G;}}}else{try{B=F.fn.call(E,this.type,C,F.obj);}catch(D){this.lastError=D;if(A){throw D;}}}return B;},unsubscribeAll:function(){var A=this.subscribers.length,B;for(B=A-1;B>-1;B--){this._delete(B);}this.subscribers=[];return A;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers.splice(A,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"context: "+this.scope;}};YAHOO.util.Subscriber=function(A,B,C){this.fn=A;this.obj=YAHOO.lang.isUndefined(B)?null:B;this.overrideContext=C;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.overrideContext){if(this.overrideContext===true){return this.obj;}else{return this.overrideContext;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", overrideContext: "+(this.overrideContext||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var G=false,H=[],J=[],A=0,E=[],B=0,C={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9},D=YAHOO.env.ua.ie,F="focusin",I="focusout";return{POLL_RETRYS:500,POLL_INTERVAL:40,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:D,_interval:null,_dri:null,_specialTypes:{focusin:(D?"focusin":"focus"),focusout:(D?"focusout":"blur")},DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){this._interval=YAHOO.lang.later(this.POLL_INTERVAL,this,this._tryPreloadAttach,null,true);}},onAvailable:function(Q,M,O,P,N){var K=(YAHOO.lang.isString(Q))?[Q]:Q;for(var L=0;L<K.length;L=L+1){E.push({id:K[L],fn:M,obj:O,overrideContext:P,checkReady:N});}A=this.POLL_RETRYS;this.startInterval();},onContentReady:function(N,K,L,M){this.onAvailable(N,K,L,M,true);},onDOMReady:function(){this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent,arguments);},_addListener:function(M,K,V,P,T,Y){if(!V||!V.call){return false;}if(this._isValidCollection(M)){var W=true;for(var Q=0,S=M.length;Q<S;++Q){W=this.on(M[Q],K,V,P,T)&&W;}return W;}else{if(YAHOO.lang.isString(M)){var O=this.getEl(M);if(O){M=O;}else{this.onAvailable(M,function(){YAHOO.util.Event._addListener(M,K,V,P,T,Y);});return true;}}}if(!M){return false;}if("unload"==K&&P!==this){J[J.length]=[M,K,V,P,T];return true;}var L=M;if(T){if(T===true){L=P;}else{L=T;}}var N=function(Z){return V.call(L,YAHOO.util.Event.getEvent(Z,M),P);};var X=[M,K,V,N,L,P,T,Y];var R=H.length;H[R]=X;try{this._simpleAdd(M,K,N,Y);}catch(U){this.lastError=U;this.removeListener(M,K,V);return false;}return true;},_getType:function(K){return this._specialTypes[K]||K;},addListener:function(M,P,L,N,O){var K=((P==F||P==I)&&!YAHOO.env.ua.ie)?true:false;return this._addListener(M,this._getType(P),L,N,O,K);},addFocusListener:function(L,K,M,N){return this.on(L,F,K,M,N);},removeFocusListener:function(L,K){return this.removeListener(L,F,K);},addBlurListener:function(L,K,M,N){return this.on(L,I,K,M,N);},removeBlurListener:function(L,K){return this.removeListener(L,I,K);},removeListener:function(L,K,R){var M,P,U;K=this._getType(K);if(typeof L=="string"){L=this.getEl(L);}else{if(this._isValidCollection(L)){var S=true;for(M=L.length-1;M>-1;M--){S=(this.removeListener(L[M],K,R)&&S);}return S;}}if(!R||!R.call){return this.purgeElement(L,false,K);}if("unload"==K){for(M=J.length-1;M>-1;M--){U=J[M];if(U&&U[0]==L&&U[1]==K&&U[2]==R){J.splice(M,1);return true;}}return false;}var N=null;var O=arguments[3];if("undefined"===typeof O){O=this._getCacheIndex(H,L,K,R);}if(O>=0){N=H[O];}if(!L||!N){return false;}var T=N[this.CAPTURE]===true?true:false;try{this._simpleRemove(L,K,N[this.WFN],T);}catch(Q){this.lastError=Q;return false;}delete H[O][this.WFN];delete H[O][this.FN];H.splice(O,1);return true;},getTarget:function(M,L){var K=M.target||M.srcElement;return this.resolveTextNode(K);},resolveTextNode:function(L){try{if(L&&3==L.nodeType){return L.parentNode;}}catch(K){}return L;},getPageX:function(L){var K=L.pageX;if(!K&&0!==K){K=L.clientX||0;if(this.isIE){K+=this._getScrollLeft();}}return K;},getPageY:function(K){var L=K.pageY;if(!L&&0!==L){L=K.clientY||0;if(this.isIE){L+=this._getScrollTop();}}return L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];},getRelatedTarget:function(L){var K=L.relatedTarget;if(!K){if(L.type=="mouseout"){K=L.toElement;
-}else{if(L.type=="mouseover"){K=L.fromElement;}}}return this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=new Date().getTime();try{M.time=L;}catch(K){this.lastError=K;return L;}}return M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefault(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagation();}else{K.cancelBubble=true;}},preventDefault:function(K){if(K.preventDefault){K.preventDefault();}else{K.returnValue=false;}},getEvent:function(M,K){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break;}N=N.caller;}}return L;},getCharCode:function(L){var K=L.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in C)){K=C[K];}return K;},_getCacheIndex:function(M,P,Q,O){for(var N=0,L=M.length;N<L;N=N+1){var K=M[N];if(K&&K[this.FN]==O&&K[this.EL]==P&&K[this.TYPE]==Q){return N;}}return -1;},generateId:function(K){var L=K.id;if(!L){L="yuievtautoid-"+B;++B;K.id=L;}return L;},_isValidCollection:function(L){try{return(L&&typeof L!=="string"&&L.length&&!L.tagName&&!L.alert&&typeof L[0]!=="undefined");}catch(K){return false;}},elCache:{},getEl:function(K){return(typeof K==="string")?document.getElementById(K):K;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",YAHOO,0,0,1),_load:function(L){if(!G){G=true;var K=YAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(L){var K=YAHOO.util.Event;if(!K.DOMReady){K.DOMReady=true;K.DOMReadyEvent.fire();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreloadAttach:function(){if(E.length===0){A=0;if(this._interval){this._interval.cancel();this._interval=null;}return;}if(this.locked){return;}if(this.isIE){if(!this.DOMReady){this.startInterval();return;}}this.locked=true;var Q=!G;if(!Q){Q=(A>0&&E.length>0);}var P=[];var R=function(T,U){var S=T;if(U.overrideContext){if(U.overrideContext===true){S=U.obj;}else{S=U.overrideContext;}}U.fn.call(S,U.obj);};var L,K,O,N,M=[];for(L=0,K=E.length;L<K;L=L+1){O=E[L];if(O){N=this.getEl(O.id);if(N){if(O.checkReady){if(G||N.nextSibling||!Q){M.push(O);E[L]=null;}}else{R(N,O);E[L]=null;}}else{P.push(O);}}}for(L=0,K=M.length;L<K;L=L+1){O=M[L];R(this.getEl(O.id),O);}A--;if(Q){for(L=E.length-1;L>-1;L--){O=E[L];if(!O||!O.id){E.splice(L,1);}}this.startInterval();}else{if(this._interval){this._interval.cancel();this._interval=null;}}this.locked=false;},purgeElement:function(O,P,R){var M=(YAHOO.lang.isString(O))?this.getEl(O):O;var Q=this.getListeners(M,R),N,K;if(Q){for(N=Q.length-1;N>-1;N--){var L=Q[N];this.removeListener(M,L.type,L.fn);}}if(P&&M&&M.childNodes){for(N=0,K=M.childNodes.length;N<K;++N){this.purgeElement(M.childNodes[N],P,R);}}},getListeners:function(M,K){var P=[],L;if(!K){L=[H,J];}else{if(K==="unload"){L=[J];}else{K=this._getType(K);L=[H];}}var R=(YAHOO.lang.isString(M))?this.getEl(M):M;for(var O=0;O<L.length;O=O+1){var T=L[O];if(T){for(var Q=0,S=T.length;Q<S;++Q){var N=T[Q];if(N&&N[this.EL]===R&&(!K||K===N[this.TYPE])){P.push({type:N[this.TYPE],fn:N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE],scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:function(R){var L=YAHOO.util.Event,O,N,M,Q,P,S=J.slice(),K;for(O=0,Q=J.length;O<Q;++O){M=S[O];if(M){K=window;if(M[L.ADJ_SCOPE]){if(M[L.ADJ_SCOPE]===true){K=M[L.UNLOAD_OBJ];}else{K=M[L.ADJ_SCOPE];}}M[L.FN].call(K,L.getEvent(R,M[L.EL]),M[L.UNLOAD_OBJ]);S[O]=null;}}M=null;K=null;J=null;if(H){for(N=H.length-1;N>-1;N--){M=H[N];if(M){L.removeListener(M[L.EL],M[L.TYPE],M[L.FN],N);}}M=null;}L._simpleRemove(window,"unload",L._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var K=document.documentElement,L=document.body;if(K&&(K.scrollTop||K.scrollLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(M,N,L,K){M.addEventListener(N,L,(K));};}else{if(window.attachEvent){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detachEvent){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return function(){};}}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;EU.onFocus=EU.addFocusListener;EU.onBlur=EU.addBlurListener;
-/* DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
-if(EU.isIE){if(self!==self.top){document.onreadystatechange=function(){if(document.readyState=="complete"){document.onreadystatechange=null;EU._ready();}};}else{YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var n=document.createElement("p");EU._dri=setInterval(function(){try{n.doScroll("left");clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}}else{if(EU.webkit&&EU.webkit<525){EU._dri=setInterval(function(){var rs=document.readyState;if("loaded"==rs||"complete"==rs){clearInterval(EU._dri);EU._dri=null;EU._ready();}},EU.POLL_INTERVAL);}else{EU._simpleAdd(document,"DOMContentLoaded",EU._ready);}}EU._simpleAdd(window,"load",EU._load);EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,overrideContext:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);
-},createEvent:function(B,G){this.__yui_events=this.__yui_events||{};var E=G||{},D=this.__yui_events,F;if(D[B]){}else{F=new YAHOO.util.CustomEvent(B,E.scope||this,E.silent,YAHOO.util.CustomEvent.FLAT,E.fireOnce);D[B]=F;if(E.onSubscribeCallback){F.subscribeEvent.subscribe(E.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var A=this.__yui_subscribers[B];if(A){for(var C=0;C<A.length;++C){F.subscribe(A[C].fn,A[C].obj,A[C].overrideContext);}}}return D[B];},fireEvent:function(B){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[B];if(!D){return null;}var A=[];for(var C=1;C<arguments.length;++C){A.push(arguments[C]);}return D.fire.apply(D,A);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};(function(){var A=YAHOO.util.Event,C=YAHOO.lang;YAHOO.util.KeyListener=function(D,I,E,F){if(!D){}else{if(!I){}else{if(!E){}}}if(!F){F=YAHOO.util.KeyListener.KEYDOWN;}var G=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(C.isString(D)){D=document.getElementById(D);}if(C.isFunction(E)){G.subscribe(E);}else{G.subscribe(E.fn,E.scope,E.correctScope);}function H(O,N){if(!I.shift){I.shift=false;}if(!I.alt){I.alt=false;}if(!I.ctrl){I.ctrl=false;}if(O.shiftKey==I.shift&&O.altKey==I.alt&&O.ctrlKey==I.ctrl){var J,M=I.keys,L;if(YAHOO.lang.isArray(M)){for(var K=0;K<M.length;K++){J=M[K];L=A.getCharCode(O);if(J==L){G.fire(L,O);break;}}}else{L=A.getCharCode(O);if(M==L){G.fire(L,O);}}}}this.enable=function(){if(!this.enabled){A.on(D,F,H);this.enabledEvent.fire(I);}this.enabled=true;};this.disable=function(){if(this.enabled){A.removeListener(D,F,H);this.disabledEvent.fire(I);}this.enabled=false;};this.toString=function(){return"KeyListener ["+I.keys+"] "+D.tagName+(D.id?"["+D.id+"]":"");};};var B=YAHOO.util.KeyListener;B.KEYDOWN="keydown";B.KEYUP="keyup";B.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};})();YAHOO.register("event",YAHOO.util.Event,{version:"2.8.2r1",build:"7"});YAHOO.util.Connect={_msxml_progid:["Microsoft.XMLHTTP","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP"],_http_headers:{},_has_http_headers:false,_use_default_post_header:true,_default_post_header:"application/x-www-form-urlencoded; charset=UTF-8",_default_form_header:"application/x-www-form-urlencoded",_use_default_xhr_header:true,_default_xhr_header:"XMLHttpRequest",_has_default_headers:true,_default_headers:{},_poll:{},_timeOut:{},_polling_interval:50,_transaction_id:0,startEvent:new YAHOO.util.CustomEvent("start"),completeEvent:new YAHOO.util.CustomEvent("complete"),successEvent:new YAHOO.util.CustomEvent("success"),failureEvent:new YAHOO.util.CustomEvent("failure"),abortEvent:new YAHOO.util.CustomEvent("abort"),_customEvents:{onStart:["startEvent","start"],onComplete:["completeEvent","complete"],onSuccess:["successEvent","success"],onFailure:["failureEvent","failure"],onUpload:["uploadEvent","upload"],onAbort:["abortEvent","abort"]},setProgId:function(A){this._msxml_progid.unshift(A);},setDefaultPostHeader:function(A){if(typeof A=="string"){this._default_post_header=A;}else{if(typeof A=="boolean"){this._use_default_post_header=A;}}},setDefaultXhrHeader:function(A){if(typeof A=="string"){this._default_xhr_header=A;}else{this._use_default_xhr_header=A;}},setPollingInterval:function(A){if(typeof A=="number"&&isFinite(A)){this._polling_interval=A;}},createXhrObject:function(F){var D,A,B;try{A=new XMLHttpRequest();D={conn:A,tId:F,xhr:true};}catch(C){for(B=0;B<this._msxml_progid.length;++B){try{A=new ActiveXObject(this._msxml_progid[B]);D={conn:A,tId:F,xhr:true};break;}catch(E){}}}finally{return D;}},getConnectionObject:function(A){var C,D=this._transaction_id;try{if(!A){C=this.createXhrObject(D);}else{C={tId:D};if(A==="xdr"){C.conn=this._transport;C.xdr=true;}else{if(A==="upload"){C.upload=true;}}}if(C){this._transaction_id++;}}catch(B){}return C;},asyncRequest:function(G,D,F,A){var E,C,B=(F&&F.argument)?F.argument:null;if(this._isFileUpload){C="upload";}else{if(F.xdr){C="xdr";}}E=this.getConnectionObject(C);if(!E){return null;}else{if(F&&F.customevents){this.initCustomEvents(E,F);}if(this._isFormSubmit){if(this._isFileUpload){this.uploadFile(E,F,D,A);return E;}if(G.toUpperCase()=="GET"){if(this._sFormData.length!==0){D+=((D.indexOf("?")==-1)?"?":"&")+this._sFormData;}}else{if(G.toUpperCase()=="POST"){A=A?this._sFormData+"&"+A:this._sFormData;}}}if(G.toUpperCase()=="GET"&&(F&&F.cache===false)){D+=((D.indexOf("?")==-1)?"?":"&")+"rnd="+new Date().valueOf().toString();}if(this._use_default_xhr_header){if(!this._default_headers["X-Requested-With"]){this.initHeader("X-Requested-With",this._default_xhr_header,true);}}if((G.toUpperCase()==="POST"&&this._use_default_post_header)&&this._isFormSubmit===false){this.initHeader("Content-Type",this._default_post_header);}if(E.xdr){this.xdr(E,G,D,F,A);return E;}E.conn.open(G,D,true);if(this._has_default_headers||this._has_http_headers){this.setHeader(E);}this.handleReadyState(E,F);E.conn.send(A||"");if(this._isFormSubmit===true){this.resetFormState();}this.startEvent.fire(E,B);if(E.startEvent){E.startEvent.fire(E,B);}return E;}},initCustomEvents:function(A,C){var B;for(B in C.customevents){if(this._customEvents[B][0]){A[this._customEvents[B][0]]=new YAHOO.util.CustomEvent(this._customEvents[B][1],(C.scope)?C.scope:null);A[this._customEvents[B][0]].subscribe(C.customevents[B]);}}},handleReadyState:function(C,D){var B=this,A=(D&&D.argument)?D.argument:null;if(D&&D.timeout){this._timeOut[C.tId]=window.setTimeout(function(){B.abort(C,D,true);},D.timeout);}this._poll[C.tId]=window.setInterval(function(){if(C.conn&&C.conn.readyState===4){window.clearInterval(B._poll[C.tId]);delete B._poll[C.tId];if(D&&D.timeout){window.clearTimeout(B._timeOut[C.tId]);delete B._timeOut[C.tId];}B.completeEvent.fire(C,A);if(C.completeEvent){C.completeEvent.fire(C,A);}B.handleTransactionResponse(C,D);}},this._polling_interval);},handleTransactionResponse:function(B,I,D){var E,A,G=(I&&I.argument)?I.argument:null,C=(B.r&&B.r.statusText==="xdr:success")?true:false,H=(B.r&&B.r.statusText==="xdr:failure")?true:false,J=D;try{if((B.conn.status!==undefined&&B.conn.status!==0)||C){E=B.conn.status;}else{if(H&&!J){E=0;}else{E=13030;}}}catch(F){E=13030;}if((E>=200&&E<300)||E===1223||C){A=B.xdr?B.r:this.createResponseObject(B,G);if(I&&I.success){if(!I.scope){I.success(A);}else{I.success.apply(I.scope,[A]);}}this.successEvent.fire(A);if(B.successEvent){B.successEvent.fire(A);}}else{switch(E){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:A=this.createExceptionObject(B.tId,G,(D?D:false));if(I&&I.failure){if(!I.scope){I.failure(A);}else{I.failure.apply(I.scope,[A]);}}break;default:A=(B.xdr)?B.response:this.createResponseObject(B,G);if(I&&I.failure){if(!I.scope){I.failure(A);}else{I.failure.apply(I.scope,[A]);}}}this.failureEvent.fire(A);if(B.failureEvent){B.failureEvent.fire(A);}}this.releaseObject(B);A=null;},createResponseObject:function(A,G){var D={},I={},E,C,F,B;try{C=A.conn.getAllResponseHeaders();F=C.split("\n");for(E=0;E<F.length;E++){B=F[E].indexOf(":");if(B!=-1){I[F[E].substring(0,B)]=YAHOO.lang.trim(F[E].substring(B+2));}}}catch(H){}D.tId=A.tId;D.status=(A.conn.status==1223)?204:A.conn.status;D.statusText=(A.conn.status==1223)?"No Content":A.conn.statusText;D.getResponseHeader=I;D.getAllResponseHeaders=C;D.responseText=A.conn.responseText;D.responseXML=A.conn.responseXML;if(G){D.argument=G;}return D;},createExceptionObject:function(H,D,A){var F=0,G="communication failure",C=-1,B="transaction aborted",E={};E.tId=H;if(A){E.status=C;E.statusText=B;}else{E.status=F;E.statusText=G;}if(D){E.argument=D;}return E;},initHeader:function(A,D,C){var B=(C)?this._default_headers:this._http_headers;B[A]=D;if(C){this._has_default_headers=true;}else{this._has_http_headers=true;}},setHeader:function(A){var B;if(this._has_default_headers){for(B in this._default_headers){if(YAHOO.lang.hasOwnProperty(this._default_headers,B)){A.conn.setRequestHeader(B,this._default_headers[B]);}}}if(this._has_http_headers){for(B in this._http_headers){if(YAHOO.lang.hasOwnProperty(this._http_headers,B)){A.conn.setRequestHeader(B,this._http_headers[B]);
-}}this._http_headers={};this._has_http_headers=false;}},resetDefaultHeaders:function(){this._default_headers={};this._has_default_headers=false;},abort:function(E,G,A){var D,B=(G&&G.argument)?G.argument:null;E=E||{};if(E.conn){if(E.xhr){if(this.isCallInProgress(E)){E.conn.abort();window.clearInterval(this._poll[E.tId]);delete this._poll[E.tId];if(A){window.clearTimeout(this._timeOut[E.tId]);delete this._timeOut[E.tId];}D=true;}}else{if(E.xdr){E.conn.abort(E.tId);D=true;}}}else{if(E.upload){var C="yuiIO"+E.tId;var F=document.getElementById(C);if(F){YAHOO.util.Event.removeListener(F,"load");document.body.removeChild(F);if(A){window.clearTimeout(this._timeOut[E.tId]);delete this._timeOut[E.tId];}D=true;}}else{D=false;}}if(D===true){this.abortEvent.fire(E,B);if(E.abortEvent){E.abortEvent.fire(E,B);}this.handleTransactionResponse(E,G,true);}return D;},isCallInProgress:function(A){A=A||{};if(A.xhr&&A.conn){return A.conn.readyState!==4&&A.conn.readyState!==0;}else{if(A.xdr&&A.conn){return A.conn.isCallInProgress(A.tId);}else{if(A.upload===true){return document.getElementById("yuiIO"+A.tId)?true:false;}else{return false;}}}},releaseObject:function(A){if(A&&A.conn){A.conn=null;A=null;}}};(function(){var G=YAHOO.util.Connect,H={};function D(I){var J='<object id="YUIConnectionSwf" type="application/x-shockwave-flash" data="'+I+'" width="0" height="0">'+'<param name="movie" value="'+I+'">'+'<param name="allowScriptAccess" value="always">'+"</object>",K=document.createElement("div");document.body.appendChild(K);K.innerHTML=J;}function B(L,I,J,M,K){H[parseInt(L.tId)]={"o":L,"c":M};if(K){M.method=I;M.data=K;}L.conn.send(J,M,L.tId);}function E(I){D(I);G._transport=document.getElementById("YUIConnectionSwf");}function C(){G.xdrReadyEvent.fire();}function A(J,I){if(J){G.startEvent.fire(J,I.argument);if(J.startEvent){J.startEvent.fire(J,I.argument);}}}function F(J){var K=H[J.tId].o,I=H[J.tId].c;if(J.statusText==="xdr:start"){A(K,I);return;}J.responseText=decodeURI(J.responseText);K.r=J;if(I.argument){K.r.argument=I.argument;}this.handleTransactionResponse(K,I,J.statusText==="xdr:abort"?true:false);delete H[J.tId];}G.xdr=B;G.swf=D;G.transport=E;G.xdrReadyEvent=new YAHOO.util.CustomEvent("xdrReady");G.xdrReady=C;G.handleXdrResponse=F;})();(function(){var D=YAHOO.util.Connect,F=YAHOO.util.Event;D._isFormSubmit=false;D._isFileUpload=false;D._formNode=null;D._sFormData=null;D._submitElementValue=null;D.uploadEvent=new YAHOO.util.CustomEvent("upload"),D._hasSubmitListener=function(){if(F){F.addListener(document,"click",function(J){var I=F.getTarget(J),H=I.nodeName.toLowerCase();if((H==="input"||H==="button")&&(I.type&&I.type.toLowerCase()=="submit")){D._submitElementValue=encodeURIComponent(I.name)+"="+encodeURIComponent(I.value);}});return true;}return false;}();function G(T,O,J){var S,I,R,P,W,Q=false,M=[],V=0,L,N,K,U,H;this.resetFormState();if(typeof T=="string"){S=(document.getElementById(T)||document.forms[T]);}else{if(typeof T=="object"){S=T;}else{return;}}if(O){this.createFrame(J?J:null);this._isFormSubmit=true;this._isFileUpload=true;this._formNode=S;return;}for(L=0,N=S.elements.length;L<N;++L){I=S.elements[L];W=I.disabled;R=I.name;if(!W&&R){R=encodeURIComponent(R)+"=";P=encodeURIComponent(I.value);switch(I.type){case"select-one":if(I.selectedIndex>-1){H=I.options[I.selectedIndex];M[V++]=R+encodeURIComponent((H.attributes.value&&H.attributes.value.specified)?H.value:H.text);}break;case"select-multiple":if(I.selectedIndex>-1){for(K=I.selectedIndex,U=I.options.length;K<U;++K){H=I.options[K];if(H.selected){M[V++]=R+encodeURIComponent((H.attributes.value&&H.attributes.value.specified)?H.value:H.text);}}}break;case"radio":case"checkbox":if(I.checked){M[V++]=R+P;}break;case"file":case undefined:case"reset":case"button":break;case"submit":if(Q===false){if(this._hasSubmitListener&&this._submitElementValue){M[V++]=this._submitElementValue;}Q=true;}break;default:M[V++]=R+P;}}}this._isFormSubmit=true;this._sFormData=M.join("&");this.initHeader("Content-Type",this._default_form_header);return this._sFormData;}function C(){this._isFormSubmit=false;this._isFileUpload=false;this._formNode=null;this._sFormData="";}function B(H){var I="yuiIO"+this._transaction_id,J;if(YAHOO.env.ua.ie){J=document.createElement('<iframe id="'+I+'" name="'+I+'" />');if(typeof H=="boolean"){J.src="javascript:false";}}else{J=document.createElement("iframe");J.id=I;J.name=I;}J.style.position="absolute";J.style.top="-1000px";J.style.left="-1000px";document.body.appendChild(J);}function E(H){var K=[],I=H.split("&"),J,L;for(J=0;J<I.length;J++){L=I[J].indexOf("=");if(L!=-1){K[J]=document.createElement("input");K[J].type="hidden";K[J].name=decodeURIComponent(I[J].substring(0,L));K[J].value=decodeURIComponent(I[J].substring(L+1));this._formNode.appendChild(K[J]);}}return K;}function A(K,V,L,J){var Q="yuiIO"+K.tId,R="multipart/form-data",T=document.getElementById(Q),M=(document.documentMode&&document.documentMode===8)?true:false,W=this,S=(V&&V.argument)?V.argument:null,U,P,I,O,H,N;H={action:this._formNode.getAttribute("action"),method:this._formNode.getAttribute("method"),target:this._formNode.getAttribute("target")};this._formNode.setAttribute("action",L);this._formNode.setAttribute("method","POST");this._formNode.setAttribute("target",Q);if(YAHOO.env.ua.ie&&!M){this._formNode.setAttribute("encoding",R);}else{this._formNode.setAttribute("enctype",R);}if(J){U=this.appendPostData(J);}this._formNode.submit();this.startEvent.fire(K,S);if(K.startEvent){K.startEvent.fire(K,S);}if(V&&V.timeout){this._timeOut[K.tId]=window.setTimeout(function(){W.abort(K,V,true);},V.timeout);}if(U&&U.length>0){for(P=0;P<U.length;P++){this._formNode.removeChild(U[P]);}}for(I in H){if(YAHOO.lang.hasOwnProperty(H,I)){if(H[I]){this._formNode.setAttribute(I,H[I]);}else{this._formNode.removeAttribute(I);}}}this.resetFormState();N=function(){if(V&&V.timeout){window.clearTimeout(W._timeOut[K.tId]);delete W._timeOut[K.tId];}W.completeEvent.fire(K,S);if(K.completeEvent){K.completeEvent.fire(K,S);
-}O={tId:K.tId,argument:V.argument};try{O.responseText=T.contentWindow.document.body?T.contentWindow.document.body.innerHTML:T.contentWindow.document.documentElement.textContent;O.responseXML=T.contentWindow.document.XMLDocument?T.contentWindow.document.XMLDocument:T.contentWindow.document;}catch(X){}if(V&&V.upload){if(!V.scope){V.upload(O);}else{V.upload.apply(V.scope,[O]);}}W.uploadEvent.fire(O);if(K.uploadEvent){K.uploadEvent.fire(O);}F.removeListener(T,"load",N);setTimeout(function(){document.body.removeChild(T);W.releaseObject(K);},100);};F.addListener(T,"load",N);}D.setForm=G;D.resetFormState=C;D.createFrame=B;D.appendPostData=E;D.uploadFile=A;})();YAHOO.register("connection",YAHOO.util.Connect,{version:"2.8.2r1",build:"7"});(function(){var B=YAHOO.util;var A=function(D,C,E,F){if(!D){}this.init(D,C,E,F);};A.NAME="Anim";A.prototype={toString:function(){var C=this.getEl()||{};var D=C.id||C.tagName;return(this.constructor.NAME+": "+D);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(C,E,D){return this.method(this.currentFrame,E,D-E,this.totalFrames);},setAttribute:function(C,F,E){var D=this.getEl();if(this.patterns.noNegatives.test(C)){F=(F>0)?F:0;}if(C in D&&!("style" in D&&C in D.style)){D[C]=F;}else{B.Dom.setStyle(D,C,F+E);}},getAttribute:function(C){var E=this.getEl();var G=B.Dom.getStyle(E,C);if(G!=="auto"&&!this.patterns.offsetUnit.test(G)){return parseFloat(G);}var D=this.patterns.offsetAttribute.exec(C)||[];var H=!!(D[3]);var F=!!(D[2]);if("style" in E){if(F||(B.Dom.getStyle(E,"position")=="absolute"&&H)){G=E["offset"+D[0].charAt(0).toUpperCase()+D[0].substr(1)];}else{G=0;}}else{if(C in E){G=E[C];}}return G;},getDefaultUnit:function(C){if(this.patterns.defaultUnit.test(C)){return"px";}return"";},setRuntimeAttribute:function(D){var I;var E;var F=this.attributes;this.runtimeAttributes[D]={};var H=function(J){return(typeof J!=="undefined");};if(!H(F[D]["to"])&&!H(F[D]["by"])){return false;}I=(H(F[D]["from"]))?F[D]["from"]:this.getAttribute(D);if(H(F[D]["to"])){E=F[D]["to"];}else{if(H(F[D]["by"])){if(I.constructor==Array){E=[];for(var G=0,C=I.length;G<C;++G){E[G]=I[G]+F[D]["by"][G]*1;}}else{E=I+F[D]["by"]*1;}}}this.runtimeAttributes[D].start=I;this.runtimeAttributes[D].end=E;this.runtimeAttributes[D].unit=(H(F[D].unit))?F[D]["unit"]:this.getDefaultUnit(D);return true;},init:function(E,J,I,C){var D=false;var F=null;var H=0;E=B.Dom.get(E);this.attributes=J||{};this.duration=!YAHOO.lang.isUndefined(I)?I:1;this.method=C||B.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=B.AnimMgr.fps;this.setEl=function(M){E=B.Dom.get(M);};this.getEl=function(){return E;};this.isAnimated=function(){return D;};this.getStartTime=function(){return F;};this.runtimeAttributes={};this.animate=function(){if(this.isAnimated()){return false;}this.currentFrame=0;this.totalFrames=(this.useSeconds)?Math.ceil(B.AnimMgr.fps*this.duration):this.duration;if(this.duration===0&&this.useSeconds){this.totalFrames=1;}B.AnimMgr.registerElement(this);return true;};this.stop=function(M){if(!this.isAnimated()){return false;}if(M){this.currentFrame=this.totalFrames;this._onTween.fire();}B.AnimMgr.stop(this);};var L=function(){this.onStart.fire();this.runtimeAttributes={};for(var M in this.attributes){this.setRuntimeAttribute(M);}D=true;H=0;F=new Date();};var K=function(){var O={duration:new Date()-this.getStartTime(),currentFrame:this.currentFrame};O.toString=function(){return("duration: "+O.duration+", currentFrame: "+O.currentFrame);};this.onTween.fire(O);var N=this.runtimeAttributes;for(var M in N){this.setAttribute(M,this.doMethod(M,N[M].start,N[M].end),N[M].unit);}H+=1;};var G=function(){var M=(new Date()-F)/1000;var N={duration:M,frames:H,fps:H/M};N.toString=function(){return("duration: "+N.duration+", frames: "+N.frames+", fps: "+N.fps);};D=false;H=0;this.onComplete.fire(N);};this._onStart=new B.CustomEvent("_start",this,true);this.onStart=new B.CustomEvent("start",this);this.onTween=new B.CustomEvent("tween",this);this._onTween=new B.CustomEvent("_tween",this,true);this.onComplete=new B.CustomEvent("complete",this);this._onComplete=new B.CustomEvent("_complete",this,true);this._onStart.subscribe(L);this._onTween.subscribe(K);this._onComplete.subscribe(G);}};B.Anim=A;})();YAHOO.util.AnimMgr=new function(){var C=null;var B=[];var A=0;this.fps=1000;this.delay=1;this.registerElement=function(F){B[B.length]=F;A+=1;F._onStart.fire();this.start();};this.unRegister=function(G,F){F=F||E(G);if(!G.isAnimated()||F===-1){return false;}G._onComplete.fire();B.splice(F,1);A-=1;if(A<=0){this.stop();}return true;};this.start=function(){if(C===null){C=setInterval(this.run,this.delay);}};this.stop=function(H){if(!H){clearInterval(C);for(var G=0,F=B.length;G<F;++G){this.unRegister(B[0],0);}B=[];C=null;A=0;}else{this.unRegister(H);}};this.run=function(){for(var H=0,F=B.length;H<F;++H){var G=B[H];if(!G||!G.isAnimated()){continue;}if(G.currentFrame<G.totalFrames||G.totalFrames===null){G.currentFrame+=1;if(G.useSeconds){D(G);}G._onTween.fire();}else{YAHOO.util.AnimMgr.stop(G,H);}}};var E=function(H){for(var G=0,F=B.length;G<F;++G){if(B[G]===H){return G;}}return -1;};var D=function(G){var J=G.totalFrames;var I=G.currentFrame;var H=(G.currentFrame*G.duration*1000/G.totalFrames);var F=(new Date()-G.getStartTime());var K=0;if(F<G.duration*1000){K=Math.round((F/H-1)*G.currentFrame);}else{K=J-(I+1);}if(K>0&&isFinite(K)){if(G.currentFrame+K>=J){K=J-(I+1);}G.currentFrame+=K;}};this._queue=B;this._getIndex=E;};YAHOO.util.Bezier=new function(){this.getPosition=function(E,D){var F=E.length;var C=[];for(var B=0;B<F;++B){C[B]=[E[B][0],E[B][1]];}for(var A=1;A<F;++A){for(B=0;B<F-A;++B){C[B][0]=(1-D)*C[B][0]+D*C[parseInt(B+1,10)][0];C[B][1]=(1-D)*C[B][1]+D*C[parseInt(B+1,10)][1];}}return[C[0][0],C[0][1]];};};(function(){var A=function(F,E,G,H){A.superclass.constructor.call(this,F,E,G,H);};A.NAME="ColorAnim";A.DEFAULT_BGCOLOR="#fff";var C=YAHOO.util;YAHOO.extend(A,C.Anim);var D=A.superclass;var B=A.prototype;B.patterns.color=/color$/i;B.patterns.rgb=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;B.patterns.hex=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;B.patterns.hex3=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;B.patterns.transparent=/^transparent|rgba\(0, 0, 0, 0\)$/;B.parseColor=function(E){if(E.length==3){return E;}var F=this.patterns.hex.exec(E);if(F&&F.length==4){return[parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16)];}F=this.patterns.rgb.exec(E);if(F&&F.length==4){return[parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10)];}F=this.patterns.hex3.exec(E);if(F&&F.length==4){return[parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16)];
-}return null;};B.getAttribute=function(E){var G=this.getEl();if(this.patterns.color.test(E)){var I=YAHOO.util.Dom.getStyle(G,E);var H=this;if(this.patterns.transparent.test(I)){var F=YAHOO.util.Dom.getAncestorBy(G,function(J){return !H.patterns.transparent.test(I);});if(F){I=C.Dom.getStyle(F,E);}else{I=A.DEFAULT_BGCOLOR;}}}else{I=D.getAttribute.call(this,E);}return I;};B.doMethod=function(F,J,G){var I;if(this.patterns.color.test(F)){I=[];for(var H=0,E=J.length;H<E;++H){I[H]=D.doMethod.call(this,F,J[H],G[H]);}I="rgb("+Math.floor(I[0])+","+Math.floor(I[1])+","+Math.floor(I[2])+")";}else{I=D.doMethod.call(this,F,J,G);}return I;};B.setRuntimeAttribute=function(F){D.setRuntimeAttribute.call(this,F);if(this.patterns.color.test(F)){var H=this.attributes;var J=this.parseColor(this.runtimeAttributes[F].start);var G=this.parseColor(this.runtimeAttributes[F].end);if(typeof H[F]["to"]==="undefined"&&typeof H[F]["by"]!=="undefined"){G=this.parseColor(H[F].by);for(var I=0,E=J.length;I<E;++I){G[I]=J[I]+G[I];}}this.runtimeAttributes[F].start=J;this.runtimeAttributes[F].end=G;}};C.ColorAnim=A;})();
-/*
-TERMS OF USE - EASING EQUATIONS
-Open source under the BSD License.
-Copyright 2001 Robert Penner All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-YAHOO.util.Easing={easeNone:function(B,A,D,C){return D*B/C+A;},easeIn:function(B,A,D,C){return D*(B/=C)*B+A;},easeOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A;},easeBoth:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B+A;}return -D/2*((--B)*(B-2)-1)+A;},easeInStrong:function(B,A,D,C){return D*(B/=C)*B*B*B+A;},easeOutStrong:function(B,A,D,C){return -D*((B=B/C-1)*B*B*B-1)+A;},easeBothStrong:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B+A;}return -D/2*((B-=2)*B*B*B-2)+A;},elasticIn:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return -(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;},elasticOut:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return B*Math.pow(2,-10*C)*Math.sin((C*F-D)*(2*Math.PI)/E)+G+A;},elasticBoth:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F/2)==2){return A+G;}if(!E){E=F*(0.3*1.5);}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}if(C<1){return -0.5*(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;}return B*Math.pow(2,-10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E)*0.5+G+A;},backIn:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*(B/=D)*B*((C+1)*B-C)+A;},backOut:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*((B=B/D-1)*B*((C+1)*B+C)+1)+A;},backBoth:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}if((B/=D/2)<1){return E/2*(B*B*(((C*=(1.525))+1)*B-C))+A;}return E/2*((B-=2)*B*(((C*=(1.525))+1)*B+C)+2)+A;},bounceIn:function(B,A,D,C){return D-YAHOO.util.Easing.bounceOut(C-B,0,D,C)+A;},bounceOut:function(B,A,D,C){if((B/=C)<(1/2.75)){return D*(7.5625*B*B)+A;}else{if(B<(2/2.75)){return D*(7.5625*(B-=(1.5/2.75))*B+0.75)+A;}else{if(B<(2.5/2.75)){return D*(7.5625*(B-=(2.25/2.75))*B+0.9375)+A;}}}return D*(7.5625*(B-=(2.625/2.75))*B+0.984375)+A;},bounceBoth:function(B,A,D,C){if(B<C/2){return YAHOO.util.Easing.bounceIn(B*2,0,D,C)*0.5+A;}return YAHOO.util.Easing.bounceOut(B*2-C,0,D,C)*0.5+D*0.5+A;}};(function(){var A=function(H,G,I,J){if(H){A.superclass.constructor.call(this,H,G,I,J);}};A.NAME="Motion";var E=YAHOO.util;YAHOO.extend(A,E.ColorAnim);var F=A.superclass;var C=A.prototype;C.patterns.points=/^points$/i;C.setAttribute=function(G,I,H){if(this.patterns.points.test(G)){H=H||"px";F.setAttribute.call(this,"left",I[0],H);F.setAttribute.call(this,"top",I[1],H);}else{F.setAttribute.call(this,G,I,H);}};C.getAttribute=function(G){if(this.patterns.points.test(G)){var H=[F.getAttribute.call(this,"left"),F.getAttribute.call(this,"top")];}else{H=F.getAttribute.call(this,G);}return H;};C.doMethod=function(G,K,H){var J=null;if(this.patterns.points.test(G)){var I=this.method(this.currentFrame,0,100,this.totalFrames)/100;J=E.Bezier.getPosition(this.runtimeAttributes[G],I);}else{J=F.doMethod.call(this,G,K,H);}return J;};C.setRuntimeAttribute=function(P){if(this.patterns.points.test(P)){var H=this.getEl();var J=this.attributes;var G;var L=J["points"]["control"]||[];var I;var M,O;if(L.length>0&&!(L[0] instanceof Array)){L=[L];}else{var K=[];for(M=0,O=L.length;M<O;++M){K[M]=L[M];}L=K;}if(E.Dom.getStyle(H,"position")=="static"){E.Dom.setStyle(H,"position","relative");}if(D(J["points"]["from"])){E.Dom.setXY(H,J["points"]["from"]);
-}else{E.Dom.setXY(H,E.Dom.getXY(H));}G=this.getAttribute("points");if(D(J["points"]["to"])){I=B.call(this,J["points"]["to"],G);var N=E.Dom.getXY(this.getEl());for(M=0,O=L.length;M<O;++M){L[M]=B.call(this,L[M],G);}}else{if(D(J["points"]["by"])){I=[G[0]+J["points"]["by"][0],G[1]+J["points"]["by"][1]];for(M=0,O=L.length;M<O;++M){L[M]=[G[0]+L[M][0],G[1]+L[M][1]];}}}this.runtimeAttributes[P]=[G];if(L.length>0){this.runtimeAttributes[P]=this.runtimeAttributes[P].concat(L);}this.runtimeAttributes[P][this.runtimeAttributes[P].length]=I;}else{F.setRuntimeAttribute.call(this,P);}};var B=function(G,I){var H=E.Dom.getXY(this.getEl());G=[G[0]-H[0]+I[0],G[1]-H[1]+I[1]];return G;};var D=function(G){return(typeof G!=="undefined");};E.Motion=A;})();(function(){var D=function(F,E,G,H){if(F){D.superclass.constructor.call(this,F,E,G,H);}};D.NAME="Scroll";var B=YAHOO.util;YAHOO.extend(D,B.ColorAnim);var C=D.superclass;var A=D.prototype;A.doMethod=function(E,H,F){var G=null;if(E=="scroll"){G=[this.method(this.currentFrame,H[0],F[0]-H[0],this.totalFrames),this.method(this.currentFrame,H[1],F[1]-H[1],this.totalFrames)];}else{G=C.doMethod.call(this,E,H,F);}return G;};A.getAttribute=function(E){var G=null;var F=this.getEl();if(E=="scroll"){G=[F.scrollLeft,F.scrollTop];}else{G=C.getAttribute.call(this,E);}return G;};A.setAttribute=function(E,H,G){var F=this.getEl();if(E=="scroll"){F.scrollLeft=H[0];F.scrollTop=H[1];}else{C.setAttribute.call(this,E,H,G);}};B.Scroll=D;})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.8.2r1",build:"7"});if(!YAHOO.util.DragDropMgr){YAHOO.util.DragDropMgr=function(){var A=YAHOO.util.Event,B=YAHOO.util.Dom;return{useShim:false,_shimActive:false,_shimState:false,_debugShim:false,_createShim:function(){var C=document.createElement("div");C.id="yui-ddm-shim";if(document.body.firstChild){document.body.insertBefore(C,document.body.firstChild);}else{document.body.appendChild(C);}C.style.display="none";C.style.backgroundColor="red";C.style.position="absolute";C.style.zIndex="99999";B.setStyle(C,"opacity","0");this._shim=C;A.on(C,"mouseup",this.handleMouseUp,this,true);A.on(C,"mousemove",this.handleMouseMove,this,true);A.on(window,"scroll",this._sizeShim,this,true);},_sizeShim:function(){if(this._shimActive){var C=this._shim;C.style.height=B.getDocumentHeight()+"px";C.style.width=B.getDocumentWidth()+"px";C.style.top="0";C.style.left="0";}},_activateShim:function(){if(this.useShim){if(!this._shim){this._createShim();}this._shimActive=true;var C=this._shim,D="0";if(this._debugShim){D=".5";}B.setStyle(C,"opacity",D);this._sizeShim();C.style.display="block";}},_deactivateShim:function(){this._shim.style.display="none";this._shimActive=false;},_shim:null,ids:{},handleIds:{},dragCurrent:null,dragOvers:{},deltaX:0,deltaY:0,preventDefault:true,stopPropagation:true,initialized:false,locked:false,interactionInfo:null,init:function(){this.initialized=true;},POINT:0,INTERSECT:1,STRICT_INTERSECT:2,mode:0,_execOnAll:function(E,D){for(var F in this.ids){for(var C in this.ids[F]){var G=this.ids[F][C];if(!this.isTypeOfDD(G)){continue;}G[E].apply(G,D);}}},_onLoad:function(){this.init();A.on(document,"mouseup",this.handleMouseUp,this,true);A.on(document,"mousemove",this.handleMouseMove,this,true);A.on(window,"unload",this._onUnload,this,true);A.on(window,"resize",this._onResize,this,true);},_onResize:function(C){this._execOnAll("resetConstraints",[]);},lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isLocked:function(){return this.locked;},locationCache:{},useCache:true,clickPixelThresh:3,clickTimeThresh:1000,dragThreshMet:false,clickTimeout:null,startX:0,startY:0,fromTimeout:false,regDragDrop:function(D,C){if(!this.initialized){this.init();}if(!this.ids[C]){this.ids[C]={};}this.ids[C][D.id]=D;},removeDDFromGroup:function(E,C){if(!this.ids[C]){this.ids[C]={};}var D=this.ids[C];if(D&&D[E.id]){delete D[E.id];}},_remove:function(E){for(var D in E.groups){if(D){var C=this.ids[D];if(C&&C[E.id]){delete C[E.id];}}}delete this.handleIds[E.id];},regHandle:function(D,C){if(!this.handleIds[D]){this.handleIds[D]={};}this.handleIds[D][C]=C;},isDragDrop:function(C){return(this.getDDById(C))?true:false;},getRelated:function(H,D){var G=[];for(var F in H.groups){for(var E in this.ids[F]){var C=this.ids[F][E];if(!this.isTypeOfDD(C)){continue;}if(!D||C.isTarget){G[G.length]=C;}}}return G;},isLegalTarget:function(G,F){var D=this.getRelated(G,true);for(var E=0,C=D.length;E<C;++E){if(D[E].id==F.id){return true;}}return false;},isTypeOfDD:function(C){return(C&&C.__ygDragDrop);},isHandle:function(D,C){return(this.handleIds[D]&&this.handleIds[D][C]);},getDDById:function(D){for(var C in this.ids){if(this.ids[C][D]){return this.ids[C][D];}}return null;},handleMouseDown:function(E,D){this.currentTarget=YAHOO.util.Event.getTarget(E);this.dragCurrent=D;var C=D.getEl();this.startX=YAHOO.util.Event.getPageX(E);this.startY=YAHOO.util.Event.getPageY(E);this.deltaX=this.startX-C.offsetLeft;this.deltaY=this.startY-C.offsetTop;this.dragThreshMet=false;this.clickTimeout=setTimeout(function(){var F=YAHOO.util.DDM;F.startDrag(F.startX,F.startY);F.fromTimeout=true;},this.clickTimeThresh);},startDrag:function(C,E){if(this.dragCurrent&&this.dragCurrent.useShim){this._shimState=this.useShim;this.useShim=true;}this._activateShim();clearTimeout(this.clickTimeout);var D=this.dragCurrent;if(D&&D.events.b4StartDrag){D.b4StartDrag(C,E);D.fireEvent("b4StartDragEvent",{x:C,y:E});}if(D&&D.events.startDrag){D.startDrag(C,E);D.fireEvent("startDragEvent",{x:C,y:E});}this.dragThreshMet=true;},handleMouseUp:function(C){if(this.dragCurrent){clearTimeout(this.clickTimeout);if(this.dragThreshMet){if(this.fromTimeout){this.fromTimeout=false;this.handleMouseMove(C);}this.fromTimeout=false;this.fireEvents(C,true);}else{}this.stopDrag(C);this.stopEvent(C);}},stopEvent:function(C){if(this.stopPropagation){YAHOO.util.Event.stopPropagation(C);}if(this.preventDefault){YAHOO.util.Event.preventDefault(C);}},stopDrag:function(E,D){var C=this.dragCurrent;if(C&&!D){if(this.dragThreshMet){if(C.events.b4EndDrag){C.b4EndDrag(E);C.fireEvent("b4EndDragEvent",{e:E});}if(C.events.endDrag){C.endDrag(E);C.fireEvent("endDragEvent",{e:E});}}if(C.events.mouseUp){C.onMouseUp(E);C.fireEvent("mouseUpEvent",{e:E});}}if(this._shimActive){this._deactivateShim();if(this.dragCurrent&&this.dragCurrent.useShim){this.useShim=this._shimState;this._shimState=false;}}this.dragCurrent=null;this.dragOvers={};},handleMouseMove:function(F){var C=this.dragCurrent;if(C){if(YAHOO.util.Event.isIE&&!F.button){this.stopEvent(F);return this.handleMouseUp(F);}else{if(F.clientX<0||F.clientY<0){}}if(!this.dragThreshMet){var E=Math.abs(this.startX-YAHOO.util.Event.getPageX(F));var D=Math.abs(this.startY-YAHOO.util.Event.getPageY(F));if(E>this.clickPixelThresh||D>this.clickPixelThresh){this.startDrag(this.startX,this.startY);}}if(this.dragThreshMet){if(C&&C.events.b4Drag){C.b4Drag(F);C.fireEvent("b4DragEvent",{e:F});}if(C&&C.events.drag){C.onDrag(F);C.fireEvent("dragEvent",{e:F});}if(C){this.fireEvents(F,false);}}this.stopEvent(F);}},fireEvents:function(V,L){var a=this.dragCurrent;if(!a||a.isLocked()||a.dragOnly){return;}var N=YAHOO.util.Event.getPageX(V),M=YAHOO.util.Event.getPageY(V),P=new YAHOO.util.Point(N,M),K=a.getTargetCoord(P.x,P.y),F=a.getDragEl(),E=["out","over","drop","enter"],U=new YAHOO.util.Region(K.y,K.x+F.offsetWidth,K.y+F.offsetHeight,K.x),I=[],D={},Q=[],c={outEvts:[],overEvts:[],dropEvts:[],enterEvts:[]};for(var S in this.dragOvers){var d=this.dragOvers[S];if(!this.isTypeOfDD(d)){continue;
-}if(!this.isOverTarget(P,d,this.mode,U)){c.outEvts.push(d);}I[S]=true;delete this.dragOvers[S];}for(var R in a.groups){if("string"!=typeof R){continue;}for(S in this.ids[R]){var G=this.ids[R][S];if(!this.isTypeOfDD(G)){continue;}if(G.isTarget&&!G.isLocked()&&G!=a){if(this.isOverTarget(P,G,this.mode,U)){D[R]=true;if(L){c.dropEvts.push(G);}else{if(!I[G.id]){c.enterEvts.push(G);}else{c.overEvts.push(G);}this.dragOvers[G.id]=G;}}}}}this.interactionInfo={out:c.outEvts,enter:c.enterEvts,over:c.overEvts,drop:c.dropEvts,point:P,draggedRegion:U,sourceRegion:this.locationCache[a.id],validDrop:L};for(var C in D){Q.push(C);}if(L&&!c.dropEvts.length){this.interactionInfo.validDrop=false;if(a.events.invalidDrop){a.onInvalidDrop(V);a.fireEvent("invalidDropEvent",{e:V});}}for(S=0;S<E.length;S++){var Y=null;if(c[E[S]+"Evts"]){Y=c[E[S]+"Evts"];}if(Y&&Y.length){var H=E[S].charAt(0).toUpperCase()+E[S].substr(1),X="onDrag"+H,J="b4Drag"+H,O="drag"+H+"Event",W="drag"+H;if(this.mode){if(a.events[J]){a[J](V,Y,Q);a.fireEvent(J+"Event",{event:V,info:Y,group:Q});}if(a.events[W]){a[X](V,Y,Q);a.fireEvent(O,{event:V,info:Y,group:Q});}}else{for(var Z=0,T=Y.length;Z<T;++Z){if(a.events[J]){a[J](V,Y[Z].id,Q[0]);a.fireEvent(J+"Event",{event:V,info:Y[Z].id,group:Q[0]});}if(a.events[W]){a[X](V,Y[Z].id,Q[0]);a.fireEvent(O,{event:V,info:Y[Z].id,group:Q[0]});}}}}}},getBestMatch:function(E){var G=null;var D=E.length;if(D==1){G=E[0];}else{for(var F=0;F<D;++F){var C=E[F];if(this.mode==this.INTERSECT&&C.cursorIsOver){G=C;break;}else{if(!G||!G.overlap||(C.overlap&&G.overlap.getArea()<C.overlap.getArea())){G=C;}}}}return G;},refreshCache:function(D){var F=D||this.ids;for(var C in F){if("string"!=typeof C){continue;}for(var E in this.ids[C]){var G=this.ids[C][E];if(this.isTypeOfDD(G)){var H=this.getLocation(G);if(H){this.locationCache[G.id]=H;}else{delete this.locationCache[G.id];}}}}},verifyEl:function(D){try{if(D){var C=D.offsetParent;if(C){return true;}}}catch(E){}return false;},getLocation:function(H){if(!this.isTypeOfDD(H)){return null;}var F=H.getEl(),K,E,D,M,L,N,C,J,G;try{K=YAHOO.util.Dom.getXY(F);}catch(I){}if(!K){return null;}E=K[0];D=E+F.offsetWidth;M=K[1];L=M+F.offsetHeight;N=M-H.padding[0];C=D+H.padding[1];J=L+H.padding[2];G=E-H.padding[3];return new YAHOO.util.Region(N,C,J,G);},isOverTarget:function(K,C,E,F){var G=this.locationCache[C.id];if(!G||!this.useCache){G=this.getLocation(C);this.locationCache[C.id]=G;}if(!G){return false;}C.cursorIsOver=G.contains(K);var J=this.dragCurrent;if(!J||(!E&&!J.constrainX&&!J.constrainY)){return C.cursorIsOver;}C.overlap=null;if(!F){var H=J.getTargetCoord(K.x,K.y);var D=J.getDragEl();F=new YAHOO.util.Region(H.y,H.x+D.offsetWidth,H.y+D.offsetHeight,H.x);}var I=F.intersect(G);if(I){C.overlap=I;return(E)?true:C.cursorIsOver;}else{return false;}},_onUnload:function(D,C){this.unregAll();},unregAll:function(){if(this.dragCurrent){this.stopDrag();this.dragCurrent=null;}this._execOnAll("unreg",[]);this.ids={};},elementCache:{},getElWrapper:function(D){var C=this.elementCache[D];if(!C||!C.el){C=this.elementCache[D]=new this.ElementWrapper(YAHOO.util.Dom.get(D));}return C;},getElement:function(C){return YAHOO.util.Dom.get(C);},getCss:function(D){var C=YAHOO.util.Dom.get(D);return(C)?C.style:null;},ElementWrapper:function(C){this.el=C||null;this.id=this.el&&C.id;this.css=this.el&&C.style;},getPosX:function(C){return YAHOO.util.Dom.getX(C);},getPosY:function(C){return YAHOO.util.Dom.getY(C);},swapNode:function(E,C){if(E.swapNode){E.swapNode(C);}else{var F=C.parentNode;var D=C.nextSibling;if(D==E){F.insertBefore(E,C);}else{if(C==E.nextSibling){F.insertBefore(C,E);}else{E.parentNode.replaceChild(C,E);F.insertBefore(E,D);}}}},getScroll:function(){var E,C,F=document.documentElement,D=document.body;if(F&&(F.scrollTop||F.scrollLeft)){E=F.scrollTop;C=F.scrollLeft;}else{if(D){E=D.scrollTop;C=D.scrollLeft;}else{}}return{top:E,left:C};},getStyle:function(D,C){return YAHOO.util.Dom.getStyle(D,C);},getScrollTop:function(){return this.getScroll().top;},getScrollLeft:function(){return this.getScroll().left;},moveToEl:function(C,E){var D=YAHOO.util.Dom.getXY(E);YAHOO.util.Dom.setXY(C,D);},getClientHeight:function(){return YAHOO.util.Dom.getViewportHeight();},getClientWidth:function(){return YAHOO.util.Dom.getViewportWidth();},numericSort:function(D,C){return(D-C);},_timeoutCount:0,_addListeners:function(){var C=YAHOO.util.DDM;if(YAHOO.util.Event&&document){C._onLoad();}else{if(C._timeoutCount>2000){}else{setTimeout(C._addListeners,10);if(document&&document.body){C._timeoutCount+=1;}}}},handleWasClicked:function(C,E){if(this.isHandle(E,C.id)){return true;}else{var D=C.parentNode;while(D){if(this.isHandle(E,D.id)){return true;}else{D=D.parentNode;}}}return false;}};}();YAHOO.util.DDM=YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function(){var A=YAHOO.util.Event;var B=YAHOO.util.Dom;YAHOO.util.DragDrop=function(E,C,D){if(E){this.init(E,C,D);}};YAHOO.util.DragDrop.prototype={events:null,on:function(){this.subscribe.apply(this,arguments);},id:null,config:null,dragElId:null,handleElId:null,invalidHandleTypes:null,invalidHandleIds:null,invalidHandleClasses:null,startPageX:0,startPageY:0,groups:null,locked:false,lock:function(){this.locked=true;},unlock:function(){this.locked=false;},isTarget:true,padding:null,dragOnly:false,useShim:false,_domRef:null,__ygDragDrop:true,constrainX:false,constrainY:false,minX:0,maxX:0,minY:0,maxY:0,deltaX:0,deltaY:0,maintainOffset:false,xTicks:null,yTicks:null,primaryButtonOnly:true,available:false,hasOuterHandles:false,cursorIsOver:false,overlap:null,b4StartDrag:function(C,D){},startDrag:function(C,D){},b4Drag:function(C){},onDrag:function(C){},onDragEnter:function(C,D){},b4DragOver:function(C){},onDragOver:function(C,D){},b4DragOut:function(C){},onDragOut:function(C,D){},b4DragDrop:function(C){},onDragDrop:function(C,D){},onInvalidDrop:function(C){},b4EndDrag:function(C){},endDrag:function(C){},b4MouseDown:function(C){},onMouseDown:function(C){},onMouseUp:function(C){},onAvailable:function(){},getEl:function(){if(!this._domRef){this._domRef=B.get(this.id);
-}return this._domRef;},getDragEl:function(){return B.get(this.dragElId);},init:function(F,C,D){this.initTarget(F,C,D);A.on(this._domRef||this.id,"mousedown",this.handleMouseDown,this,true);for(var E in this.events){this.createEvent(E+"Event");}},initTarget:function(E,C,D){this.config=D||{};this.events={};this.DDM=YAHOO.util.DDM;this.groups={};if(typeof E!=="string"){this._domRef=E;E=B.generateId(E);}this.id=E;this.addToGroup((C)?C:"default");this.handleElId=E;A.onAvailable(E,this.handleOnAvailable,this,true);this.setDragElId(E);this.invalidHandleTypes={A:"A"};this.invalidHandleIds={};this.invalidHandleClasses=[];this.applyConfig();},applyConfig:function(){this.events={mouseDown:true,b4MouseDown:true,mouseUp:true,b4StartDrag:true,startDrag:true,b4EndDrag:true,endDrag:true,drag:true,b4Drag:true,invalidDrop:true,b4DragOut:true,dragOut:true,dragEnter:true,b4DragOver:true,dragOver:true,b4DragDrop:true,dragDrop:true};if(this.config.events){for(var C in this.config.events){if(this.config.events[C]===false){this.events[C]=false;}}}this.padding=this.config.padding||[0,0,0,0];this.isTarget=(this.config.isTarget!==false);this.maintainOffset=(this.config.maintainOffset);this.primaryButtonOnly=(this.config.primaryButtonOnly!==false);this.dragOnly=((this.config.dragOnly===true)?true:false);this.useShim=((this.config.useShim===true)?true:false);},handleOnAvailable:function(){this.available=true;this.resetConstraints();this.onAvailable();},setPadding:function(E,C,F,D){if(!C&&0!==C){this.padding=[E,E,E,E];}else{if(!F&&0!==F){this.padding=[E,C,E,C];}else{this.padding=[E,C,F,D];}}},setInitPosition:function(F,E){var G=this.getEl();if(!this.DDM.verifyEl(G)){if(G&&G.style&&(G.style.display=="none")){}else{}return;}var D=F||0;var C=E||0;var H=B.getXY(G);this.initPageX=H[0]-D;this.initPageY=H[1]-C;this.lastPageX=H[0];this.lastPageY=H[1];this.setStartPosition(H);},setStartPosition:function(D){var C=D||B.getXY(this.getEl());this.deltaSetXY=null;this.startPageX=C[0];this.startPageY=C[1];},addToGroup:function(C){this.groups[C]=true;this.DDM.regDragDrop(this,C);},removeFromGroup:function(C){if(this.groups[C]){delete this.groups[C];}this.DDM.removeDDFromGroup(this,C);},setDragElId:function(C){this.dragElId=C;},setHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.handleElId=C;this.DDM.regHandle(this.id,C);},setOuterHandleElId:function(C){if(typeof C!=="string"){C=B.generateId(C);}A.on(C,"mousedown",this.handleMouseDown,this,true);this.setHandleElId(C);this.hasOuterHandles=true;},unreg:function(){A.removeListener(this.id,"mousedown",this.handleMouseDown);this._domRef=null;this.DDM._remove(this);},isLocked:function(){return(this.DDM.isLocked()||this.locked);},handleMouseDown:function(J,I){var D=J.which||J.button;if(this.primaryButtonOnly&&D>1){return;}if(this.isLocked()){return;}var C=this.b4MouseDown(J),F=true;if(this.events.b4MouseDown){F=this.fireEvent("b4MouseDownEvent",J);}var E=this.onMouseDown(J),H=true;if(this.events.mouseDown){H=this.fireEvent("mouseDownEvent",J);}if((C===false)||(E===false)||(F===false)||(H===false)){return;}this.DDM.refreshCache(this.groups);var G=new YAHOO.util.Point(A.getPageX(J),A.getPageY(J));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(G,this)){}else{if(this.clickValidator(J)){this.setStartPosition();this.DDM.handleMouseDown(J,this);this.DDM.stopEvent(J);}else{}}},clickValidator:function(D){var C=YAHOO.util.Event.getTarget(D);return(this.isValidHandleChild(C)&&(this.id==this.handleElId||this.DDM.handleWasClicked(C,this.id)));},getTargetCoord:function(E,D){var C=E-this.deltaX;var F=D-this.deltaY;if(this.constrainX){if(C<this.minX){C=this.minX;}if(C>this.maxX){C=this.maxX;}}if(this.constrainY){if(F<this.minY){F=this.minY;}if(F>this.maxY){F=this.maxY;}}C=this.getTick(C,this.xTicks);F=this.getTick(F,this.yTicks);return{x:C,y:F};},addInvalidHandleType:function(C){var D=C.toUpperCase();this.invalidHandleTypes[D]=D;},addInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}this.invalidHandleIds[C]=C;},addInvalidHandleClass:function(C){this.invalidHandleClasses.push(C);},removeInvalidHandleType:function(C){var D=C.toUpperCase();delete this.invalidHandleTypes[D];},removeInvalidHandleId:function(C){if(typeof C!=="string"){C=B.generateId(C);}delete this.invalidHandleIds[C];},removeInvalidHandleClass:function(D){for(var E=0,C=this.invalidHandleClasses.length;E<C;++E){if(this.invalidHandleClasses[E]==D){delete this.invalidHandleClasses[E];}}},isValidHandleChild:function(F){var E=true;var H;try{H=F.nodeName.toUpperCase();}catch(G){H=F.nodeName;}E=E&&!this.invalidHandleTypes[H];E=E&&!this.invalidHandleIds[F.id];for(var D=0,C=this.invalidHandleClasses.length;E&&D<C;++D){E=!B.hasClass(F,this.invalidHandleClasses[D]);}return E;},setXTicks:function(F,C){this.xTicks=[];this.xTickSize=C;var E={};for(var D=this.initPageX;D>=this.minX;D=D-C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}for(D=this.initPageX;D<=this.maxX;D=D+C){if(!E[D]){this.xTicks[this.xTicks.length]=D;E[D]=true;}}this.xTicks.sort(this.DDM.numericSort);},setYTicks:function(F,C){this.yTicks=[];this.yTickSize=C;var E={};for(var D=this.initPageY;D>=this.minY;D=D-C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}for(D=this.initPageY;D<=this.maxY;D=D+C){if(!E[D]){this.yTicks[this.yTicks.length]=D;E[D]=true;}}this.yTicks.sort(this.DDM.numericSort);},setXConstraint:function(E,D,C){this.leftConstraint=parseInt(E,10);this.rightConstraint=parseInt(D,10);this.minX=this.initPageX-this.leftConstraint;this.maxX=this.initPageX+this.rightConstraint;if(C){this.setXTicks(this.initPageX,C);}this.constrainX=true;},clearConstraints:function(){this.constrainX=false;this.constrainY=false;this.clearTicks();},clearTicks:function(){this.xTicks=null;this.yTicks=null;this.xTickSize=0;this.yTickSize=0;},setYConstraint:function(C,E,D){this.topConstraint=parseInt(C,10);this.bottomConstraint=parseInt(E,10);this.minY=this.initPageY-this.topConstraint;this.maxY=this.initPageY+this.bottomConstraint;if(D){this.setYTicks(this.initPageY,D);
-}this.constrainY=true;},resetConstraints:function(){if(this.initPageX||this.initPageX===0){var D=(this.maintainOffset)?this.lastPageX-this.initPageX:0;var C=(this.maintainOffset)?this.lastPageY-this.initPageY:0;this.setInitPosition(D,C);}else{this.setInitPosition();}if(this.constrainX){this.setXConstraint(this.leftConstraint,this.rightConstraint,this.xTickSize);}if(this.constrainY){this.setYConstraint(this.topConstraint,this.bottomConstraint,this.yTickSize);}},getTick:function(I,F){if(!F){return I;}else{if(F[0]>=I){return F[0];}else{for(var D=0,C=F.length;D<C;++D){var E=D+1;if(F[E]&&F[E]>=I){var H=I-F[D];var G=F[E]-I;return(G>H)?F[D]:F[E];}}return F[F.length-1];}}},toString:function(){return("DragDrop "+this.id);}};YAHOO.augment(YAHOO.util.DragDrop,YAHOO.util.EventProvider);})();YAHOO.util.DD=function(C,A,B){if(C){this.init(C,A,B);}};YAHOO.extend(YAHOO.util.DD,YAHOO.util.DragDrop,{scroll:true,autoOffset:function(C,B){var A=C-this.startPageX;var D=B-this.startPageY;this.setDelta(A,D);},setDelta:function(B,A){this.deltaX=B;this.deltaY=A;},setDragElPos:function(C,B){var A=this.getDragEl();this.alignElWithMouse(A,C,B);},alignElWithMouse:function(C,G,F){var E=this.getTargetCoord(G,F);if(!this.deltaSetXY){var H=[E.x,E.y];YAHOO.util.Dom.setXY(C,H);var D=parseInt(YAHOO.util.Dom.getStyle(C,"left"),10);var B=parseInt(YAHOO.util.Dom.getStyle(C,"top"),10);this.deltaSetXY=[D-E.x,B-E.y];}else{YAHOO.util.Dom.setStyle(C,"left",(E.x+this.deltaSetXY[0])+"px");YAHOO.util.Dom.setStyle(C,"top",(E.y+this.deltaSetXY[1])+"px");}this.cachePosition(E.x,E.y);var A=this;setTimeout(function(){A.autoScroll.call(A,E.x,E.y,C.offsetHeight,C.offsetWidth);},0);},cachePosition:function(B,A){if(B){this.lastPageX=B;this.lastPageY=A;}else{var C=YAHOO.util.Dom.getXY(this.getEl());this.lastPageX=C[0];this.lastPageY=C[1];}},autoScroll:function(J,I,E,K){if(this.scroll){var L=this.DDM.getClientHeight();var B=this.DDM.getClientWidth();var N=this.DDM.getScrollTop();var D=this.DDM.getScrollLeft();var H=E+I;var M=K+J;var G=(L+N-I-this.deltaY);var F=(B+D-J-this.deltaX);var C=40;var A=(document.all)?80:30;if(H>L&&G<C){window.scrollTo(D,N+A);}if(I<N&&N>0&&I-N<C){window.scrollTo(D,N-A);}if(M>B&&F<C){window.scrollTo(D+A,N);}if(J<D&&D>0&&J-D<C){window.scrollTo(D-A,N);}}},applyConfig:function(){YAHOO.util.DD.superclass.applyConfig.call(this);this.scroll=(this.config.scroll!==false);},b4MouseDown:function(A){this.setStartPosition();this.autoOffset(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},b4Drag:function(A){this.setDragElPos(YAHOO.util.Event.getPageX(A),YAHOO.util.Event.getPageY(A));},toString:function(){return("DD "+this.id);}});YAHOO.util.DDProxy=function(C,A,B){if(C){this.init(C,A,B);this.initFrame();}};YAHOO.util.DDProxy.dragElId="ygddfdiv";YAHOO.extend(YAHOO.util.DDProxy,YAHOO.util.DD,{resizeFrame:true,centerFrame:false,createFrame:function(){var B=this,A=document.body;if(!A||!A.firstChild){setTimeout(function(){B.createFrame();},50);return;}var F=this.getDragEl(),E=YAHOO.util.Dom;if(!F){F=document.createElement("div");F.id=this.dragElId;var D=F.style;D.position="absolute";D.visibility="hidden";D.cursor="move";D.border="2px solid #aaa";D.zIndex=999;D.height="25px";D.width="25px";var C=document.createElement("div");E.setStyle(C,"height","100%");E.setStyle(C,"width","100%");E.setStyle(C,"background-color","#ccc");E.setStyle(C,"opacity","0");F.appendChild(C);A.insertBefore(F,A.firstChild);}},initFrame:function(){this.createFrame();},applyConfig:function(){YAHOO.util.DDProxy.superclass.applyConfig.call(this);this.resizeFrame=(this.config.resizeFrame!==false);this.centerFrame=(this.config.centerFrame);this.setDragElId(this.config.dragElId||YAHOO.util.DDProxy.dragElId);},showFrame:function(E,D){var C=this.getEl();var A=this.getDragEl();var B=A.style;this._resizeProxy();if(this.centerFrame){this.setDelta(Math.round(parseInt(B.width,10)/2),Math.round(parseInt(B.height,10)/2));}this.setDragElPos(E,D);YAHOO.util.Dom.setStyle(A,"visibility","visible");},_resizeProxy:function(){if(this.resizeFrame){var H=YAHOO.util.Dom;var B=this.getEl();var C=this.getDragEl();var G=parseInt(H.getStyle(C,"borderTopWidth"),10);var I=parseInt(H.getStyle(C,"borderRightWidth"),10);var F=parseInt(H.getStyle(C,"borderBottomWidth"),10);var D=parseInt(H.getStyle(C,"borderLeftWidth"),10);if(isNaN(G)){G=0;}if(isNaN(I)){I=0;}if(isNaN(F)){F=0;}if(isNaN(D)){D=0;}var E=Math.max(0,B.offsetWidth-I-D);var A=Math.max(0,B.offsetHeight-G-F);H.setStyle(C,"width",E+"px");H.setStyle(C,"height",A+"px");}},b4MouseDown:function(B){this.setStartPosition();var A=YAHOO.util.Event.getPageX(B);var C=YAHOO.util.Event.getPageY(B);this.autoOffset(A,C);},b4StartDrag:function(A,B){this.showFrame(A,B);},b4EndDrag:function(A){YAHOO.util.Dom.setStyle(this.getDragEl(),"visibility","hidden");},endDrag:function(D){var C=YAHOO.util.Dom;var B=this.getEl();var A=this.getDragEl();C.setStyle(A,"visibility","");C.setStyle(B,"visibility","hidden");YAHOO.util.DDM.moveToEl(B,A);C.setStyle(A,"visibility","hidden");C.setStyle(B,"visibility","");},toString:function(){return("DDProxy "+this.id);}});YAHOO.util.DDTarget=function(C,A,B){if(C){this.initTarget(C,A,B);}};YAHOO.extend(YAHOO.util.DDTarget,YAHOO.util.DragDrop,{toString:function(){return("DDTarget "+this.id);}});YAHOO.register("dragdrop",YAHOO.util.DragDropMgr,{version:"2.8.2r1",build:"7"});YAHOO.util.Attribute=function(B,A){if(A){this.owner=A;this.configure(B,true);}};YAHOO.util.Attribute.prototype={name:undefined,value:null,owner:null,readOnly:false,writeOnce:false,_initialConfig:null,_written:false,method:null,setter:null,getter:null,validator:null,getValue:function(){var A=this.value;if(this.getter){A=this.getter.call(this.owner,this.name,A);}return A;},setValue:function(F,B){var E,A=this.owner,C=this.name;var D={type:C,prevValue:this.getValue(),newValue:F};if(this.readOnly||(this.writeOnce&&this._written)){return false;}if(this.validator&&!this.validator.call(A,F)){return false;}if(!B){E=A.fireBeforeChangeEvent(D);if(E===false){return false;}}if(this.setter){F=this.setter.call(A,F,this.name);if(F===undefined){}}if(this.method){this.method.call(A,F,this.name);}this.value=F;this._written=true;D.type=C;if(!B){this.owner.fireChangeEvent(D);}return true;},configure:function(B,C){B=B||{};if(C){this._written=false;}this._initialConfig=this._initialConfig||{};for(var A in B){if(B.hasOwnProperty(A)){this[A]=B[A];if(C){this._initialConfig[A]=B[A];}}}},resetValue:function(){return this.setValue(this._initialConfig.value);},resetConfig:function(){this.configure(this._initialConfig,true);},refresh:function(A){this.setValue(this.value,A);}};(function(){var A=YAHOO.util.Lang;YAHOO.util.AttributeProvider=function(){};YAHOO.util.AttributeProvider.prototype={_configs:null,get:function(C){this._configs=this._configs||{};var B=this._configs[C];if(!B||!this._configs.hasOwnProperty(C)){return null;}return B.getValue();},set:function(D,E,B){this._configs=this._configs||{};var C=this._configs[D];if(!C){return false;}return C.setValue(E,B);},getAttributeKeys:function(){this._configs=this._configs;var C=[],B;for(B in this._configs){if(A.hasOwnProperty(this._configs,B)&&!A.isUndefined(this._configs[B])){C[C.length]=B;}}return C;},setAttributes:function(D,B){for(var C in D){if(A.hasOwnProperty(D,C)){this.set(C,D[C],B);}}},resetValue:function(C,B){this._configs=this._configs||{};if(this._configs[C]){this.set(C,this._configs[C]._initialConfig.value,B);return true;}return false;},refresh:function(E,C){this._configs=this._configs||{};var F=this._configs;E=((A.isString(E))?[E]:E)||this.getAttributeKeys();for(var D=0,B=E.length;D<B;++D){if(F.hasOwnProperty(E[D])){this._configs[E[D]].refresh(C);}}},register:function(B,C){this.setAttributeConfig(B,C);},getAttributeConfig:function(C){this._configs=this._configs||{};var B=this._configs[C]||{};var D={};for(C in B){if(A.hasOwnProperty(B,C)){D[C]=B[C];}}return D;},setAttributeConfig:function(B,C,D){this._configs=this._configs||{};C=C||{};if(!this._configs[B]){C.name=B;this._configs[B]=this.createAttribute(C);}else{this._configs[B].configure(C,D);}},configureAttribute:function(B,C,D){this.setAttributeConfig(B,C,D);},resetAttributeConfig:function(B){this._configs=this._configs||{};this._configs[B].resetConfig();},subscribe:function(B,C){this._events=this._events||{};if(!(B in this._events)){this._events[B]=this.createEvent(B);}YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){this.subscribe.apply(this,arguments);},addListener:function(){this.subscribe.apply(this,arguments);},fireBeforeChangeEvent:function(C){var B="before";B+=C.type.charAt(0).toUpperCase()+C.type.substr(1)+"Change";C.type=B;return this.fireEvent(C.type,C);},fireChangeEvent:function(B){B.type+="Change";return this.fireEvent(B.type,B);},createAttribute:function(B){return new YAHOO.util.Attribute(B,this);}};YAHOO.augment(YAHOO.util.AttributeProvider,YAHOO.util.EventProvider);})();(function(){var B=YAHOO.util.Dom,D=YAHOO.util.AttributeProvider,C={mouseenter:true,mouseleave:true};var A=function(E,F){this.init.apply(this,arguments);};A.DOM_EVENTS={"click":true,"dblclick":true,"keydown":true,"keypress":true,"keyup":true,"mousedown":true,"mousemove":true,"mouseout":true,"mouseover":true,"mouseup":true,"mouseenter":true,"mouseleave":true,"focus":true,"blur":true,"submit":true,"change":true};A.prototype={DOM_EVENTS:null,DEFAULT_HTML_SETTER:function(G,E){var F=this.get("element");if(F){F[E]=G;}return G;},DEFAULT_HTML_GETTER:function(E){var F=this.get("element"),G;if(F){G=F[E];}return G;},appendChild:function(E){E=E.get?E.get("element"):E;return this.get("element").appendChild(E);},getElementsByTagName:function(E){return this.get("element").getElementsByTagName(E);},hasChildNodes:function(){return this.get("element").hasChildNodes();},insertBefore:function(E,F){E=E.get?E.get("element"):E;F=(F&&F.get)?F.get("element"):F;return this.get("element").insertBefore(E,F);},removeChild:function(E){E=E.get?E.get("element"):E;return this.get("element").removeChild(E);},replaceChild:function(E,F){E=E.get?E.get("element"):E;F=F.get?F.get("element"):F;return this.get("element").replaceChild(E,F);},initAttributes:function(E){},addListener:function(J,I,K,H){H=H||this;var E=YAHOO.util.Event,G=this.get("element")||this.get("id"),F=this;if(C[J]&&!E._createMouseDelegate){return false;}if(!this._events[J]){if(G&&this.DOM_EVENTS[J]){E.on(G,J,function(M,L){if(M.srcElement&&!M.target){M.target=M.srcElement;}if((M.toElement&&!M.relatedTarget)||(M.fromElement&&!M.relatedTarget)){M.relatedTarget=E.getRelatedTarget(M);}if(!M.currentTarget){M.currentTarget=G;}F.fireEvent(J,M,L);},K,H);}this.createEvent(J,{scope:this});}return YAHOO.util.EventProvider.prototype.subscribe.apply(this,arguments);},on:function(){return this.addListener.apply(this,arguments);},subscribe:function(){return this.addListener.apply(this,arguments);},removeListener:function(F,E){return this.unsubscribe.apply(this,arguments);},addClass:function(E){B.addClass(this.get("element"),E);},getElementsByClassName:function(F,E){return B.getElementsByClassName(F,E,this.get("element"));},hasClass:function(E){return B.hasClass(this.get("element"),E);},removeClass:function(E){return B.removeClass(this.get("element"),E);},replaceClass:function(F,E){return B.replaceClass(this.get("element"),F,E);},setStyle:function(F,E){return B.setStyle(this.get("element"),F,E);
-},getStyle:function(E){return B.getStyle(this.get("element"),E);},fireQueue:function(){var F=this._queue;for(var G=0,E=F.length;G<E;++G){this[F[G][0]].apply(this,F[G][1]);}},appendTo:function(F,G){F=(F.get)?F.get("element"):B.get(F);this.fireEvent("beforeAppendTo",{type:"beforeAppendTo",target:F});G=(G&&G.get)?G.get("element"):B.get(G);var E=this.get("element");if(!E){return false;}if(!F){return false;}if(E.parent!=F){if(G){F.insertBefore(E,G);}else{F.appendChild(E);}}this.fireEvent("appendTo",{type:"appendTo",target:F});return E;},get:function(E){var G=this._configs||{},F=G.element;if(F&&!G[E]&&!YAHOO.lang.isUndefined(F.value[E])){this._setHTMLAttrConfig(E);}return D.prototype.get.call(this,E);},setAttributes:function(K,H){var F={},I=this._configOrder;for(var J=0,E=I.length;J<E;++J){if(K[I[J]]!==undefined){F[I[J]]=true;this.set(I[J],K[I[J]],H);}}for(var G in K){if(K.hasOwnProperty(G)&&!F[G]){this.set(G,K[G],H);}}},set:function(F,H,E){var G=this.get("element");if(!G){this._queue[this._queue.length]=["set",arguments];if(this._configs[F]){this._configs[F].value=H;}return;}if(!this._configs[F]&&!YAHOO.lang.isUndefined(G[F])){this._setHTMLAttrConfig(F);}return D.prototype.set.apply(this,arguments);},setAttributeConfig:function(E,F,G){this._configOrder.push(E);D.prototype.setAttributeConfig.apply(this,arguments);},createEvent:function(F,E){this._events[F]=true;return D.prototype.createEvent.apply(this,arguments);},init:function(F,E){this._initElement(F,E);},destroy:function(){var E=this.get("element");YAHOO.util.Event.purgeElement(E,true);this.unsubscribeAll();if(E&&E.parentNode){E.parentNode.removeChild(E);}this._queue=[];this._events={};this._configs={};this._configOrder=[];},_initElement:function(G,F){this._queue=this._queue||[];this._events=this._events||{};this._configs=this._configs||{};this._configOrder=[];F=F||{};F.element=F.element||G||null;var I=false;var E=A.DOM_EVENTS;this.DOM_EVENTS=this.DOM_EVENTS||{};for(var H in E){if(E.hasOwnProperty(H)){this.DOM_EVENTS[H]=E[H];}}if(typeof F.element==="string"){this._setHTMLAttrConfig("id",{value:F.element});}if(B.get(F.element)){I=true;this._initHTMLElement(F);this._initContent(F);}YAHOO.util.Event.onAvailable(F.element,function(){if(!I){this._initHTMLElement(F);}this.fireEvent("available",{type:"available",target:B.get(F.element)});},this,true);YAHOO.util.Event.onContentReady(F.element,function(){if(!I){this._initContent(F);}this.fireEvent("contentReady",{type:"contentReady",target:B.get(F.element)});},this,true);},_initHTMLElement:function(E){this.setAttributeConfig("element",{value:B.get(E.element),readOnly:true});},_initContent:function(E){this.initAttributes(E);this.setAttributes(E,true);this.fireQueue();},_setHTMLAttrConfig:function(E,G){var F=this.get("element");G=G||{};G.name=E;G.setter=G.setter||this.DEFAULT_HTML_SETTER;G.getter=G.getter||this.DEFAULT_HTML_GETTER;G.value=G.value||F[E];this._configs[E]=new YAHOO.util.Attribute(G,this);}};YAHOO.augment(A,D);YAHOO.util.Element=A;})();YAHOO.register("element",YAHOO.util.Element,{version:"2.8.2r1",build:"7"});YAHOO.register("utilities", YAHOO, {version: "2.8.2r1", build: "7"});/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.2r1
-*/
-(function(){var lang=YAHOO.lang,util=YAHOO.util,Ev=util.Event;util.DataSourceBase=function(oLiveData,oConfigs){if(oLiveData===null||oLiveData===undefined){return;}this.liveData=oLiveData;this._oQueue={interval:null,conn:null,requests:[]};this.responseSchema={};if(oConfigs&&(oConfigs.constructor==Object)){for(var sConfig in oConfigs){if(sConfig){this[sConfig]=oConfigs[sConfig];}}}var maxCacheEntries=this.maxCacheEntries;if(!lang.isNumber(maxCacheEntries)||(maxCacheEntries<0)){maxCacheEntries=0;}this._aIntervals=[];this.createEvent("cacheRequestEvent");this.createEvent("cacheResponseEvent");this.createEvent("requestEvent");this.createEvent("responseEvent");this.createEvent("responseParseEvent");this.createEvent("responseCacheEvent");this.createEvent("dataErrorEvent");this.createEvent("cacheFlushEvent");var DS=util.DataSourceBase;this._sName="DataSource instance"+DS._nIndex;DS._nIndex++;};var DS=util.DataSourceBase;lang.augmentObject(DS,{TYPE_UNKNOWN:-1,TYPE_JSARRAY:0,TYPE_JSFUNCTION:1,TYPE_XHR:2,TYPE_JSON:3,TYPE_XML:4,TYPE_TEXT:5,TYPE_HTMLTABLE:6,TYPE_SCRIPTNODE:7,TYPE_LOCAL:8,ERROR_DATAINVALID:"Invalid data",ERROR_DATANULL:"Null data",_nIndex:0,_nTransactionId:0,_getLocationValue:function(field,context){var locator=field.locator||field.key||field,xmldoc=context.ownerDocument||context,result,res,value=null;try{if(!lang.isUndefined(xmldoc.evaluate)){result=xmldoc.evaluate(locator,context,xmldoc.createNSResolver(!context.ownerDocument?context.documentElement:context.ownerDocument.documentElement),0,null);while(res=result.iterateNext()){value=res.textContent;}}else{xmldoc.setProperty("SelectionLanguage","XPath");result=context.selectNodes(locator)[0];value=result.value||result.text||null;}return value;}catch(e){}},issueCallback:function(callback,params,error,scope){if(lang.isFunction(callback)){callback.apply(scope,params);}else{if(lang.isObject(callback)){scope=callback.scope||scope||window;var callbackFunc=callback.success;if(error){callbackFunc=callback.failure;}if(callbackFunc){callbackFunc.apply(scope,params.concat([callback.argument]));}}}},parseString:function(oData){if(!lang.isValue(oData)){return null;}var string=oData+"";if(lang.isString(string)){return string;}else{return null;}},parseNumber:function(oData){if(!lang.isValue(oData)||(oData==="")){return null;}var number=oData*1;if(lang.isNumber(number)){return number;}else{return null;}},convertNumber:function(oData){return DS.parseNumber(oData);},parseDate:function(oData){var date=null;if(!(oData instanceof Date)){date=new Date(oData);}else{return oData;}if(date instanceof Date){return date;}else{return null;}},convertDate:function(oData){return DS.parseDate(oData);}});DS.Parser={string:DS.parseString,number:DS.parseNumber,date:DS.parseDate};DS.prototype={_sName:null,_aCache:null,_oQueue:null,_aIntervals:null,maxCacheEntries:0,liveData:null,dataType:DS.TYPE_UNKNOWN,responseType:DS.TYPE_UNKNOWN,responseSchema:null,useXPath:false,toString:function(){return this._sName;},getCachedResponse:function(oRequest,oCallback,oCaller){var aCache=this._aCache;if(this.maxCacheEntries>0){if(!aCache){this._aCache=[];}else{var nCacheLength=aCache.length;if(nCacheLength>0){var oResponse=null;this.fireEvent("cacheRequestEvent",{request:oRequest,callback:oCallback,caller:oCaller});for(var i=nCacheLength-1;i>=0;i--){var oCacheElem=aCache[i];if(this.isCacheHit(oRequest,oCacheElem.request)){oResponse=oCacheElem.response;this.fireEvent("cacheResponseEvent",{request:oRequest,response:oResponse,callback:oCallback,caller:oCaller});if(i<nCacheLength-1){aCache.splice(i,1);this.addToCache(oRequest,oResponse);}oResponse.cached=true;break;}}return oResponse;}}}else{if(aCache){this._aCache=null;}}return null;},isCacheHit:function(oRequest,oCachedRequest){return(oRequest===oCachedRequest);},addToCache:function(oRequest,oResponse){var aCache=this._aCache;if(!aCache){return;}while(aCache.length>=this.maxCacheEntries){aCache.shift();}var oCacheElem={request:oRequest,response:oResponse};aCache[aCache.length]=oCacheElem;this.fireEvent("responseCacheEvent",{request:oRequest,response:oResponse});},flushCache:function(){if(this._aCache){this._aCache=[];this.fireEvent("cacheFlushEvent");}},setInterval:function(nMsec,oRequest,oCallback,oCaller){if(lang.isNumber(nMsec)&&(nMsec>=0)){var oSelf=this;var nId=setInterval(function(){oSelf.makeConnection(oRequest,oCallback,oCaller);},nMsec);this._aIntervals.push(nId);return nId;}else{}},clearInterval:function(nId){var tracker=this._aIntervals||[];for(var i=tracker.length-1;i>-1;i--){if(tracker[i]===nId){tracker.splice(i,1);clearInterval(nId);}}},clearAllIntervals:function(){var tracker=this._aIntervals||[];for(var i=tracker.length-1;i>-1;i--){clearInterval(tracker[i]);}tracker=[];},sendRequest:function(oRequest,oCallback,oCaller){var oCachedResponse=this.getCachedResponse(oRequest,oCallback,oCaller);if(oCachedResponse){DS.issueCallback(oCallback,[oRequest,oCachedResponse],false,oCaller);return null;}return this.makeConnection(oRequest,oCallback,oCaller);},makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oRawResponse=this.liveData;this.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);return tId;},handleResponse:function(oRequest,oRawResponse,oCallback,oCaller,tId){this.fireEvent("responseEvent",{tId:tId,request:oRequest,response:oRawResponse,callback:oCallback,caller:oCaller});var xhr=(this.dataType==DS.TYPE_XHR)?true:false;var oParsedResponse=null;var oFullResponse=oRawResponse;if(this.responseType===DS.TYPE_UNKNOWN){var ctype=(oRawResponse&&oRawResponse.getResponseHeader)?oRawResponse.getResponseHeader["Content-Type"]:null;if(ctype){if(ctype.indexOf("text/xml")>-1){this.responseType=DS.TYPE_XML;}else{if(ctype.indexOf("application/json")>-1){this.responseType=DS.TYPE_JSON;}else{if(ctype.indexOf("text/plain")>-1){this.responseType=DS.TYPE_TEXT;}}}}else{if(YAHOO.lang.isArray(oRawResponse)){this.responseType=DS.TYPE_JSARRAY;
-}else{if(oRawResponse&&oRawResponse.nodeType&&(oRawResponse.nodeType===9||oRawResponse.nodeType===1||oRawResponse.nodeType===11)){this.responseType=DS.TYPE_XML;}else{if(oRawResponse&&oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){this.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){this.responseType=DS.TYPE_TEXT;}}}}}}}switch(this.responseType){case DS.TYPE_JSARRAY:if(xhr&&oRawResponse&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}try{if(lang.isString(oFullResponse)){var parseArgs=[oFullResponse].concat(this.parseJSONArgs);if(lang.JSON){oFullResponse=lang.JSON.parse.apply(lang.JSON,parseArgs);}else{if(window.JSON&&JSON.parse){oFullResponse=JSON.parse.apply(JSON,parseArgs);}else{if(oFullResponse.parseJSON){oFullResponse=oFullResponse.parseJSON.apply(oFullResponse,parseArgs.slice(1));}else{while(oFullResponse.length>0&&(oFullResponse.charAt(0)!="{")&&(oFullResponse.charAt(0)!="[")){oFullResponse=oFullResponse.substring(1,oFullResponse.length);}if(oFullResponse.length>0){var arrayEnd=Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));oFullResponse=oFullResponse.substring(0,arrayEnd+1);oFullResponse=eval("("+oFullResponse+")");}}}}}}catch(e1){}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseArrayData(oRequest,oFullResponse);break;case DS.TYPE_JSON:if(xhr&&oRawResponse&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}try{if(lang.isString(oFullResponse)){var parseArgs=[oFullResponse].concat(this.parseJSONArgs);if(lang.JSON){oFullResponse=lang.JSON.parse.apply(lang.JSON,parseArgs);}else{if(window.JSON&&JSON.parse){oFullResponse=JSON.parse.apply(JSON,parseArgs);}else{if(oFullResponse.parseJSON){oFullResponse=oFullResponse.parseJSON.apply(oFullResponse,parseArgs.slice(1));}else{while(oFullResponse.length>0&&(oFullResponse.charAt(0)!="{")&&(oFullResponse.charAt(0)!="[")){oFullResponse=oFullResponse.substring(1,oFullResponse.length);}if(oFullResponse.length>0){var objEnd=Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));oFullResponse=oFullResponse.substring(0,objEnd+1);oFullResponse=eval("("+oFullResponse+")");}}}}}}catch(e){}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseJSONData(oRequest,oFullResponse);break;case DS.TYPE_HTMLTABLE:if(xhr&&oRawResponse.responseText){var el=document.createElement("div");el.innerHTML=oRawResponse.responseText;oFullResponse=el.getElementsByTagName("table")[0];}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseHTMLTableData(oRequest,oFullResponse);break;case DS.TYPE_XML:if(xhr&&oRawResponse.responseXML){oFullResponse=oRawResponse.responseXML;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseXMLData(oRequest,oFullResponse);break;case DS.TYPE_TEXT:if(xhr&&lang.isString(oRawResponse.responseText)){oFullResponse=oRawResponse.responseText;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseTextData(oRequest,oFullResponse);break;default:oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseData(oRequest,oFullResponse);break;}oParsedResponse=oParsedResponse||{};if(!oParsedResponse.results){oParsedResponse.results=[];}if(!oParsedResponse.meta){oParsedResponse.meta={};}if(!oParsedResponse.error){oParsedResponse=this.doBeforeCallback(oRequest,oFullResponse,oParsedResponse,oCallback);this.fireEvent("responseParseEvent",{request:oRequest,response:oParsedResponse,callback:oCallback,caller:oCaller});this.addToCache(oRequest,oParsedResponse);}else{oParsedResponse.error=true;this.fireEvent("dataErrorEvent",{request:oRequest,response:oRawResponse,callback:oCallback,caller:oCaller,message:DS.ERROR_DATANULL});}oParsedResponse.tId=tId;DS.issueCallback(oCallback,[oRequest,oParsedResponse],oParsedResponse.error,oCaller);},doBeforeParseData:function(oRequest,oFullResponse,oCallback){return oFullResponse;},doBeforeCallback:function(oRequest,oFullResponse,oParsedResponse,oCallback){return oParsedResponse;},parseData:function(oRequest,oFullResponse){if(lang.isValue(oFullResponse)){var oParsedResponse={results:oFullResponse,meta:{}};return oParsedResponse;}return null;},parseArrayData:function(oRequest,oFullResponse){if(lang.isArray(oFullResponse)){var results=[],i,j,rec,field,data;if(lang.isArray(this.responseSchema.fields)){var fields=this.responseSchema.fields;for(i=fields.length-1;i>=0;--i){if(typeof fields[i]!=="object"){fields[i]={key:fields[i]};}}var parsers={},p;for(i=fields.length-1;i>=0;--i){p=(typeof fields[i].parser==="function"?fields[i].parser:DS.Parser[fields[i].parser+""])||fields[i].converter;if(p){parsers[fields[i].key]=p;}}var arrType=lang.isArray(oFullResponse[0]);for(i=oFullResponse.length-1;i>-1;i--){var oResult={};rec=oFullResponse[i];if(typeof rec==="object"){for(j=fields.length-1;j>-1;j--){field=fields[j];data=arrType?rec[j]:rec[field.key];if(parsers[field.key]){data=parsers[field.key].call(this,data);}if(data===undefined){data=null;}oResult[field.key]=data;}}else{if(lang.isString(rec)){for(j=fields.length-1;j>-1;j--){field=fields[j];data=rec;if(parsers[field.key]){data=parsers[field.key].call(this,data);}if(data===undefined){data=null;}oResult[field.key]=data;}}}results[i]=oResult;}}else{results=oFullResponse;}var oParsedResponse={results:results};return oParsedResponse;}return null;},parseTextData:function(oRequest,oFullResponse){if(lang.isString(oFullResponse)){if(lang.isString(this.responseSchema.recordDelim)&&lang.isString(this.responseSchema.fieldDelim)){var oParsedResponse={results:[]};var recDelim=this.responseSchema.recordDelim;var fieldDelim=this.responseSchema.fieldDelim;if(oFullResponse.length>0){var newLength=oFullResponse.length-recDelim.length;if(oFullResponse.substr(newLength)==recDelim){oFullResponse=oFullResponse.substr(0,newLength);
-}if(oFullResponse.length>0){var recordsarray=oFullResponse.split(recDelim);for(var i=0,len=recordsarray.length,recIdx=0;i<len;++i){var bError=false,sRecord=recordsarray[i];if(lang.isString(sRecord)&&(sRecord.length>0)){var fielddataarray=recordsarray[i].split(fieldDelim);var oResult={};if(lang.isArray(this.responseSchema.fields)){var fields=this.responseSchema.fields;for(var j=fields.length-1;j>-1;j--){try{var data=fielddataarray[j];if(lang.isString(data)){if(data.charAt(0)=='"'){data=data.substr(1);}if(data.charAt(data.length-1)=='"'){data=data.substr(0,data.length-1);}var field=fields[j];var key=(lang.isValue(field.key))?field.key:field;if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}else{bError=true;}}catch(e){bError=true;}}}else{oResult=fielddataarray;}if(!bError){oParsedResponse.results[recIdx++]=oResult;}}}}}return oParsedResponse;}}return null;},parseXMLResult:function(result){var oResult={},schema=this.responseSchema;try{for(var m=schema.fields.length-1;m>=0;m--){var field=schema.fields[m];var key=(lang.isValue(field.key))?field.key:field;var data=null;if(this.useXPath){data=YAHOO.util.DataSource._getLocationValue(field,result);}else{var xmlAttr=result.attributes.getNamedItem(key);if(xmlAttr){data=xmlAttr.value;}else{var xmlNode=result.getElementsByTagName(key);if(xmlNode&&xmlNode.item(0)){var item=xmlNode.item(0);data=(item)?((item.text)?item.text:(item.textContent)?item.textContent:null):null;if(!data){var datapieces=[];for(var j=0,len=item.childNodes.length;j<len;j++){if(item.childNodes[j].nodeValue){datapieces[datapieces.length]=item.childNodes[j].nodeValue;}}if(datapieces.length>0){data=datapieces.join("");}}}}}if(data===null){data="";}if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}}catch(e){}return oResult;},parseXMLData:function(oRequest,oFullResponse){var bError=false,schema=this.responseSchema,oParsedResponse={meta:{}},xmlList=null,metaNode=schema.metaNode,metaLocators=schema.metaFields||{},i,k,loc,v;try{if(this.useXPath){for(k in metaLocators){oParsedResponse.meta[k]=YAHOO.util.DataSource._getLocationValue(metaLocators[k],oFullResponse);}}else{metaNode=metaNode?oFullResponse.getElementsByTagName(metaNode)[0]:oFullResponse;if(metaNode){for(k in metaLocators){if(lang.hasOwnProperty(metaLocators,k)){loc=metaLocators[k];v=metaNode.getElementsByTagName(loc)[0];if(v){v=v.firstChild.nodeValue;}else{v=metaNode.attributes.getNamedItem(loc);if(v){v=v.value;}}if(lang.isValue(v)){oParsedResponse.meta[k]=v;}}}}}xmlList=(schema.resultNode)?oFullResponse.getElementsByTagName(schema.resultNode):null;}catch(e){}if(!xmlList||!lang.isArray(schema.fields)){bError=true;}else{oParsedResponse.results=[];for(i=xmlList.length-1;i>=0;--i){var oResult=this.parseXMLResult(xmlList.item(i));oParsedResponse.results[i]=oResult;}}if(bError){oParsedResponse.error=true;}else{}return oParsedResponse;},parseJSONData:function(oRequest,oFullResponse){var oParsedResponse={results:[],meta:{}};if(lang.isObject(oFullResponse)&&this.responseSchema.resultsList){var schema=this.responseSchema,fields=schema.fields,resultsList=oFullResponse,results=[],metaFields=schema.metaFields||{},fieldParsers=[],fieldPaths=[],simpleFields=[],bError=false,i,len,j,v,key,parser,path;var buildPath=function(needle){var path=null,keys=[],i=0;if(needle){needle=needle.replace(/\[(['"])(.*?)\1\]/g,function(x,$1,$2){keys[i]=$2;return".@"+(i++);}).replace(/\[(\d+)\]/g,function(x,$1){keys[i]=parseInt($1,10)|0;return".@"+(i++);}).replace(/^\./,"");if(!/[^\w\.\$@]/.test(needle)){path=needle.split(".");for(i=path.length-1;i>=0;--i){if(path[i].charAt(0)==="@"){path[i]=keys[parseInt(path[i].substr(1),10)];}}}else{}}return path;};var walkPath=function(path,origin){var v=origin,i=0,len=path.length;for(;i<len&&v;++i){v=v[path[i]];}return v;};path=buildPath(schema.resultsList);if(path){resultsList=walkPath(path,oFullResponse);if(resultsList===undefined){bError=true;}}else{bError=true;}if(!resultsList){resultsList=[];}if(!lang.isArray(resultsList)){resultsList=[resultsList];}if(!bError){if(schema.fields){var field;for(i=0,len=fields.length;i<len;i++){field=fields[i];key=field.key||field;parser=((typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""])||field.converter;path=buildPath(key);if(parser){fieldParsers[fieldParsers.length]={key:key,parser:parser};}if(path){if(path.length>1){fieldPaths[fieldPaths.length]={key:key,path:path};}else{simpleFields[simpleFields.length]={key:key,path:path[0]};}}else{}}for(i=resultsList.length-1;i>=0;--i){var r=resultsList[i],rec={};if(r){for(j=simpleFields.length-1;j>=0;--j){rec[simpleFields[j].key]=(r[simpleFields[j].path]!==undefined)?r[simpleFields[j].path]:r[j];}for(j=fieldPaths.length-1;j>=0;--j){rec[fieldPaths[j].key]=walkPath(fieldPaths[j].path,r);}for(j=fieldParsers.length-1;j>=0;--j){var p=fieldParsers[j].key;rec[p]=fieldParsers[j].parser(rec[p]);if(rec[p]===undefined){rec[p]=null;}}}results[i]=rec;}}else{results=resultsList;}for(key in metaFields){if(lang.hasOwnProperty(metaFields,key)){path=buildPath(metaFields[key]);if(path){v=walkPath(path,oFullResponse);oParsedResponse.meta[key]=v;}}}}else{oParsedResponse.error=true;}oParsedResponse.results=results;}else{oParsedResponse.error=true;}return oParsedResponse;},parseHTMLTableData:function(oRequest,oFullResponse){var bError=false;var elTable=oFullResponse;var fields=this.responseSchema.fields;var oParsedResponse={results:[]};if(lang.isArray(fields)){for(var i=0;i<elTable.tBodies.length;i++){var elTbody=elTable.tBodies[i];for(var j=elTbody.rows.length-1;j>-1;j--){var elRow=elTbody.rows[j];var oResult={};for(var k=fields.length-1;k>-1;k--){var field=fields[k];var key=(lang.isValue(field.key))?field.key:field;
-var data=elRow.cells[k].innerHTML;if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}oParsedResponse.results[j]=oResult;}}}else{bError=true;}if(bError){oParsedResponse.error=true;}else{}return oParsedResponse;}};lang.augmentProto(DS,util.EventProvider);util.LocalDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_LOCAL;if(oLiveData){if(YAHOO.lang.isArray(oLiveData)){this.responseType=DS.TYPE_JSARRAY;}else{if(oLiveData.nodeType&&oLiveData.nodeType==9){this.responseType=DS.TYPE_XML;}else{if(oLiveData.nodeName&&(oLiveData.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;oLiveData=oLiveData.cloneNode(true);}else{if(YAHOO.lang.isString(oLiveData)){this.responseType=DS.TYPE_TEXT;}else{if(YAHOO.lang.isObject(oLiveData)){this.responseType=DS.TYPE_JSON;}}}}}}else{oLiveData=[];this.responseType=DS.TYPE_JSARRAY;}util.LocalDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.LocalDataSource,DS);lang.augmentObject(util.LocalDataSource,DS);util.FunctionDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_JSFUNCTION;oLiveData=oLiveData||function(){};util.FunctionDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.FunctionDataSource,DS,{scope:null,makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oRawResponse=(this.scope)?this.liveData.call(this.scope,oRequest,this):this.liveData(oRequest);if(this.responseType===DS.TYPE_UNKNOWN){if(YAHOO.lang.isArray(oRawResponse)){this.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse&&oRawResponse.nodeType&&oRawResponse.nodeType==9){this.responseType=DS.TYPE_XML;}else{if(oRawResponse&&oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){this.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){this.responseType=DS.TYPE_TEXT;}}}}}}this.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);return tId;}});lang.augmentObject(util.FunctionDataSource,DS);util.ScriptNodeDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_SCRIPTNODE;oLiveData=oLiveData||"";util.ScriptNodeDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.ScriptNodeDataSource,DS,{getUtility:util.Get,asyncMode:"allowAll",scriptCallbackParam:"callback",generateRequestCallback:function(id){return"&"+this.scriptCallbackParam+"=YAHOO.util.ScriptNodeDataSource.callbacks["+id+"]";},doBeforeGetScriptNode:function(sUri){return sUri;},makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});if(util.ScriptNodeDataSource._nPending===0){util.ScriptNodeDataSource.callbacks=[];util.ScriptNodeDataSource._nId=0;}var id=util.ScriptNodeDataSource._nId;util.ScriptNodeDataSource._nId++;var oSelf=this;util.ScriptNodeDataSource.callbacks[id]=function(oRawResponse){if((oSelf.asyncMode!=="ignoreStaleResponses")||(id===util.ScriptNodeDataSource.callbacks.length-1)){if(oSelf.responseType===DS.TYPE_UNKNOWN){if(YAHOO.lang.isArray(oRawResponse)){oSelf.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse.nodeType&&oRawResponse.nodeType==9){oSelf.responseType=DS.TYPE_XML;}else{if(oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){oSelf.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){oSelf.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){oSelf.responseType=DS.TYPE_TEXT;}}}}}}oSelf.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);}else{}delete util.ScriptNodeDataSource.callbacks[id];};util.ScriptNodeDataSource._nPending++;var sUri=this.liveData+oRequest+this.generateRequestCallback(id);sUri=this.doBeforeGetScriptNode(sUri);this.getUtility.script(sUri,{autopurge:true,onsuccess:util.ScriptNodeDataSource._bumpPendingDown,onfail:util.ScriptNodeDataSource._bumpPendingDown});return tId;}});lang.augmentObject(util.ScriptNodeDataSource,DS);lang.augmentObject(util.ScriptNodeDataSource,{_nId:0,_nPending:0,callbacks:[]});util.XHRDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_XHR;this.connMgr=this.connMgr||util.Connect;oLiveData=oLiveData||"";util.XHRDataSource.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.XHRDataSource,DS,{connMgr:null,connXhrMode:"allowAll",connMethodPost:false,connTimeout:0,makeConnection:function(oRequest,oCallback,oCaller){var oRawResponse=null;var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oSelf=this;var oConnMgr=this.connMgr;var oQueue=this._oQueue;var _xhrSuccess=function(oResponse){if(oResponse&&(this.connXhrMode=="ignoreStaleResponses")&&(oResponse.tId!=oQueue.conn.tId)){return null;}else{if(!oResponse){this.fireEvent("dataErrorEvent",{request:oRequest,response:null,callback:oCallback,caller:oCaller,message:DS.ERROR_DATANULL});DS.issueCallback(oCallback,[oRequest,{error:true}],true,oCaller);return null;}else{if(this.responseType===DS.TYPE_UNKNOWN){var ctype=(oResponse.getResponseHeader)?oResponse.getResponseHeader["Content-Type"]:null;if(ctype){if(ctype.indexOf("text/xml")>-1){this.responseType=DS.TYPE_XML;}else{if(ctype.indexOf("application/json")>-1){this.responseType=DS.TYPE_JSON;}else{if(ctype.indexOf("text/plain")>-1){this.responseType=DS.TYPE_TEXT;}}}}}this.handleResponse(oRequest,oResponse,oCallback,oCaller,tId);}}};var _xhrFailure=function(oResponse){this.fireEvent("dataErrorEvent",{request:oRequest,response:oResponse,callback:oCallback,caller:oCaller,message:DS.ERROR_DATAINVALID});if(lang.isString(this.liveData)&&lang.isString(oRequest)&&(this.liveData.lastIndexOf("?")!==this.liveData.length-1)&&(oRequest.indexOf("?")!==0)){}oResponse=oResponse||{};
-oResponse.error=true;DS.issueCallback(oCallback,[oRequest,oResponse],true,oCaller);return null;};var _xhrCallback={success:_xhrSuccess,failure:_xhrFailure,scope:this};if(lang.isNumber(this.connTimeout)){_xhrCallback.timeout=this.connTimeout;}if(this.connXhrMode=="cancelStaleRequests"){if(oQueue.conn){if(oConnMgr.abort){oConnMgr.abort(oQueue.conn);oQueue.conn=null;}else{}}}if(oConnMgr&&oConnMgr.asyncRequest){var sLiveData=this.liveData;var isPost=this.connMethodPost;var sMethod=(isPost)?"POST":"GET";var sUri=(isPost||!lang.isValue(oRequest))?sLiveData:sLiveData+oRequest;var sRequest=(isPost)?oRequest:null;if(this.connXhrMode!="queueRequests"){oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,_xhrCallback,sRequest);}else{if(oQueue.conn){var allRequests=oQueue.requests;allRequests.push({request:oRequest,callback:_xhrCallback});if(!oQueue.interval){oQueue.interval=setInterval(function(){if(oConnMgr.isCallInProgress(oQueue.conn)){return;}else{if(allRequests.length>0){sUri=(isPost||!lang.isValue(allRequests[0].request))?sLiveData:sLiveData+allRequests[0].request;sRequest=(isPost)?allRequests[0].request:null;oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,allRequests[0].callback,sRequest);allRequests.shift();}else{clearInterval(oQueue.interval);oQueue.interval=null;}}},50);}}else{oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,_xhrCallback,sRequest);}}}else{DS.issueCallback(oCallback,[oRequest,{error:true}],true,oCaller);}return tId;}});lang.augmentObject(util.XHRDataSource,DS);util.DataSource=function(oLiveData,oConfigs){oConfigs=oConfigs||{};var dataType=oConfigs.dataType;if(dataType){if(dataType==DS.TYPE_LOCAL){lang.augmentObject(util.DataSource,util.LocalDataSource);return new util.LocalDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_XHR){lang.augmentObject(util.DataSource,util.XHRDataSource);return new util.XHRDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_SCRIPTNODE){lang.augmentObject(util.DataSource,util.ScriptNodeDataSource);return new util.ScriptNodeDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_JSFUNCTION){lang.augmentObject(util.DataSource,util.FunctionDataSource);return new util.FunctionDataSource(oLiveData,oConfigs);}}}}}if(YAHOO.lang.isString(oLiveData)){lang.augmentObject(util.DataSource,util.XHRDataSource);return new util.XHRDataSource(oLiveData,oConfigs);}else{if(YAHOO.lang.isFunction(oLiveData)){lang.augmentObject(util.DataSource,util.FunctionDataSource);return new util.FunctionDataSource(oLiveData,oConfigs);}else{lang.augmentObject(util.DataSource,util.LocalDataSource);return new util.LocalDataSource(oLiveData,oConfigs);}}};lang.augmentObject(util.DataSource,DS);})();YAHOO.util.Number={format:function(B,E){if(!isFinite(+B)){return"";}B=!isFinite(+B)?0:+B;E=YAHOO.lang.merge(YAHOO.util.Number.format.defaults,(E||{}));var C=B<0,F=Math.abs(B),A=E.decimalPlaces,I=E.thousandsSeparator,H,G,D;if(A<0){H=F-(F%1)+"";D=H.length+A;if(D>0){H=Number("."+H).toFixed(D).slice(2)+new Array(H.length-D+1).join("0");}else{H="0";}}else{H=F<1&&F>=0.5&&!A?"1":F.toFixed(A);}if(F>1000){G=H.split(/\D/);D=G[0].length%3||3;G[0]=G[0].slice(0,D)+G[0].slice(D).replace(/(\d{3})/g,I+"$1");H=G.join(E.decimalSeparator);}H=E.prefix+H+E.suffix;return C?E.negativeFormat.replace(/#/,H):H;}};YAHOO.util.Number.format.defaults={decimalSeparator:".",decimalPlaces:null,thousandsSeparator:"",prefix:"",suffix:"",negativeFormat:"-#"};(function(){var A=function(C,E,D){if(typeof D==="undefined"){D=10;}for(;parseInt(C,10)<D&&D>1;D/=10){C=E.toString()+C;}return C.toString();};var B={formats:{a:function(D,C){return C.a[D.getDay()];},A:function(D,C){return C.A[D.getDay()];},b:function(D,C){return C.b[D.getMonth()];},B:function(D,C){return C.B[D.getMonth()];},C:function(C){return A(parseInt(C.getFullYear()/100,10),0);},d:["getDate","0"],e:["getDate"," "],g:function(C){return A(parseInt(B.formats.G(C)%100,10),0);},G:function(E){var F=E.getFullYear();var D=parseInt(B.formats.V(E),10);var C=parseInt(B.formats.W(E),10);if(C>D){F++;}else{if(C===0&&D>=52){F--;}}return F;},H:["getHours","0"],I:function(D){var C=D.getHours()%12;return A(C===0?12:C,0);},j:function(G){var F=new Date(""+G.getFullYear()+"/1/1 GMT");var D=new Date(""+G.getFullYear()+"/"+(G.getMonth()+1)+"/"+G.getDate()+" GMT");var C=D-F;var E=parseInt(C/60000/60/24,10)+1;return A(E,0,100);},k:["getHours"," "],l:function(D){var C=D.getHours()%12;return A(C===0?12:C," ");},m:function(C){return A(C.getMonth()+1,0);},M:["getMinutes","0"],p:function(D,C){return C.p[D.getHours()>=12?1:0];},P:function(D,C){return C.P[D.getHours()>=12?1:0];},s:function(D,C){return parseInt(D.getTime()/1000,10);},S:["getSeconds","0"],u:function(C){var D=C.getDay();return D===0?7:D;},U:function(F){var C=parseInt(B.formats.j(F),10);var E=6-F.getDay();var D=parseInt((C+E)/7,10);return A(D,0);},V:function(F){var E=parseInt(B.formats.W(F),10);var C=(new Date(""+F.getFullYear()+"/1/1")).getDay();var D=E+(C>4||C<=1?0:1);if(D===53&&(new Date(""+F.getFullYear()+"/12/31")).getDay()<4){D=1;}else{if(D===0){D=B.formats.V(new Date(""+(F.getFullYear()-1)+"/12/31"));}}return A(D,0);},w:"getDay",W:function(F){var C=parseInt(B.formats.j(F),10);var E=7-B.formats.u(F);var D=parseInt((C+E)/7,10);return A(D,0,10);},y:function(C){return A(C.getFullYear()%100,0);},Y:"getFullYear",z:function(E){var D=E.getTimezoneOffset();var C=A(parseInt(Math.abs(D/60),10),0);var F=A(Math.abs(D%60),0);return(D>0?"-":"+")+C+F;},Z:function(C){var D=C.toString().replace(/^.*:\d\d( GMT[+-]\d+)? \(?([A-Za-z ]+)\)?\d*$/,"$2").replace(/[a-z ]/g,"");if(D.length>4){D=B.formats.z(C);}return D;},"%":function(C){return"%";}},aggregates:{c:"locale",D:"%m/%d/%y",F:"%Y-%m-%d",h:"%b",n:"\n",r:"locale",R:"%H:%M",t:"\t",T:"%H:%M:%S",x:"locale",X:"locale"},format:function(G,F,D){F=F||{};if(!(G instanceof Date)){return YAHOO.lang.isValue(G)?G:"";}var H=F.format||"%m/%d/%Y";if(H==="YYYY/MM/DD"){H="%Y/%m/%d";}else{if(H==="DD/MM/YYYY"){H="%d/%m/%Y";}else{if(H==="MM/DD/YYYY"){H="%m/%d/%Y";}}}D=D||"en";if(!(D in YAHOO.util.DateLocale)){if(D.replace(/-[a-zA-Z]+$/,"") in YAHOO.util.DateLocale){D=D.replace(/-[a-zA-Z]+$/,"");
-}else{D="en";}}var J=YAHOO.util.DateLocale[D];var C=function(L,K){var M=B.aggregates[K];return(M==="locale"?J[K]:M);};var E=function(L,K){var M=B.formats[K];if(typeof M==="string"){return G[M]();}else{if(typeof M==="function"){return M.call(G,G,J);}else{if(typeof M==="object"&&typeof M[0]==="string"){return A(G[M[0]](),M[1]);}else{return K;}}}};while(H.match(/%[cDFhnrRtTxX]/)){H=H.replace(/%([cDFhnrRtTxX])/g,C);}var I=H.replace(/%([aAbBCdegGHIjklmMpPsSuUVwWyYzZ%])/g,E);C=E=undefined;return I;}};YAHOO.namespace("YAHOO.util");YAHOO.util.Date=B;YAHOO.util.DateLocale={a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a %d %b %Y %T %Z",p:["AM","PM"],P:["am","pm"],r:"%I:%M:%S %p",x:"%d/%m/%y",X:"%T"};YAHOO.util.DateLocale["en"]=YAHOO.lang.merge(YAHOO.util.DateLocale,{});YAHOO.util.DateLocale["en-US"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"],{c:"%a %d %b %Y %I:%M:%S %p %Z",x:"%m/%d/%Y",X:"%I:%M:%S %p"});YAHOO.util.DateLocale["en-GB"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"],{r:"%l:%M:%S %P %Z"});YAHOO.util.DateLocale["en-AU"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"]);})();YAHOO.register("datasource",YAHOO.util.DataSource,{version:"2.8.2r1",build:"7"});/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.2r1
-*/
-YAHOO.widget.DS_JSArray=YAHOO.util.LocalDataSource;YAHOO.widget.DS_JSFunction=YAHOO.util.FunctionDataSource;YAHOO.widget.DS_XHR=function(B,A,D){var C=new YAHOO.util.XHRDataSource(B,D);C._aDeprecatedSchema=A;return C;};YAHOO.widget.DS_ScriptNode=function(B,A,D){var C=new YAHOO.util.ScriptNodeDataSource(B,D);C._aDeprecatedSchema=A;return C;};YAHOO.widget.DS_XHR.TYPE_JSON=YAHOO.util.DataSourceBase.TYPE_JSON;YAHOO.widget.DS_XHR.TYPE_XML=YAHOO.util.DataSourceBase.TYPE_XML;YAHOO.widget.DS_XHR.TYPE_FLAT=YAHOO.util.DataSourceBase.TYPE_TEXT;YAHOO.widget.AutoComplete=function(G,B,J,C){if(G&&B&&J){if(J&&YAHOO.lang.isFunction(J.sendRequest)){this.dataSource=J;}else{return;}this.key=0;var D=J.responseSchema;if(J._aDeprecatedSchema){var K=J._aDeprecatedSchema;if(YAHOO.lang.isArray(K)){if((J.responseType===YAHOO.util.DataSourceBase.TYPE_JSON)||(J.responseType===YAHOO.util.DataSourceBase.TYPE_UNKNOWN)){D.resultsList=K[0];this.key=K[1];D.fields=(K.length<3)?null:K.slice(1);}else{if(J.responseType===YAHOO.util.DataSourceBase.TYPE_XML){D.resultNode=K[0];this.key=K[1];D.fields=K.slice(1);}else{if(J.responseType===YAHOO.util.DataSourceBase.TYPE_TEXT){D.recordDelim=K[0];D.fieldDelim=K[1];}}}J.responseSchema=D;}}if(YAHOO.util.Dom.inDocument(G)){if(YAHOO.lang.isString(G)){this._sName="instance"+YAHOO.widget.AutoComplete._nIndex+" "+G;this._elTextbox=document.getElementById(G);}else{this._sName=(G.id)?"instance"+YAHOO.widget.AutoComplete._nIndex+" "+G.id:"instance"+YAHOO.widget.AutoComplete._nIndex;this._elTextbox=G;}YAHOO.util.Dom.addClass(this._elTextbox,"yui-ac-input");}else{return;}if(YAHOO.util.Dom.inDocument(B)){if(YAHOO.lang.isString(B)){this._elContainer=document.getElementById(B);}else{this._elContainer=B;}if(this._elContainer.style.display=="none"){}var E=this._elContainer.parentNode;var A=E.tagName.toLowerCase();if(A=="div"){YAHOO.util.Dom.addClass(E,"yui-ac");}else{}}else{return;}if(this.dataSource.dataType===YAHOO.util.DataSourceBase.TYPE_LOCAL){this.applyLocalFilter=true;}if(C&&(C.constructor==Object)){for(var I in C){if(I){this[I]=C[I];}}}this._initContainerEl();this._initProps();this._initListEl();this._initContainerHelperEls();var H=this;var F=this._elTextbox;YAHOO.util.Event.addListener(F,"keyup",H._onTextboxKeyUp,H);YAHOO.util.Event.addListener(F,"keydown",H._onTextboxKeyDown,H);YAHOO.util.Event.addListener(F,"focus",H._onTextboxFocus,H);YAHOO.util.Event.addListener(F,"blur",H._onTextboxBlur,H);YAHOO.util.Event.addListener(B,"mouseover",H._onContainerMouseover,H);YAHOO.util.Event.addListener(B,"mouseout",H._onContainerMouseout,H);YAHOO.util.Event.addListener(B,"click",H._onContainerClick,H);YAHOO.util.Event.addListener(B,"scroll",H._onContainerScroll,H);YAHOO.util.Event.addListener(B,"resize",H._onContainerResize,H);YAHOO.util.Event.addListener(F,"keypress",H._onTextboxKeyPress,H);YAHOO.util.Event.addListener(window,"unload",H._onWindowUnload,H);this.textboxFocusEvent=new YAHOO.util.CustomEvent("textboxFocus",this);this.textboxKeyEvent=new YAHOO.util.CustomEvent("textboxKey",this);this.dataRequestEvent=new YAHOO.util.CustomEvent("dataRequest",this);this.dataReturnEvent=new YAHOO.util.CustomEvent("dataReturn",this);this.dataErrorEvent=new YAHOO.util.CustomEvent("dataError",this);this.containerPopulateEvent=new YAHOO.util.CustomEvent("containerPopulate",this);this.containerExpandEvent=new YAHOO.util.CustomEvent("containerExpand",this);this.typeAheadEvent=new YAHOO.util.CustomEvent("typeAhead",this);this.itemMouseOverEvent=new YAHOO.util.CustomEvent("itemMouseOver",this);this.itemMouseOutEvent=new YAHOO.util.CustomEvent("itemMouseOut",this);this.itemArrowToEvent=new YAHOO.util.CustomEvent("itemArrowTo",this);this.itemArrowFromEvent=new YAHOO.util.CustomEvent("itemArrowFrom",this);this.itemSelectEvent=new YAHOO.util.CustomEvent("itemSelect",this);this.unmatchedItemSelectEvent=new YAHOO.util.CustomEvent("unmatchedItemSelect",this);this.selectionEnforceEvent=new YAHOO.util.CustomEvent("selectionEnforce",this);this.containerCollapseEvent=new YAHOO.util.CustomEvent("containerCollapse",this);this.textboxBlurEvent=new YAHOO.util.CustomEvent("textboxBlur",this);this.textboxChangeEvent=new YAHOO.util.CustomEvent("textboxChange",this);F.setAttribute("autocomplete","off");YAHOO.widget.AutoComplete._nIndex++;}else{}};YAHOO.widget.AutoComplete.prototype.dataSource=null;YAHOO.widget.AutoComplete.prototype.applyLocalFilter=null;YAHOO.widget.AutoComplete.prototype.queryMatchCase=false;YAHOO.widget.AutoComplete.prototype.queryMatchContains=false;YAHOO.widget.AutoComplete.prototype.queryMatchSubset=false;YAHOO.widget.AutoComplete.prototype.minQueryLength=1;YAHOO.widget.AutoComplete.prototype.maxResultsDisplayed=10;YAHOO.widget.AutoComplete.prototype.queryDelay=0.2;YAHOO.widget.AutoComplete.prototype.typeAheadDelay=0.5;YAHOO.widget.AutoComplete.prototype.queryInterval=500;YAHOO.widget.AutoComplete.prototype.highlightClassName="yui-ac-highlight";YAHOO.widget.AutoComplete.prototype.prehighlightClassName=null;YAHOO.widget.AutoComplete.prototype.delimChar=null;YAHOO.widget.AutoComplete.prototype.autoHighlight=true;YAHOO.widget.AutoComplete.prototype.typeAhead=false;YAHOO.widget.AutoComplete.prototype.animHoriz=false;YAHOO.widget.AutoComplete.prototype.animVert=true;YAHOO.widget.AutoComplete.prototype.animSpeed=0.3;YAHOO.widget.AutoComplete.prototype.forceSelection=false;YAHOO.widget.AutoComplete.prototype.allowBrowserAutocomplete=true;YAHOO.widget.AutoComplete.prototype.alwaysShowContainer=false;YAHOO.widget.AutoComplete.prototype.useIFrame=false;YAHOO.widget.AutoComplete.prototype.useShadow=false;YAHOO.widget.AutoComplete.prototype.suppressInputUpdate=false;YAHOO.widget.AutoComplete.prototype.resultTypeList=true;YAHOO.widget.AutoComplete.prototype.queryQuestionMark=true;YAHOO.widget.AutoComplete.prototype.autoSnapContainer=true;YAHOO.widget.AutoComplete.prototype.toString=function(){return"AutoComplete "+this._sName;};YAHOO.widget.AutoComplete.prototype.getInputEl=function(){return this._elTextbox;};YAHOO.widget.AutoComplete.prototype.getContainerEl=function(){return this._elContainer;
-};YAHOO.widget.AutoComplete.prototype.isFocused=function(){return this._bFocused;};YAHOO.widget.AutoComplete.prototype.isContainerOpen=function(){return this._bContainerOpen;};YAHOO.widget.AutoComplete.prototype.getListEl=function(){return this._elList;};YAHOO.widget.AutoComplete.prototype.getListItemMatch=function(A){if(A._sResultMatch){return A._sResultMatch;}else{return null;}};YAHOO.widget.AutoComplete.prototype.getListItemData=function(A){if(A._oResultData){return A._oResultData;}else{return null;}};YAHOO.widget.AutoComplete.prototype.getListItemIndex=function(A){if(YAHOO.lang.isNumber(A._nItemIndex)){return A._nItemIndex;}else{return null;}};YAHOO.widget.AutoComplete.prototype.setHeader=function(B){if(this._elHeader){var A=this._elHeader;if(B){A.innerHTML=B;A.style.display="";}else{A.innerHTML="";A.style.display="none";}}};YAHOO.widget.AutoComplete.prototype.setFooter=function(B){if(this._elFooter){var A=this._elFooter;if(B){A.innerHTML=B;A.style.display="";}else{A.innerHTML="";A.style.display="none";}}};YAHOO.widget.AutoComplete.prototype.setBody=function(A){if(this._elBody){var B=this._elBody;YAHOO.util.Event.purgeElement(B,true);if(A){B.innerHTML=A;B.style.display="";}else{B.innerHTML="";B.style.display="none";}this._elList=null;}};YAHOO.widget.AutoComplete.prototype.generateRequest=function(B){var A=this.dataSource.dataType;if(A===YAHOO.util.DataSourceBase.TYPE_XHR){if(!this.dataSource.connMethodPost){B=(this.queryQuestionMark?"?":"")+(this.dataSource.scriptQueryParam||"query")+"="+B+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}else{B=(this.dataSource.scriptQueryParam||"query")+"="+B+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}}else{if(A===YAHOO.util.DataSourceBase.TYPE_SCRIPTNODE){B="&"+(this.dataSource.scriptQueryParam||"query")+"="+B+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}}return B;};YAHOO.widget.AutoComplete.prototype.sendQuery=function(B){this._bFocused=true;var A=(this.delimChar)?this._elTextbox.value+B:B;this._sendQuery(A);};YAHOO.widget.AutoComplete.prototype.snapContainer=function(){var A=this._elTextbox,B=YAHOO.util.Dom.getXY(A);B[1]+=YAHOO.util.Dom.get(A).offsetHeight+2;YAHOO.util.Dom.setXY(this._elContainer,B);};YAHOO.widget.AutoComplete.prototype.expandContainer=function(){this._toggleContainer(true);};YAHOO.widget.AutoComplete.prototype.collapseContainer=function(){this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype.clearList=function(){var B=this._elList.childNodes,A=B.length-1;for(;A>-1;A--){B[A].style.display="none";}};YAHOO.widget.AutoComplete.prototype.getSubsetMatches=function(E){var D,C,A;for(var B=E.length;B>=this.minQueryLength;B--){A=this.generateRequest(E.substr(0,B));this.dataRequestEvent.fire(this,D,A);C=this.dataSource.getCachedResponse(A);if(C){return this.filterResults.apply(this.dataSource,[E,C,C,{scope:this}]);}}return null;};YAHOO.widget.AutoComplete.prototype.preparseRawResponse=function(C,B,A){var D=((this.responseStripAfter!=="")&&(B.indexOf))?B.indexOf(this.responseStripAfter):-1;if(D!=-1){B=B.substring(0,D);}return B;};YAHOO.widget.AutoComplete.prototype.filterResults=function(K,M,Q,L){if(L&&L.argument&&L.argument.query){K=L.argument.query;}if(K&&K!==""){Q=YAHOO.widget.AutoComplete._cloneObject(Q);var I=L.scope,P=this,C=Q.results,N=[],B=I.maxResultsDisplayed,J=(P.queryMatchCase||I.queryMatchCase),A=(P.queryMatchContains||I.queryMatchContains);for(var D=0,H=C.length;D<H;D++){var F=C[D];var E=null;if(YAHOO.lang.isString(F)){E=F;}else{if(YAHOO.lang.isArray(F)){E=F[0];}else{if(this.responseSchema.fields){var O=this.responseSchema.fields[0].key||this.responseSchema.fields[0];E=F[O];}else{if(this.key){E=F[this.key];}}}}if(YAHOO.lang.isString(E)){var G=(J)?E.indexOf(decodeURIComponent(K)):E.toLowerCase().indexOf(decodeURIComponent(K).toLowerCase());if((!A&&(G===0))||(A&&(G>-1))){N.push(F);}}if(H>B&&N.length===B){break;}}Q.results=N;}else{}return Q;};YAHOO.widget.AutoComplete.prototype.handleResponse=function(C,A,B){if((this instanceof YAHOO.widget.AutoComplete)&&this._sName){this._populateList(C,A,B);}};YAHOO.widget.AutoComplete.prototype.doBeforeLoadData=function(C,A,B){return true;};YAHOO.widget.AutoComplete.prototype.formatResult=function(B,D,A){var C=(A)?A:"";return C;};YAHOO.widget.AutoComplete.prototype.doBeforeExpandContainer=function(D,A,C,B){return true;};YAHOO.widget.AutoComplete.prototype.destroy=function(){var B=this.toString();var A=this._elTextbox;var D=this._elContainer;this.textboxFocusEvent.unsubscribeAll();this.textboxKeyEvent.unsubscribeAll();this.dataRequestEvent.unsubscribeAll();this.dataReturnEvent.unsubscribeAll();this.dataErrorEvent.unsubscribeAll();this.containerPopulateEvent.unsubscribeAll();this.containerExpandEvent.unsubscribeAll();this.typeAheadEvent.unsubscribeAll();this.itemMouseOverEvent.unsubscribeAll();this.itemMouseOutEvent.unsubscribeAll();this.itemArrowToEvent.unsubscribeAll();this.itemArrowFromEvent.unsubscribeAll();this.itemSelectEvent.unsubscribeAll();this.unmatchedItemSelectEvent.unsubscribeAll();this.selectionEnforceEvent.unsubscribeAll();this.containerCollapseEvent.unsubscribeAll();this.textboxBlurEvent.unsubscribeAll();this.textboxChangeEvent.unsubscribeAll();YAHOO.util.Event.purgeElement(A,true);YAHOO.util.Event.purgeElement(D,true);D.innerHTML="";for(var C in this){if(YAHOO.lang.hasOwnProperty(this,C)){this[C]=null;}}};YAHOO.widget.AutoComplete.prototype.textboxFocusEvent=null;YAHOO.widget.AutoComplete.prototype.textboxKeyEvent=null;YAHOO.widget.AutoComplete.prototype.dataRequestEvent=null;YAHOO.widget.AutoComplete.prototype.dataReturnEvent=null;YAHOO.widget.AutoComplete.prototype.dataErrorEvent=null;YAHOO.widget.AutoComplete.prototype.containerPopulateEvent=null;YAHOO.widget.AutoComplete.prototype.containerExpandEvent=null;YAHOO.widget.AutoComplete.prototype.typeAheadEvent=null;YAHOO.widget.AutoComplete.prototype.itemMouseOverEvent=null;YAHOO.widget.AutoComplete.prototype.itemMouseOutEvent=null;
-YAHOO.widget.AutoComplete.prototype.itemArrowToEvent=null;YAHOO.widget.AutoComplete.prototype.itemArrowFromEvent=null;YAHOO.widget.AutoComplete.prototype.itemSelectEvent=null;YAHOO.widget.AutoComplete.prototype.unmatchedItemSelectEvent=null;YAHOO.widget.AutoComplete.prototype.selectionEnforceEvent=null;YAHOO.widget.AutoComplete.prototype.containerCollapseEvent=null;YAHOO.widget.AutoComplete.prototype.textboxBlurEvent=null;YAHOO.widget.AutoComplete.prototype.textboxChangeEvent=null;YAHOO.widget.AutoComplete._nIndex=0;YAHOO.widget.AutoComplete.prototype._sName=null;YAHOO.widget.AutoComplete.prototype._elTextbox=null;YAHOO.widget.AutoComplete.prototype._elContainer=null;YAHOO.widget.AutoComplete.prototype._elContent=null;YAHOO.widget.AutoComplete.prototype._elHeader=null;YAHOO.widget.AutoComplete.prototype._elBody=null;YAHOO.widget.AutoComplete.prototype._elFooter=null;YAHOO.widget.AutoComplete.prototype._elShadow=null;YAHOO.widget.AutoComplete.prototype._elIFrame=null;YAHOO.widget.AutoComplete.prototype._bFocused=false;YAHOO.widget.AutoComplete.prototype._oAnim=null;YAHOO.widget.AutoComplete.prototype._bContainerOpen=false;YAHOO.widget.AutoComplete.prototype._bOverContainer=false;YAHOO.widget.AutoComplete.prototype._elList=null;YAHOO.widget.AutoComplete.prototype._nDisplayedItems=0;YAHOO.widget.AutoComplete.prototype._sCurQuery=null;YAHOO.widget.AutoComplete.prototype._sPastSelections="";YAHOO.widget.AutoComplete.prototype._sInitInputValue=null;YAHOO.widget.AutoComplete.prototype._elCurListItem=null;YAHOO.widget.AutoComplete.prototype._elCurPrehighlightItem=null;YAHOO.widget.AutoComplete.prototype._bItemSelected=false;YAHOO.widget.AutoComplete.prototype._nKeyCode=null;YAHOO.widget.AutoComplete.prototype._nDelayID=-1;YAHOO.widget.AutoComplete.prototype._nTypeAheadDelayID=-1;YAHOO.widget.AutoComplete.prototype._iFrameSrc="javascript:false;";YAHOO.widget.AutoComplete.prototype._queryInterval=null;YAHOO.widget.AutoComplete.prototype._sLastTextboxValue=null;YAHOO.widget.AutoComplete.prototype._initProps=function(){var B=this.minQueryLength;if(!YAHOO.lang.isNumber(B)){this.minQueryLength=1;}var E=this.maxResultsDisplayed;if(!YAHOO.lang.isNumber(E)||(E<1)){this.maxResultsDisplayed=10;}var F=this.queryDelay;if(!YAHOO.lang.isNumber(F)||(F<0)){this.queryDelay=0.2;}var C=this.typeAheadDelay;if(!YAHOO.lang.isNumber(C)||(C<0)){this.typeAheadDelay=0.2;}var A=this.delimChar;if(YAHOO.lang.isString(A)&&(A.length>0)){this.delimChar=[A];}else{if(!YAHOO.lang.isArray(A)){this.delimChar=null;}}var D=this.animSpeed;if((this.animHoriz||this.animVert)&&YAHOO.util.Anim){if(!YAHOO.lang.isNumber(D)||(D<0)){this.animSpeed=0.3;}if(!this._oAnim){this._oAnim=new YAHOO.util.Anim(this._elContent,{},this.animSpeed);}else{this._oAnim.duration=this.animSpeed;}}if(this.forceSelection&&A){}};YAHOO.widget.AutoComplete.prototype._initContainerHelperEls=function(){if(this.useShadow&&!this._elShadow){var A=document.createElement("div");A.className="yui-ac-shadow";A.style.width=0;A.style.height=0;this._elShadow=this._elContainer.appendChild(A);}if(this.useIFrame&&!this._elIFrame){var B=document.createElement("iframe");B.src=this._iFrameSrc;B.frameBorder=0;B.scrolling="no";B.style.position="absolute";B.style.width=0;B.style.height=0;B.style.padding=0;B.tabIndex=-1;B.role="presentation";B.title="Presentational iframe shim";this._elIFrame=this._elContainer.appendChild(B);}};YAHOO.widget.AutoComplete.prototype._initContainerEl=function(){YAHOO.util.Dom.addClass(this._elContainer,"yui-ac-container");if(!this._elContent){var C=document.createElement("div");C.className="yui-ac-content";C.style.display="none";this._elContent=this._elContainer.appendChild(C);var B=document.createElement("div");B.className="yui-ac-hd";B.style.display="none";this._elHeader=this._elContent.appendChild(B);var D=document.createElement("div");D.className="yui-ac-bd";this._elBody=this._elContent.appendChild(D);var A=document.createElement("div");A.className="yui-ac-ft";A.style.display="none";this._elFooter=this._elContent.appendChild(A);}else{}};YAHOO.widget.AutoComplete.prototype._initListEl=function(){var C=this.maxResultsDisplayed,A=this._elList||document.createElement("ul"),B;while(A.childNodes.length<C){B=document.createElement("li");B.style.display="none";B._nItemIndex=A.childNodes.length;A.appendChild(B);}if(!this._elList){var D=this._elBody;YAHOO.util.Event.purgeElement(D,true);D.innerHTML="";this._elList=D.appendChild(A);}this._elBody.style.display="";};YAHOO.widget.AutoComplete.prototype._focus=function(){var A=this;setTimeout(function(){try{A._elTextbox.focus();}catch(B){}},0);};YAHOO.widget.AutoComplete.prototype._enableIntervalDetection=function(){var A=this;if(!A._queryInterval&&A.queryInterval){A._queryInterval=setInterval(function(){A._onInterval();},A.queryInterval);}};YAHOO.widget.AutoComplete.prototype.enableIntervalDetection=YAHOO.widget.AutoComplete.prototype._enableIntervalDetection;YAHOO.widget.AutoComplete.prototype._onInterval=function(){var A=this._elTextbox.value;var B=this._sLastTextboxValue;if(A!=B){this._sLastTextboxValue=A;this._sendQuery(A);}};YAHOO.widget.AutoComplete.prototype._clearInterval=function(){if(this._queryInterval){clearInterval(this._queryInterval);this._queryInterval=null;}};YAHOO.widget.AutoComplete.prototype._isIgnoreKey=function(A){if((A==9)||(A==13)||(A==16)||(A==17)||(A>=18&&A<=20)||(A==27)||(A>=33&&A<=35)||(A>=36&&A<=40)||(A>=44&&A<=45)||(A==229)){return true;}return false;};YAHOO.widget.AutoComplete.prototype._sendQuery=function(D){if(this.minQueryLength<0){this._toggleContainer(false);return;}if(this.delimChar){var A=this._extractQuery(D);D=A.query;this._sPastSelections=A.previous;}if((D&&(D.length<this.minQueryLength))||(!D&&this.minQueryLength>0)){if(this._nDelayID!=-1){clearTimeout(this._nDelayID);}this._toggleContainer(false);return;}D=encodeURIComponent(D);this._nDelayID=-1;if(this.dataSource.queryMatchSubset||this.queryMatchSubset){var C=this.getSubsetMatches(D);if(C){this.handleResponse(D,C,{query:D});return;
-}}if(this.dataSource.responseStripAfter){this.dataSource.doBeforeParseData=this.preparseRawResponse;}if(this.applyLocalFilter){this.dataSource.doBeforeCallback=this.filterResults;}var B=this.generateRequest(D);this.dataRequestEvent.fire(this,D,B);this.dataSource.sendRequest(B,{success:this.handleResponse,failure:this.handleResponse,scope:this,argument:{query:D}});};YAHOO.widget.AutoComplete.prototype._populateListItem=function(B,A,C){B.innerHTML=this.formatResult(A,C,B._sResultMatch);};YAHOO.widget.AutoComplete.prototype._populateList=function(K,F,C){if(this._nTypeAheadDelayID!=-1){clearTimeout(this._nTypeAheadDelayID);}K=(C&&C.query)?C.query:K;var H=this.doBeforeLoadData(K,F,C);if(H&&!F.error){this.dataReturnEvent.fire(this,K,F.results);if(this._bFocused){var M=decodeURIComponent(K);this._sCurQuery=M;this._bItemSelected=false;var R=F.results,A=Math.min(R.length,this.maxResultsDisplayed),J=(this.dataSource.responseSchema.fields)?(this.dataSource.responseSchema.fields[0].key||this.dataSource.responseSchema.fields[0]):0;if(A>0){if(!this._elList||(this._elList.childNodes.length<A)){this._initListEl();}this._initContainerHelperEls();var I=this._elList.childNodes;for(var Q=A-1;Q>=0;Q--){var P=I[Q],E=R[Q];if(this.resultTypeList){var B=[];B[0]=(YAHOO.lang.isString(E))?E:E[J]||E[this.key];var L=this.dataSource.responseSchema.fields;if(YAHOO.lang.isArray(L)&&(L.length>1)){for(var N=1,S=L.length;N<S;N++){B[B.length]=E[L[N].key||L[N]];}}else{if(YAHOO.lang.isArray(E)){B=E;}else{if(YAHOO.lang.isString(E)){B=[E];}else{B[1]=E;}}}E=B;}P._sResultMatch=(YAHOO.lang.isString(E))?E:(YAHOO.lang.isArray(E))?E[0]:(E[J]||"");P._oResultData=E;this._populateListItem(P,E,M);P.style.display="";}if(A<I.length){var G;for(var O=I.length-1;O>=A;O--){G=I[O];G.style.display="none";}}this._nDisplayedItems=A;this.containerPopulateEvent.fire(this,K,R);if(this.autoHighlight){var D=this._elList.firstChild;this._toggleHighlight(D,"to");this.itemArrowToEvent.fire(this,D);this._typeAhead(D,K);}else{this._toggleHighlight(this._elCurListItem,"from");}H=this._doBeforeExpandContainer(this._elTextbox,this._elContainer,K,R);this._toggleContainer(H);}else{this._toggleContainer(false);}return;}}else{this.dataErrorEvent.fire(this,K,F);}};YAHOO.widget.AutoComplete.prototype._doBeforeExpandContainer=function(D,A,C,B){if(this.autoSnapContainer){this.snapContainer();}return this.doBeforeExpandContainer(D,A,C,B);};YAHOO.widget.AutoComplete.prototype._clearSelection=function(){var A=(this.delimChar)?this._extractQuery(this._elTextbox.value):{previous:"",query:this._elTextbox.value};this._elTextbox.value=A.previous;this.selectionEnforceEvent.fire(this,A.query);};YAHOO.widget.AutoComplete.prototype._textMatchesOption=function(){var A=null;for(var B=0;B<this._nDisplayedItems;B++){var C=this._elList.childNodes[B];var D=(""+C._sResultMatch).toLowerCase();if(D==this._sCurQuery.toLowerCase()){A=C;break;}}return(A);};YAHOO.widget.AutoComplete.prototype._typeAhead=function(B,D){if(!this.typeAhead||(this._nKeyCode==8)){return;}var A=this,C=this._elTextbox;if(C.setSelectionRange||C.createTextRange){this._nTypeAheadDelayID=setTimeout(function(){var F=C.value.length;A._updateValue(B);var G=C.value.length;A._selectText(C,F,G);var E=C.value.substr(F,G);A.typeAheadEvent.fire(A,D,E);},(this.typeAheadDelay*1000));}};YAHOO.widget.AutoComplete.prototype._selectText=function(D,A,B){if(D.setSelectionRange){D.setSelectionRange(A,B);}else{if(D.createTextRange){var C=D.createTextRange();C.moveStart("character",A);C.moveEnd("character",B-D.value.length);C.select();}else{D.select();}}};YAHOO.widget.AutoComplete.prototype._extractQuery=function(H){var C=this.delimChar,F=-1,G,E,B=C.length-1,D;for(;B>=0;B--){G=H.lastIndexOf(C[B]);if(G>F){F=G;}}if(C[B]==" "){for(var A=C.length-1;A>=0;A--){if(H[F-1]==C[A]){F--;break;}}}if(F>-1){E=F+1;while(H.charAt(E)==" "){E+=1;}D=H.substring(0,E);H=H.substr(E);}else{D="";}return{previous:D,query:H};};YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers=function(D){var E=this._elContent.offsetWidth+"px";var B=this._elContent.offsetHeight+"px";if(this.useIFrame&&this._elIFrame){var C=this._elIFrame;if(D){C.style.width=E;C.style.height=B;C.style.padding="";}else{C.style.width=0;C.style.height=0;C.style.padding=0;}}if(this.useShadow&&this._elShadow){var A=this._elShadow;if(D){A.style.width=E;A.style.height=B;}else{A.style.width=0;A.style.height=0;}}};YAHOO.widget.AutoComplete.prototype._toggleContainer=function(I){var D=this._elContainer;if(this.alwaysShowContainer&&this._bContainerOpen){return;}if(!I){this._toggleHighlight(this._elCurListItem,"from");this._nDisplayedItems=0;this._sCurQuery=null;if(this._elContent.style.display=="none"){return;}}var A=this._oAnim;if(A&&A.getEl()&&(this.animHoriz||this.animVert)){if(A.isAnimated()){A.stop(true);}var G=this._elContent.cloneNode(true);D.appendChild(G);G.style.top="-9000px";G.style.width="";G.style.height="";G.style.display="";var F=G.offsetWidth;var C=G.offsetHeight;var B=(this.animHoriz)?0:F;var E=(this.animVert)?0:C;A.attributes=(I)?{width:{to:F},height:{to:C}}:{width:{to:B},height:{to:E}};if(I&&!this._bContainerOpen){this._elContent.style.width=B+"px";this._elContent.style.height=E+"px";}else{this._elContent.style.width=F+"px";this._elContent.style.height=C+"px";}D.removeChild(G);G=null;var H=this;var J=function(){A.onComplete.unsubscribeAll();if(I){H._toggleContainerHelpers(true);H._bContainerOpen=I;H.containerExpandEvent.fire(H);}else{H._elContent.style.display="none";H._bContainerOpen=I;H.containerCollapseEvent.fire(H);}};this._toggleContainerHelpers(false);this._elContent.style.display="";A.onComplete.subscribe(J);A.animate();}else{if(I){this._elContent.style.display="";this._toggleContainerHelpers(true);this._bContainerOpen=I;this.containerExpandEvent.fire(this);}else{this._toggleContainerHelpers(false);this._elContent.style.display="none";this._bContainerOpen=I;this.containerCollapseEvent.fire(this);}}};YAHOO.widget.AutoComplete.prototype._toggleHighlight=function(A,C){if(A){var B=this.highlightClassName;
-if(this._elCurListItem){YAHOO.util.Dom.removeClass(this._elCurListItem,B);this._elCurListItem=null;}if((C=="to")&&B){YAHOO.util.Dom.addClass(A,B);this._elCurListItem=A;}}};YAHOO.widget.AutoComplete.prototype._togglePrehighlight=function(B,C){var A=this.prehighlightClassName;if(this._elCurPrehighlightItem){YAHOO.util.Dom.removeClass(this._elCurPrehighlightItem,A);}if(B==this._elCurListItem){return;}if((C=="mouseover")&&A){YAHOO.util.Dom.addClass(B,A);this._elCurPrehighlightItem=B;}else{YAHOO.util.Dom.removeClass(B,A);}};YAHOO.widget.AutoComplete.prototype._updateValue=function(C){if(!this.suppressInputUpdate){var F=this._elTextbox;var E=(this.delimChar)?(this.delimChar[0]||this.delimChar):null;var B=C._sResultMatch;var D="";if(E){D=this._sPastSelections;D+=B+E;if(E!=" "){D+=" ";}}else{D=B;}F.value=D;if(F.type=="textarea"){F.scrollTop=F.scrollHeight;}var A=F.value.length;this._selectText(F,A,A);this._elCurListItem=C;}};YAHOO.widget.AutoComplete.prototype._selectItem=function(A){this._bItemSelected=true;this._updateValue(A);this._sPastSelections=this._elTextbox.value;this._clearInterval();this.itemSelectEvent.fire(this,A,A._oResultData);this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype._jumpSelection=function(){if(this._elCurListItem){this._selectItem(this._elCurListItem);}else{this._toggleContainer(false);}};YAHOO.widget.AutoComplete.prototype._moveSelection=function(G){if(this._bContainerOpen){var H=this._elCurListItem,D=-1;if(H){D=H._nItemIndex;}var E=(G==40)?(D+1):(D-1);if(E<-2||E>=this._nDisplayedItems){return;}if(H){this._toggleHighlight(H,"from");this.itemArrowFromEvent.fire(this,H);}if(E==-1){if(this.delimChar){this._elTextbox.value=this._sPastSelections+this._sCurQuery;}else{this._elTextbox.value=this._sCurQuery;}return;}if(E==-2){this._toggleContainer(false);return;}var F=this._elList.childNodes[E],B=this._elContent,C=YAHOO.util.Dom.getStyle(B,"overflow"),I=YAHOO.util.Dom.getStyle(B,"overflowY"),A=((C=="auto")||(C=="scroll")||(I=="auto")||(I=="scroll"));if(A&&(E>-1)&&(E<this._nDisplayedItems)){if(G==40){if((F.offsetTop+F.offsetHeight)>(B.scrollTop+B.offsetHeight)){B.scrollTop=(F.offsetTop+F.offsetHeight)-B.offsetHeight;}else{if((F.offsetTop+F.offsetHeight)<B.scrollTop){B.scrollTop=F.offsetTop;}}}else{if(F.offsetTop<B.scrollTop){this._elContent.scrollTop=F.offsetTop;}else{if(F.offsetTop>(B.scrollTop+B.offsetHeight)){this._elContent.scrollTop=(F.offsetTop+F.offsetHeight)-B.offsetHeight;}}}}this._toggleHighlight(F,"to");this.itemArrowToEvent.fire(this,F);if(this.typeAhead){this._updateValue(F);}}};YAHOO.widget.AutoComplete.prototype._onContainerMouseover=function(A,C){var D=YAHOO.util.Event.getTarget(A);var B=D.nodeName.toLowerCase();while(D&&(B!="table")){switch(B){case"body":return;case"li":if(C.prehighlightClassName){C._togglePrehighlight(D,"mouseover");}else{C._toggleHighlight(D,"to");}C.itemMouseOverEvent.fire(C,D);break;case"div":if(YAHOO.util.Dom.hasClass(D,"yui-ac-container")){C._bOverContainer=true;return;}break;default:break;}D=D.parentNode;if(D){B=D.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerMouseout=function(A,C){var D=YAHOO.util.Event.getTarget(A);var B=D.nodeName.toLowerCase();while(D&&(B!="table")){switch(B){case"body":return;case"li":if(C.prehighlightClassName){C._togglePrehighlight(D,"mouseout");}else{C._toggleHighlight(D,"from");}C.itemMouseOutEvent.fire(C,D);break;case"ul":C._toggleHighlight(C._elCurListItem,"to");break;case"div":if(YAHOO.util.Dom.hasClass(D,"yui-ac-container")){C._bOverContainer=false;return;}break;default:break;}D=D.parentNode;if(D){B=D.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerClick=function(A,C){var D=YAHOO.util.Event.getTarget(A);var B=D.nodeName.toLowerCase();while(D&&(B!="table")){switch(B){case"body":return;case"li":C._toggleHighlight(D,"to");C._selectItem(D);return;default:break;}D=D.parentNode;if(D){B=D.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerScroll=function(A,B){B._focus();};YAHOO.widget.AutoComplete.prototype._onContainerResize=function(A,B){B._toggleContainerHelpers(B._bContainerOpen);};YAHOO.widget.AutoComplete.prototype._onTextboxKeyDown=function(A,B){var C=A.keyCode;if(B._nTypeAheadDelayID!=-1){clearTimeout(B._nTypeAheadDelayID);}switch(C){case 9:if(!YAHOO.env.ua.opera&&(navigator.userAgent.toLowerCase().indexOf("mac")==-1)||(YAHOO.env.ua.webkit>420)){if(B._elCurListItem){if(B.delimChar&&(B._nKeyCode!=C)){if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);}}B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;case 13:if(!YAHOO.env.ua.opera&&(navigator.userAgent.toLowerCase().indexOf("mac")==-1)||(YAHOO.env.ua.webkit>420)){if(B._elCurListItem){if(B._nKeyCode!=C){if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);}}B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;case 27:B._toggleContainer(false);return;case 39:B._jumpSelection();break;case 38:if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);B._moveSelection(C);}break;case 40:if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);B._moveSelection(C);}break;default:B._bItemSelected=false;B._toggleHighlight(B._elCurListItem,"from");B.textboxKeyEvent.fire(B,C);break;}if(C===18){B._enableIntervalDetection();}B._nKeyCode=C;};YAHOO.widget.AutoComplete.prototype._onTextboxKeyPress=function(A,B){var C=A.keyCode;if(YAHOO.env.ua.opera||(navigator.userAgent.toLowerCase().indexOf("mac")!=-1)&&(YAHOO.env.ua.webkit<420)){switch(C){case 9:if(B._bContainerOpen){if(B.delimChar){YAHOO.util.Event.stopEvent(A);}if(B._elCurListItem){B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;case 13:if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);if(B._elCurListItem){B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;default:break;}}else{if(C==229){B._enableIntervalDetection();}}};YAHOO.widget.AutoComplete.prototype._onTextboxKeyUp=function(A,C){var B=this.value;C._initProps();var D=A.keyCode;if(C._isIgnoreKey(D)){return;
-}if(C._nDelayID!=-1){clearTimeout(C._nDelayID);}C._nDelayID=setTimeout(function(){C._sendQuery(B);},(C.queryDelay*1000));};YAHOO.widget.AutoComplete.prototype._onTextboxFocus=function(A,B){if(!B._bFocused){B._elTextbox.setAttribute("autocomplete","off");B._bFocused=true;B._sInitInputValue=B._elTextbox.value;B.textboxFocusEvent.fire(B);}};YAHOO.widget.AutoComplete.prototype._onTextboxBlur=function(A,C){if(!C._bOverContainer||(C._nKeyCode==9)){if(!C._bItemSelected){var B=C._textMatchesOption();if(!C._bContainerOpen||(C._bContainerOpen&&(B===null))){if(C.forceSelection){C._clearSelection();}else{C.unmatchedItemSelectEvent.fire(C,C._sCurQuery);}}else{if(C.forceSelection){C._selectItem(B);}}}C._clearInterval();C._bFocused=false;if(C._sInitInputValue!==C._elTextbox.value){C.textboxChangeEvent.fire(C);}C.textboxBlurEvent.fire(C);C._toggleContainer(false);}else{C._focus();}};YAHOO.widget.AutoComplete.prototype._onWindowUnload=function(A,B){if(B&&B._elTextbox&&B.allowBrowserAutocomplete){B._elTextbox.setAttribute("autocomplete","on");}};YAHOO.widget.AutoComplete.prototype.doBeforeSendQuery=function(A){return this.generateRequest(A);};YAHOO.widget.AutoComplete.prototype.getListItems=function(){var C=[],B=this._elList.childNodes;for(var A=B.length-1;A>=0;A--){C[A]=B[A];}return C;};YAHOO.widget.AutoComplete._cloneObject=function(D){if(!YAHOO.lang.isValue(D)){return D;}var F={};if(YAHOO.lang.isFunction(D)){F=D;}else{if(YAHOO.lang.isArray(D)){var E=[];for(var C=0,B=D.length;C<B;C++){E[C]=YAHOO.widget.AutoComplete._cloneObject(D[C]);}F=E;}else{if(YAHOO.lang.isObject(D)){for(var A in D){if(YAHOO.lang.hasOwnProperty(D,A)){if(YAHOO.lang.isValue(D[A])&&YAHOO.lang.isObject(D[A])||YAHOO.lang.isArray(D[A])){F[A]=YAHOO.widget.AutoComplete._cloneObject(D[A]);}else{F[A]=D[A];}}}}else{F=D;}}}return F;};YAHOO.register("autocomplete",YAHOO.widget.AutoComplete,{version:"2.8.2r1",build:"7"});/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.2r1
-*/
-(function(){YAHOO.util.Config=function(D){if(D){this.init(D);}};var B=YAHOO.lang,C=YAHOO.util.CustomEvent,A=YAHOO.util.Config;A.CONFIG_CHANGED_EVENT="configChanged";A.BOOLEAN_TYPE="boolean";A.prototype={owner:null,queueInProgress:false,config:null,initialConfig:null,eventQueue:null,configChangedEvent:null,init:function(D){this.owner=D;this.configChangedEvent=this.createEvent(A.CONFIG_CHANGED_EVENT);this.configChangedEvent.signature=C.LIST;this.queueInProgress=false;this.config={};this.initialConfig={};this.eventQueue=[];},checkBoolean:function(D){return(typeof D==A.BOOLEAN_TYPE);},checkNumber:function(D){return(!isNaN(D));},fireEvent:function(D,F){var E=this.config[D];if(E&&E.event){E.event.fire(F);}},addProperty:function(E,D){E=E.toLowerCase();this.config[E]=D;D.event=this.createEvent(E,{scope:this.owner});D.event.signature=C.LIST;D.key=E;if(D.handler){D.event.subscribe(D.handler,this.owner);}this.setProperty(E,D.value,true);if(!D.suppressEvent){this.queueProperty(E,D.value);}},getConfig:function(){var D={},F=this.config,G,E;for(G in F){if(B.hasOwnProperty(F,G)){E=F[G];if(E&&E.event){D[G]=E.value;}}}return D;},getProperty:function(D){var E=this.config[D.toLowerCase()];if(E&&E.event){return E.value;}else{return undefined;}},resetProperty:function(D){D=D.toLowerCase();var E=this.config[D];if(E&&E.event){if(this.initialConfig[D]&&!B.isUndefined(this.initialConfig[D])){this.setProperty(D,this.initialConfig[D]);return true;}}else{return false;}},setProperty:function(E,G,D){var F;E=E.toLowerCase();if(this.queueInProgress&&!D){this.queueProperty(E,G);return true;}else{F=this.config[E];if(F&&F.event){if(F.validator&&!F.validator(G)){return false;}else{F.value=G;if(!D){this.fireEvent(E,G);this.configChangedEvent.fire([E,G]);}return true;}}else{return false;}}},queueProperty:function(S,P){S=S.toLowerCase();var R=this.config[S],K=false,J,G,H,I,O,Q,F,M,N,D,L,T,E;if(R&&R.event){if(!B.isUndefined(P)&&R.validator&&!R.validator(P)){return false;}else{if(!B.isUndefined(P)){R.value=P;}else{P=R.value;}K=false;J=this.eventQueue.length;for(L=0;L<J;L++){G=this.eventQueue[L];if(G){H=G[0];I=G[1];if(H==S){this.eventQueue[L]=null;this.eventQueue.push([S,(!B.isUndefined(P)?P:I)]);K=true;break;}}}if(!K&&!B.isUndefined(P)){this.eventQueue.push([S,P]);}}if(R.supercedes){O=R.supercedes.length;for(T=0;T<O;T++){Q=R.supercedes[T];F=this.eventQueue.length;for(E=0;E<F;E++){M=this.eventQueue[E];if(M){N=M[0];D=M[1];if(N==Q.toLowerCase()){this.eventQueue.push([N,D]);this.eventQueue[E]=null;break;}}}}}return true;}else{return false;}},refireEvent:function(D){D=D.toLowerCase();var E=this.config[D];if(E&&E.event&&!B.isUndefined(E.value)){if(this.queueInProgress){this.queueProperty(D);}else{this.fireEvent(D,E.value);}}},applyConfig:function(D,G){var F,E;if(G){E={};for(F in D){if(B.hasOwnProperty(D,F)){E[F.toLowerCase()]=D[F];}}this.initialConfig=E;}for(F in D){if(B.hasOwnProperty(D,F)){this.queueProperty(F,D[F]);}}},refresh:function(){var D;for(D in this.config){if(B.hasOwnProperty(this.config,D)){this.refireEvent(D);}}},fireQueue:function(){var E,H,D,G,F;this.queueInProgress=true;for(E=0;E<this.eventQueue.length;E++){H=this.eventQueue[E];if(H){D=H[0];G=H[1];F=this.config[D];F.value=G;this.eventQueue[E]=null;this.fireEvent(D,G);}}this.queueInProgress=false;this.eventQueue=[];},subscribeToConfigEvent:function(D,E,G,H){var F=this.config[D.toLowerCase()];if(F&&F.event){if(!A.alreadySubscribed(F.event,E,G)){F.event.subscribe(E,G,H);}return true;}else{return false;}},unsubscribeFromConfigEvent:function(D,E,G){var F=this.config[D.toLowerCase()];if(F&&F.event){return F.event.unsubscribe(E,G);}else{return false;}},toString:function(){var D="Config";if(this.owner){D+=" ["+this.owner.toString()+"]";}return D;},outputEventQueue:function(){var D="",G,E,F=this.eventQueue.length;for(E=0;E<F;E++){G=this.eventQueue[E];if(G){D+=G[0]+"="+G[1]+", ";}}return D;},destroy:function(){var E=this.config,D,F;for(D in E){if(B.hasOwnProperty(E,D)){F=E[D];F.event.unsubscribeAll();F.event=null;}}this.configChangedEvent.unsubscribeAll();this.configChangedEvent=null;this.owner=null;this.config=null;this.initialConfig=null;this.eventQueue=null;}};A.alreadySubscribed=function(E,H,I){var F=E.subscribers.length,D,G;if(F>0){G=F-1;do{D=E.subscribers[G];if(D&&D.obj==I&&D.fn==H){return true;}}while(G--);}return false;};YAHOO.lang.augmentProto(A,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Module=function(R,Q){if(R){this.init(R,Q);}else{}};var F=YAHOO.util.Dom,D=YAHOO.util.Config,N=YAHOO.util.Event,M=YAHOO.util.CustomEvent,G=YAHOO.widget.Module,I=YAHOO.env.ua,H,P,O,E,A={"BEFORE_INIT":"beforeInit","INIT":"init","APPEND":"append","BEFORE_RENDER":"beforeRender","RENDER":"render","CHANGE_HEADER":"changeHeader","CHANGE_BODY":"changeBody","CHANGE_FOOTER":"changeFooter","CHANGE_CONTENT":"changeContent","DESTROY":"destroy","BEFORE_SHOW":"beforeShow","SHOW":"show","BEFORE_HIDE":"beforeHide","HIDE":"hide"},J={"VISIBLE":{key:"visible",value:true,validator:YAHOO.lang.isBoolean},"EFFECT":{key:"effect",suppressEvent:true,supercedes:["visible"]},"MONITOR_RESIZE":{key:"monitorresize",value:true},"APPEND_TO_DOCUMENT_BODY":{key:"appendtodocumentbody",value:false}};G.IMG_ROOT=null;G.IMG_ROOT_SSL=null;G.CSS_MODULE="yui-module";G.CSS_HEADER="hd";G.CSS_BODY="bd";G.CSS_FOOTER="ft";G.RESIZE_MONITOR_SECURE_URL="javascript:false;";G.RESIZE_MONITOR_BUFFER=1;G.textResizeEvent=new M("textResize");G.forceDocumentRedraw=function(){var Q=document.documentElement;if(Q){Q.className+=" ";Q.className=YAHOO.lang.trim(Q.className);}};function L(){if(!H){H=document.createElement("div");H.innerHTML=('<div class="'+G.CSS_HEADER+'"></div>'+'<div class="'+G.CSS_BODY+'"></div><div class="'+G.CSS_FOOTER+'"></div>');P=H.firstChild;O=P.nextSibling;E=O.nextSibling;}return H;}function K(){if(!P){L();}return(P.cloneNode(false));}function B(){if(!O){L();}return(O.cloneNode(false));}function C(){if(!E){L();}return(E.cloneNode(false));}G.prototype={constructor:G,element:null,header:null,body:null,footer:null,id:null,imageRoot:G.IMG_ROOT,initEvents:function(){var Q=M.LIST;
-this.beforeInitEvent=this.createEvent(A.BEFORE_INIT);this.beforeInitEvent.signature=Q;this.initEvent=this.createEvent(A.INIT);this.initEvent.signature=Q;this.appendEvent=this.createEvent(A.APPEND);this.appendEvent.signature=Q;this.beforeRenderEvent=this.createEvent(A.BEFORE_RENDER);this.beforeRenderEvent.signature=Q;this.renderEvent=this.createEvent(A.RENDER);this.renderEvent.signature=Q;this.changeHeaderEvent=this.createEvent(A.CHANGE_HEADER);this.changeHeaderEvent.signature=Q;this.changeBodyEvent=this.createEvent(A.CHANGE_BODY);this.changeBodyEvent.signature=Q;this.changeFooterEvent=this.createEvent(A.CHANGE_FOOTER);this.changeFooterEvent.signature=Q;this.changeContentEvent=this.createEvent(A.CHANGE_CONTENT);this.changeContentEvent.signature=Q;this.destroyEvent=this.createEvent(A.DESTROY);this.destroyEvent.signature=Q;this.beforeShowEvent=this.createEvent(A.BEFORE_SHOW);this.beforeShowEvent.signature=Q;this.showEvent=this.createEvent(A.SHOW);this.showEvent.signature=Q;this.beforeHideEvent=this.createEvent(A.BEFORE_HIDE);this.beforeHideEvent.signature=Q;this.hideEvent=this.createEvent(A.HIDE);this.hideEvent.signature=Q;},platform:function(){var Q=navigator.userAgent.toLowerCase();if(Q.indexOf("windows")!=-1||Q.indexOf("win32")!=-1){return"windows";}else{if(Q.indexOf("macintosh")!=-1){return"mac";}else{return false;}}}(),browser:function(){var Q=navigator.userAgent.toLowerCase();if(Q.indexOf("opera")!=-1){return"opera";}else{if(Q.indexOf("msie 7")!=-1){return"ie7";}else{if(Q.indexOf("msie")!=-1){return"ie";}else{if(Q.indexOf("safari")!=-1){return"safari";}else{if(Q.indexOf("gecko")!=-1){return"gecko";}else{return false;}}}}}}(),isSecure:function(){if(window.location.href.toLowerCase().indexOf("https")===0){return true;}else{return false;}}(),initDefaultConfig:function(){this.cfg.addProperty(J.VISIBLE.key,{handler:this.configVisible,value:J.VISIBLE.value,validator:J.VISIBLE.validator});this.cfg.addProperty(J.EFFECT.key,{suppressEvent:J.EFFECT.suppressEvent,supercedes:J.EFFECT.supercedes});this.cfg.addProperty(J.MONITOR_RESIZE.key,{handler:this.configMonitorResize,value:J.MONITOR_RESIZE.value});this.cfg.addProperty(J.APPEND_TO_DOCUMENT_BODY.key,{value:J.APPEND_TO_DOCUMENT_BODY.value});},init:function(V,U){var S,W;this.initEvents();this.beforeInitEvent.fire(G);this.cfg=new D(this);if(this.isSecure){this.imageRoot=G.IMG_ROOT_SSL;}if(typeof V=="string"){S=V;V=document.getElementById(V);if(!V){V=(L()).cloneNode(false);V.id=S;}}this.id=F.generateId(V);this.element=V;W=this.element.firstChild;if(W){var R=false,Q=false,T=false;do{if(1==W.nodeType){if(!R&&F.hasClass(W,G.CSS_HEADER)){this.header=W;R=true;}else{if(!Q&&F.hasClass(W,G.CSS_BODY)){this.body=W;Q=true;}else{if(!T&&F.hasClass(W,G.CSS_FOOTER)){this.footer=W;T=true;}}}}}while((W=W.nextSibling));}this.initDefaultConfig();F.addClass(this.element,G.CSS_MODULE);if(U){this.cfg.applyConfig(U,true);}if(!D.alreadySubscribed(this.renderEvent,this.cfg.fireQueue,this.cfg)){this.renderEvent.subscribe(this.cfg.fireQueue,this.cfg,true);}this.initEvent.fire(G);},initResizeMonitor:function(){var R=(I.gecko&&this.platform=="windows");if(R){var Q=this;setTimeout(function(){Q._initResizeMonitor();},0);}else{this._initResizeMonitor();}},_initResizeMonitor:function(){var Q,S,U;function W(){G.textResizeEvent.fire();}if(!I.opera){S=F.get("_yuiResizeMonitor");var V=this._supportsCWResize();if(!S){S=document.createElement("iframe");if(this.isSecure&&G.RESIZE_MONITOR_SECURE_URL&&I.ie){S.src=G.RESIZE_MONITOR_SECURE_URL;}if(!V){U=["<html><head><script ",'type="text/javascript">',"window.onresize=function(){window.parent.","YAHOO.widget.Module.textResizeEvent.","fire();};<","/script></head>","<body></body></html>"].join("");S.src="data:text/html;charset=utf-8,"+encodeURIComponent(U);}S.id="_yuiResizeMonitor";S.title="Text Resize Monitor";S.style.position="absolute";S.style.visibility="hidden";var R=document.body,T=R.firstChild;if(T){R.insertBefore(S,T);}else{R.appendChild(S);}S.style.backgroundColor="transparent";S.style.borderWidth="0";S.style.width="2em";S.style.height="2em";S.style.left="0";S.style.top=(-1*(S.offsetHeight+G.RESIZE_MONITOR_BUFFER))+"px";S.style.visibility="visible";if(I.webkit){Q=S.contentWindow.document;Q.open();Q.close();}}if(S&&S.contentWindow){G.textResizeEvent.subscribe(this.onDomResize,this,true);if(!G.textResizeInitialized){if(V){if(!N.on(S.contentWindow,"resize",W)){N.on(S,"resize",W);}}G.textResizeInitialized=true;}this.resizeMonitor=S;}}},_supportsCWResize:function(){var Q=true;if(I.gecko&&I.gecko<=1.8){Q=false;}return Q;},onDomResize:function(S,R){var Q=-1*(this.resizeMonitor.offsetHeight+G.RESIZE_MONITOR_BUFFER);this.resizeMonitor.style.top=Q+"px";this.resizeMonitor.style.left="0";},setHeader:function(R){var Q=this.header||(this.header=K());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderHeader();}this.changeHeaderEvent.fire(R);this.changeContentEvent.fire();},appendToHeader:function(R){var Q=this.header||(this.header=K());Q.appendChild(R);this.changeHeaderEvent.fire(R);this.changeContentEvent.fire();},setBody:function(R){var Q=this.body||(this.body=B());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderBody();}this.changeBodyEvent.fire(R);this.changeContentEvent.fire();},appendToBody:function(R){var Q=this.body||(this.body=B());Q.appendChild(R);this.changeBodyEvent.fire(R);this.changeContentEvent.fire();},setFooter:function(R){var Q=this.footer||(this.footer=C());if(R.nodeName){Q.innerHTML="";Q.appendChild(R);}else{Q.innerHTML=R;}if(this._rendered){this._renderFooter();}this.changeFooterEvent.fire(R);this.changeContentEvent.fire();},appendToFooter:function(R){var Q=this.footer||(this.footer=C());Q.appendChild(R);this.changeFooterEvent.fire(R);this.changeContentEvent.fire();},render:function(S,Q){var T=this;function R(U){if(typeof U=="string"){U=document.getElementById(U);}if(U){T._addToParent(U,T.element);T.appendEvent.fire();}}this.beforeRenderEvent.fire();
-if(!Q){Q=this.element;}if(S){R(S);}else{if(!F.inDocument(this.element)){return false;}}this._renderHeader(Q);this._renderBody(Q);this._renderFooter(Q);this._rendered=true;this.renderEvent.fire();return true;},_renderHeader:function(Q){Q=Q||this.element;if(this.header&&!F.inDocument(this.header)){var R=Q.firstChild;if(R){Q.insertBefore(this.header,R);}else{Q.appendChild(this.header);}}},_renderBody:function(Q){Q=Q||this.element;if(this.body&&!F.inDocument(this.body)){if(this.footer&&F.isAncestor(Q,this.footer)){Q.insertBefore(this.body,this.footer);}else{Q.appendChild(this.body);}}},_renderFooter:function(Q){Q=Q||this.element;if(this.footer&&!F.inDocument(this.footer)){Q.appendChild(this.footer);}},destroy:function(){var Q;if(this.element){N.purgeElement(this.element,true);Q=this.element.parentNode;}if(Q){Q.removeChild(this.element);}this.element=null;this.header=null;this.body=null;this.footer=null;G.textResizeEvent.unsubscribe(this.onDomResize,this);this.cfg.destroy();this.cfg=null;this.destroyEvent.fire();},show:function(){this.cfg.setProperty("visible",true);},hide:function(){this.cfg.setProperty("visible",false);},configVisible:function(R,Q,S){var T=Q[0];if(T){this.beforeShowEvent.fire();F.setStyle(this.element,"display","block");this.showEvent.fire();}else{this.beforeHideEvent.fire();F.setStyle(this.element,"display","none");this.hideEvent.fire();}},configMonitorResize:function(S,R,T){var Q=R[0];if(Q){this.initResizeMonitor();}else{G.textResizeEvent.unsubscribe(this.onDomResize,this,true);this.resizeMonitor=null;}},_addToParent:function(Q,R){if(!this.cfg.getProperty("appendtodocumentbody")&&Q===document.body&&Q.firstChild){Q.insertBefore(R,Q.firstChild);}else{Q.appendChild(R);}},toString:function(){return"Module "+this.id;}};YAHOO.lang.augmentProto(G,YAHOO.util.EventProvider);}());(function(){YAHOO.widget.Overlay=function(P,O){YAHOO.widget.Overlay.superclass.constructor.call(this,P,O);};var I=YAHOO.lang,M=YAHOO.util.CustomEvent,G=YAHOO.widget.Module,N=YAHOO.util.Event,F=YAHOO.util.Dom,D=YAHOO.util.Config,K=YAHOO.env.ua,B=YAHOO.widget.Overlay,H="subscribe",E="unsubscribe",C="contained",J,A={"BEFORE_MOVE":"beforeMove","MOVE":"move"},L={"X":{key:"x",validator:I.isNumber,suppressEvent:true,supercedes:["iframe"]},"Y":{key:"y",validator:I.isNumber,suppressEvent:true,supercedes:["iframe"]},"XY":{key:"xy",suppressEvent:true,supercedes:["iframe"]},"CONTEXT":{key:"context",suppressEvent:true,supercedes:["iframe"]},"FIXED_CENTER":{key:"fixedcenter",value:false,supercedes:["iframe","visible"]},"WIDTH":{key:"width",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"HEIGHT":{key:"height",suppressEvent:true,supercedes:["context","fixedcenter","iframe"]},"AUTO_FILL_HEIGHT":{key:"autofillheight",supercedes:["height"],value:"body"},"ZINDEX":{key:"zindex",value:null},"CONSTRAIN_TO_VIEWPORT":{key:"constraintoviewport",value:false,validator:I.isBoolean,supercedes:["iframe","x","y","xy"]},"IFRAME":{key:"iframe",value:(K.ie==6?true:false),validator:I.isBoolean,supercedes:["zindex"]},"PREVENT_CONTEXT_OVERLAP":{key:"preventcontextoverlap",value:false,validator:I.isBoolean,supercedes:["constraintoviewport"]}};B.IFRAME_SRC="javascript:false;";B.IFRAME_OFFSET=3;B.VIEWPORT_OFFSET=10;B.TOP_LEFT="tl";B.TOP_RIGHT="tr";B.BOTTOM_LEFT="bl";B.BOTTOM_RIGHT="br";B.PREVENT_OVERLAP_X={"tltr":true,"blbr":true,"brbl":true,"trtl":true};B.PREVENT_OVERLAP_Y={"trbr":true,"tlbl":true,"bltl":true,"brtr":true};B.CSS_OVERLAY="yui-overlay";B.CSS_HIDDEN="yui-overlay-hidden";B.CSS_IFRAME="yui-overlay-iframe";B.STD_MOD_RE=/^\s*?(body|footer|header)\s*?$/i;B.windowScrollEvent=new M("windowScroll");B.windowResizeEvent=new M("windowResize");B.windowScrollHandler=function(P){var O=N.getTarget(P);if(!O||O===window||O===window.document){if(K.ie){if(!window.scrollEnd){window.scrollEnd=-1;}clearTimeout(window.scrollEnd);window.scrollEnd=setTimeout(function(){B.windowScrollEvent.fire();},1);}else{B.windowScrollEvent.fire();}}};B.windowResizeHandler=function(O){if(K.ie){if(!window.resizeEnd){window.resizeEnd=-1;}clearTimeout(window.resizeEnd);window.resizeEnd=setTimeout(function(){B.windowResizeEvent.fire();},100);}else{B.windowResizeEvent.fire();}};B._initialized=null;if(B._initialized===null){N.on(window,"scroll",B.windowScrollHandler);N.on(window,"resize",B.windowResizeHandler);B._initialized=true;}B._TRIGGER_MAP={"windowScroll":B.windowScrollEvent,"windowResize":B.windowResizeEvent,"textResize":G.textResizeEvent};YAHOO.extend(B,G,{CONTEXT_TRIGGERS:[],init:function(P,O){B.superclass.init.call(this,P);this.beforeInitEvent.fire(B);F.addClass(this.element,B.CSS_OVERLAY);if(O){this.cfg.applyConfig(O,true);}if(this.platform=="mac"&&K.gecko){if(!D.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)){this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);}if(!D.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)){this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);}}this.initEvent.fire(B);},initEvents:function(){B.superclass.initEvents.call(this);var O=M.LIST;this.beforeMoveEvent=this.createEvent(A.BEFORE_MOVE);this.beforeMoveEvent.signature=O;this.moveEvent=this.createEvent(A.MOVE);this.moveEvent.signature=O;},initDefaultConfig:function(){B.superclass.initDefaultConfig.call(this);var O=this.cfg;O.addProperty(L.X.key,{handler:this.configX,validator:L.X.validator,suppressEvent:L.X.suppressEvent,supercedes:L.X.supercedes});O.addProperty(L.Y.key,{handler:this.configY,validator:L.Y.validator,suppressEvent:L.Y.suppressEvent,supercedes:L.Y.supercedes});O.addProperty(L.XY.key,{handler:this.configXY,suppressEvent:L.XY.suppressEvent,supercedes:L.XY.supercedes});O.addProperty(L.CONTEXT.key,{handler:this.configContext,suppressEvent:L.CONTEXT.suppressEvent,supercedes:L.CONTEXT.supercedes});O.addProperty(L.FIXED_CENTER.key,{handler:this.configFixedCenter,value:L.FIXED_CENTER.value,validator:L.FIXED_CENTER.validator,supercedes:L.FIXED_CENTER.supercedes});O.addProperty(L.WIDTH.key,{handler:this.configWidth,suppressEvent:L.WIDTH.suppressEvent,supercedes:L.WIDTH.supercedes});
-O.addProperty(L.HEIGHT.key,{handler:this.configHeight,suppressEvent:L.HEIGHT.suppressEvent,supercedes:L.HEIGHT.supercedes});O.addProperty(L.AUTO_FILL_HEIGHT.key,{handler:this.configAutoFillHeight,value:L.AUTO_FILL_HEIGHT.value,validator:this._validateAutoFill,supercedes:L.AUTO_FILL_HEIGHT.supercedes});O.addProperty(L.ZINDEX.key,{handler:this.configzIndex,value:L.ZINDEX.value});O.addProperty(L.CONSTRAIN_TO_VIEWPORT.key,{handler:this.configConstrainToViewport,value:L.CONSTRAIN_TO_VIEWPORT.value,validator:L.CONSTRAIN_TO_VIEWPORT.validator,supercedes:L.CONSTRAIN_TO_VIEWPORT.supercedes});O.addProperty(L.IFRAME.key,{handler:this.configIframe,value:L.IFRAME.value,validator:L.IFRAME.validator,supercedes:L.IFRAME.supercedes});O.addProperty(L.PREVENT_CONTEXT_OVERLAP.key,{value:L.PREVENT_CONTEXT_OVERLAP.value,validator:L.PREVENT_CONTEXT_OVERLAP.validator,supercedes:L.PREVENT_CONTEXT_OVERLAP.supercedes});},moveTo:function(O,P){this.cfg.setProperty("xy",[O,P]);},hideMacGeckoScrollbars:function(){F.replaceClass(this.element,"show-scrollbars","hide-scrollbars");},showMacGeckoScrollbars:function(){F.replaceClass(this.element,"hide-scrollbars","show-scrollbars");},_setDomVisibility:function(O){F.setStyle(this.element,"visibility",(O)?"visible":"hidden");var P=B.CSS_HIDDEN;if(O){F.removeClass(this.element,P);}else{F.addClass(this.element,P);}},configVisible:function(R,O,X){var Q=O[0],S=F.getStyle(this.element,"visibility"),Y=this.cfg.getProperty("effect"),V=[],U=(this.platform=="mac"&&K.gecko),g=D.alreadySubscribed,W,P,f,c,b,a,d,Z,T;if(S=="inherit"){f=this.element.parentNode;while(f.nodeType!=9&&f.nodeType!=11){S=F.getStyle(f,"visibility");if(S!="inherit"){break;}f=f.parentNode;}if(S=="inherit"){S="visible";}}if(Y){if(Y instanceof Array){Z=Y.length;for(c=0;c<Z;c++){W=Y[c];V[V.length]=W.effect(this,W.duration);}}else{V[V.length]=Y.effect(this,Y.duration);}}if(Q){if(U){this.showMacGeckoScrollbars();}if(Y){if(Q){if(S!="visible"||S===""){this.beforeShowEvent.fire();T=V.length;for(b=0;b<T;b++){P=V[b];if(b===0&&!g(P.animateInCompleteEvent,this.showEvent.fire,this.showEvent)){P.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true);}P.animateIn();}}}}else{if(S!="visible"||S===""){this.beforeShowEvent.fire();this._setDomVisibility(true);this.cfg.refireEvent("iframe");this.showEvent.fire();}else{this._setDomVisibility(true);}}}else{if(U){this.hideMacGeckoScrollbars();}if(Y){if(S=="visible"){this.beforeHideEvent.fire();T=V.length;for(a=0;a<T;a++){d=V[a];if(a===0&&!g(d.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)){d.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true);}d.animateOut();}}else{if(S===""){this._setDomVisibility(false);}}}else{if(S=="visible"||S===""){this.beforeHideEvent.fire();this._setDomVisibility(false);this.hideEvent.fire();}else{this._setDomVisibility(false);}}}},doCenterOnDOMEvent:function(){var O=this.cfg,P=O.getProperty("fixedcenter");if(O.getProperty("visible")){if(P&&(P!==C||this.fitsInViewport())){this.center();}}},fitsInViewport:function(){var S=B.VIEWPORT_OFFSET,Q=this.element,T=Q.offsetWidth,R=Q.offsetHeight,O=F.getViewportWidth(),P=F.getViewportHeight();return((T+S<O)&&(R+S<P));},configFixedCenter:function(S,Q,T){var U=Q[0],P=D.alreadySubscribed,R=B.windowResizeEvent,O=B.windowScrollEvent;if(U){this.center();if(!P(this.beforeShowEvent,this.center)){this.beforeShowEvent.subscribe(this.center);}if(!P(R,this.doCenterOnDOMEvent,this)){R.subscribe(this.doCenterOnDOMEvent,this,true);}if(!P(O,this.doCenterOnDOMEvent,this)){O.subscribe(this.doCenterOnDOMEvent,this,true);}}else{this.beforeShowEvent.unsubscribe(this.center);R.unsubscribe(this.doCenterOnDOMEvent,this);O.unsubscribe(this.doCenterOnDOMEvent,this);}},configHeight:function(R,P,S){var O=P[0],Q=this.element;F.setStyle(Q,"height",O);this.cfg.refireEvent("iframe");},configAutoFillHeight:function(T,S,P){var V=S[0],Q=this.cfg,U="autofillheight",W="height",R=Q.getProperty(U),O=this._autoFillOnHeightChange;Q.unsubscribeFromConfigEvent(W,O);G.textResizeEvent.unsubscribe(O);this.changeContentEvent.unsubscribe(O);if(R&&V!==R&&this[R]){F.setStyle(this[R],W,"");}if(V){V=I.trim(V.toLowerCase());Q.subscribeToConfigEvent(W,O,this[V],this);G.textResizeEvent.subscribe(O,this[V],this);this.changeContentEvent.subscribe(O,this[V],this);Q.setProperty(U,V,true);}},configWidth:function(R,O,S){var Q=O[0],P=this.element;F.setStyle(P,"width",Q);this.cfg.refireEvent("iframe");},configzIndex:function(Q,O,R){var S=O[0],P=this.element;if(!S){S=F.getStyle(P,"zIndex");if(!S||isNaN(S)){S=0;}}if(this.iframe||this.cfg.getProperty("iframe")===true){if(S<=0){S=1;}}F.setStyle(P,"zIndex",S);this.cfg.setProperty("zIndex",S,true);if(this.iframe){this.stackIframe();}},configXY:function(Q,P,R){var T=P[0],O=T[0],S=T[1];this.cfg.setProperty("x",O);this.cfg.setProperty("y",S);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},configX:function(Q,P,R){var O=P[0],S=this.cfg.getProperty("y");this.cfg.setProperty("x",O,true);this.cfg.setProperty("y",S,true);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");F.setX(this.element,O,true);this.cfg.setProperty("xy",[O,S],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},configY:function(Q,P,R){var O=this.cfg.getProperty("x"),S=P[0];this.cfg.setProperty("x",O,true);this.cfg.setProperty("y",S,true);this.beforeMoveEvent.fire([O,S]);O=this.cfg.getProperty("x");S=this.cfg.getProperty("y");F.setY(this.element,S,true);this.cfg.setProperty("xy",[O,S],true);this.cfg.refireEvent("iframe");this.moveEvent.fire([O,S]);},showIframe:function(){var P=this.iframe,O;if(P){O=this.element.parentNode;if(O!=P.parentNode){this._addToParent(O,P);}P.style.display="block";}},hideIframe:function(){if(this.iframe){this.iframe.style.display="none";}},syncIframe:function(){var O=this.iframe,Q=this.element,S=B.IFRAME_OFFSET,P=(S*2),R;if(O){O.style.width=(Q.offsetWidth+P+"px");
-O.style.height=(Q.offsetHeight+P+"px");R=this.cfg.getProperty("xy");if(!I.isArray(R)||(isNaN(R[0])||isNaN(R[1]))){this.syncPosition();R=this.cfg.getProperty("xy");}F.setXY(O,[(R[0]-S),(R[1]-S)]);}},stackIframe:function(){if(this.iframe){var O=F.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(O)&&!isNaN(O)){F.setStyle(this.iframe,"zIndex",(O-1));}}},configIframe:function(R,Q,S){var O=Q[0];function T(){var V=this.iframe,W=this.element,X;if(!V){if(!J){J=document.createElement("iframe");if(this.isSecure){J.src=B.IFRAME_SRC;}if(K.ie){J.style.filter="alpha(opacity=0)";J.frameBorder=0;}else{J.style.opacity="0";}J.style.position="absolute";J.style.border="none";J.style.margin="0";J.style.padding="0";J.style.display="none";J.tabIndex=-1;J.className=B.CSS_IFRAME;}V=J.cloneNode(false);V.id=this.id+"_f";X=W.parentNode;var U=X||document.body;this._addToParent(U,V);this.iframe=V;}this.showIframe();this.syncIframe();this.stackIframe();if(!this._hasIframeEventListeners){this.showEvent.subscribe(this.showIframe);this.hideEvent.subscribe(this.hideIframe);this.changeContentEvent.subscribe(this.syncIframe);this._hasIframeEventListeners=true;}}function P(){T.call(this);this.beforeShowEvent.unsubscribe(P);this._iframeDeferred=false;}if(O){if(this.cfg.getProperty("visible")){T.call(this);}else{if(!this._iframeDeferred){this.beforeShowEvent.subscribe(P);this._iframeDeferred=true;}}}else{this.hideIframe();if(this._hasIframeEventListeners){this.showEvent.unsubscribe(this.showIframe);this.hideEvent.unsubscribe(this.hideIframe);this.changeContentEvent.unsubscribe(this.syncIframe);this._hasIframeEventListeners=false;}}},_primeXYFromDOM:function(){if(YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))){this.syncPosition();this.cfg.refireEvent("xy");this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);}},configConstrainToViewport:function(P,O,Q){var R=O[0];if(R){if(!D.alreadySubscribed(this.beforeMoveEvent,this.enforceConstraints,this)){this.beforeMoveEvent.subscribe(this.enforceConstraints,this,true);}if(!D.alreadySubscribed(this.beforeShowEvent,this._primeXYFromDOM)){this.beforeShowEvent.subscribe(this._primeXYFromDOM);}}else{this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);this.beforeMoveEvent.unsubscribe(this.enforceConstraints,this);}},configContext:function(U,T,Q){var X=T[0],R,O,V,S,P,W=this.CONTEXT_TRIGGERS;if(X){R=X[0];O=X[1];V=X[2];S=X[3];P=X[4];if(W&&W.length>0){S=(S||[]).concat(W);}if(R){if(typeof R=="string"){this.cfg.setProperty("context",[document.getElementById(R),O,V,S,P],true);}if(O&&V){this.align(O,V,P);}if(this._contextTriggers){this._processTriggers(this._contextTriggers,E,this._alignOnTrigger);}if(S){this._processTriggers(S,H,this._alignOnTrigger);this._contextTriggers=S;}}}},_alignOnTrigger:function(P,O){this.align();},_findTriggerCE:function(O){var P=null;if(O instanceof M){P=O;}else{if(B._TRIGGER_MAP[O]){P=B._TRIGGER_MAP[O];}}return P;},_processTriggers:function(S,U,R){var Q,T;for(var P=0,O=S.length;P<O;++P){Q=S[P];T=this._findTriggerCE(Q);if(T){T[U](R,this,true);}else{this[U](Q,R);}}},align:function(P,W,S){var V=this.cfg.getProperty("context"),T=this,O,Q,U;function R(Z,a){var Y=null,X=null;switch(P){case B.TOP_LEFT:Y=a;X=Z;break;case B.TOP_RIGHT:Y=a-Q.offsetWidth;X=Z;break;case B.BOTTOM_LEFT:Y=a;X=Z-Q.offsetHeight;break;case B.BOTTOM_RIGHT:Y=a-Q.offsetWidth;X=Z-Q.offsetHeight;break;}if(Y!==null&&X!==null){if(S){Y+=S[0];X+=S[1];}T.moveTo(Y,X);}}if(V){O=V[0];Q=this.element;T=this;if(!P){P=V[1];}if(!W){W=V[2];}if(!S&&V[4]){S=V[4];}if(Q&&O){U=F.getRegion(O);switch(W){case B.TOP_LEFT:R(U.top,U.left);break;case B.TOP_RIGHT:R(U.top,U.right);break;case B.BOTTOM_LEFT:R(U.bottom,U.left);break;case B.BOTTOM_RIGHT:R(U.bottom,U.right);break;}}}},enforceConstraints:function(P,O,Q){var S=O[0];var R=this.getConstrainedXY(S[0],S[1]);this.cfg.setProperty("x",R[0],true);this.cfg.setProperty("y",R[1],true);this.cfg.setProperty("xy",R,true);},_getConstrainedPos:function(X,P){var T=this.element,R=B.VIEWPORT_OFFSET,Z=(X=="x"),Y=(Z)?T.offsetWidth:T.offsetHeight,S=(Z)?F.getViewportWidth():F.getViewportHeight(),c=(Z)?F.getDocumentScrollLeft():F.getDocumentScrollTop(),b=(Z)?B.PREVENT_OVERLAP_X:B.PREVENT_OVERLAP_Y,O=this.cfg.getProperty("context"),U=(Y+R<S),W=this.cfg.getProperty("preventcontextoverlap")&&O&&b[(O[1]+O[2])],V=c+R,a=c+S-Y-R,Q=P;if(P<V||P>a){if(W){Q=this._preventOverlap(X,O[0],Y,S,c);}else{if(U){if(P<V){Q=V;}else{if(P>a){Q=a;}}}else{Q=V;}}}return Q;},_preventOverlap:function(X,W,Y,U,b){var Z=(X=="x"),T=B.VIEWPORT_OFFSET,S=this,Q=((Z)?F.getX(W):F.getY(W))-b,O=(Z)?W.offsetWidth:W.offsetHeight,P=Q-T,R=(U-(Q+O))-T,c=false,V=function(){var d;if((S.cfg.getProperty(X)-b)>Q){d=(Q-Y);}else{d=(Q+O);}S.cfg.setProperty(X,(d+b),true);return d;},a=function(){var e=((S.cfg.getProperty(X)-b)>Q)?R:P,d;if(Y>e){if(c){V();}else{V();c=true;d=a();}}return d;};a();return this.cfg.getProperty(X);},getConstrainedX:function(O){return this._getConstrainedPos("x",O);},getConstrainedY:function(O){return this._getConstrainedPos("y",O);},getConstrainedXY:function(O,P){return[this.getConstrainedX(O),this.getConstrainedY(P)];},center:function(){var R=B.VIEWPORT_OFFSET,S=this.element.offsetWidth,Q=this.element.offsetHeight,P=F.getViewportWidth(),T=F.getViewportHeight(),O,U;if(S<P){O=(P/2)-(S/2)+F.getDocumentScrollLeft();}else{O=R+F.getDocumentScrollLeft();}if(Q<T){U=(T/2)-(Q/2)+F.getDocumentScrollTop();}else{U=R+F.getDocumentScrollTop();}this.cfg.setProperty("xy",[parseInt(O,10),parseInt(U,10)]);this.cfg.refireEvent("iframe");if(K.webkit){this.forceContainerRedraw();}},syncPosition:function(){var O=F.getXY(this.element);this.cfg.setProperty("x",O[0],true);this.cfg.setProperty("y",O[1],true);this.cfg.setProperty("xy",O,true);},onDomResize:function(Q,P){var O=this;B.superclass.onDomResize.call(this,Q,P);setTimeout(function(){O.syncPosition();O.cfg.refireEvent("iframe");O.cfg.refireEvent("context");},0);},_getComputedHeight:(function(){if(document.defaultView&&document.defaultView.getComputedStyle){return function(P){var O=null;
-if(P.ownerDocument&&P.ownerDocument.defaultView){var Q=P.ownerDocument.defaultView.getComputedStyle(P,"");if(Q){O=parseInt(Q.height,10);}}return(I.isNumber(O))?O:null;};}else{return function(P){var O=null;if(P.style.pixelHeight){O=P.style.pixelHeight;}return(I.isNumber(O))?O:null;};}})(),_validateAutoFillHeight:function(O){return(!O)||(I.isString(O)&&B.STD_MOD_RE.test(O));},_autoFillOnHeightChange:function(R,P,Q){var O=this.cfg.getProperty("height");if((O&&O!=="auto")||(O===0)){this.fillHeight(Q);}},_getPreciseHeight:function(P){var O=P.offsetHeight;if(P.getBoundingClientRect){var Q=P.getBoundingClientRect();O=Q.bottom-Q.top;}return O;},fillHeight:function(R){if(R){var P=this.innerElement||this.element,O=[this.header,this.body,this.footer],V,W=0,X=0,T=0,Q=false;for(var U=0,S=O.length;U<S;U++){V=O[U];if(V){if(R!==V){X+=this._getPreciseHeight(V);}else{Q=true;}}}if(Q){if(K.ie||K.opera){F.setStyle(R,"height",0+"px");}W=this._getComputedHeight(P);if(W===null){F.addClass(P,"yui-override-padding");W=P.clientHeight;F.removeClass(P,"yui-override-padding");}T=Math.max(W-X,0);F.setStyle(R,"height",T+"px");if(R.offsetHeight!=T){T=Math.max(T-(R.offsetHeight-T),0);}F.setStyle(R,"height",T+"px");}}},bringToTop:function(){var S=[],R=this.element;function V(Z,Y){var b=F.getStyle(Z,"zIndex"),a=F.getStyle(Y,"zIndex"),X=(!b||isNaN(b))?0:parseInt(b,10),W=(!a||isNaN(a))?0:parseInt(a,10);if(X>W){return -1;}else{if(X<W){return 1;}else{return 0;}}}function Q(Y){var X=F.hasClass(Y,B.CSS_OVERLAY),W=YAHOO.widget.Panel;if(X&&!F.isAncestor(R,Y)){if(W&&F.hasClass(Y,W.CSS_PANEL)){S[S.length]=Y.parentNode;}else{S[S.length]=Y;}}}F.getElementsBy(Q,"DIV",document.body);S.sort(V);var O=S[0],U;if(O){U=F.getStyle(O,"zIndex");if(!isNaN(U)){var T=false;if(O!=R){T=true;}else{if(S.length>1){var P=F.getStyle(S[1],"zIndex");if(!isNaN(P)&&(U==P)){T=true;}}}if(T){this.cfg.setProperty("zindex",(parseInt(U,10)+2));}}}},destroy:function(){if(this.iframe){this.iframe.parentNode.removeChild(this.iframe);}this.iframe=null;B.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent,this);B.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent,this);G.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);if(this._contextTriggers){this._processTriggers(this._contextTriggers,E,this._alignOnTrigger);}B.superclass.destroy.call(this);},forceContainerRedraw:function(){var O=this;F.addClass(O.element,"yui-force-redraw");setTimeout(function(){F.removeClass(O.element,"yui-force-redraw");},0);},toString:function(){return"Overlay "+this.id;}});}());(function(){YAHOO.widget.OverlayManager=function(G){this.init(G);};var D=YAHOO.widget.Overlay,C=YAHOO.util.Event,E=YAHOO.util.Dom,B=YAHOO.util.Config,F=YAHOO.util.CustomEvent,A=YAHOO.widget.OverlayManager;A.CSS_FOCUSED="focused";A.prototype={constructor:A,overlays:null,initDefaultConfig:function(){this.cfg.addProperty("overlays",{suppressEvent:true});this.cfg.addProperty("focusevent",{value:"mousedown"});},init:function(I){this.cfg=new B(this);this.initDefaultConfig();if(I){this.cfg.applyConfig(I,true);}this.cfg.fireQueue();var H=null;this.getActive=function(){return H;};this.focus=function(J){var K=this.find(J);if(K){K.focus();}};this.remove=function(K){var M=this.find(K),J;if(M){if(H==M){H=null;}var L=(M.element===null&&M.cfg===null)?true:false;if(!L){J=E.getStyle(M.element,"zIndex");M.cfg.setProperty("zIndex",-1000,true);}this.overlays.sort(this.compareZIndexDesc);this.overlays=this.overlays.slice(0,(this.overlays.length-1));M.hideEvent.unsubscribe(M.blur);M.destroyEvent.unsubscribe(this._onOverlayDestroy,M);M.focusEvent.unsubscribe(this._onOverlayFocusHandler,M);M.blurEvent.unsubscribe(this._onOverlayBlurHandler,M);if(!L){C.removeListener(M.element,this.cfg.getProperty("focusevent"),this._onOverlayElementFocus);M.cfg.setProperty("zIndex",J,true);M.cfg.setProperty("manager",null);}if(M.focusEvent._managed){M.focusEvent=null;}if(M.blurEvent._managed){M.blurEvent=null;}if(M.focus._managed){M.focus=null;}if(M.blur._managed){M.blur=null;}}};this.blurAll=function(){var K=this.overlays.length,J;if(K>0){J=K-1;do{this.overlays[J].blur();}while(J--);}};this._manageBlur=function(J){var K=false;if(H==J){E.removeClass(H.element,A.CSS_FOCUSED);H=null;K=true;}return K;};this._manageFocus=function(J){var K=false;if(H!=J){if(H){H.blur();}H=J;this.bringToTop(H);E.addClass(H.element,A.CSS_FOCUSED);K=true;}return K;};var G=this.cfg.getProperty("overlays");if(!this.overlays){this.overlays=[];}if(G){this.register(G);this.overlays.sort(this.compareZIndexDesc);}},_onOverlayElementFocus:function(I){var G=C.getTarget(I),H=this.close;if(H&&(G==H||E.isAncestor(H,G))){this.blur();}else{this.focus();}},_onOverlayDestroy:function(H,G,I){this.remove(I);},_onOverlayFocusHandler:function(H,G,I){this._manageFocus(I);},_onOverlayBlurHandler:function(H,G,I){this._manageBlur(I);},_bindFocus:function(G){var H=this;if(!G.focusEvent){G.focusEvent=G.createEvent("focus");G.focusEvent.signature=F.LIST;G.focusEvent._managed=true;}else{G.focusEvent.subscribe(H._onOverlayFocusHandler,G,H);}if(!G.focus){C.on(G.element,H.cfg.getProperty("focusevent"),H._onOverlayElementFocus,null,G);G.focus=function(){if(H._manageFocus(this)){if(this.cfg.getProperty("visible")&&this.focusFirst){this.focusFirst();}this.focusEvent.fire();}};G.focus._managed=true;}},_bindBlur:function(G){var H=this;if(!G.blurEvent){G.blurEvent=G.createEvent("blur");G.blurEvent.signature=F.LIST;G.focusEvent._managed=true;}else{G.blurEvent.subscribe(H._onOverlayBlurHandler,G,H);}if(!G.blur){G.blur=function(){if(H._manageBlur(this)){this.blurEvent.fire();}};G.blur._managed=true;}G.hideEvent.subscribe(G.blur);},_bindDestroy:function(G){var H=this;G.destroyEvent.subscribe(H._onOverlayDestroy,G,H);},_syncZIndex:function(G){var H=E.getStyle(G.element,"zIndex");if(!isNaN(H)){G.cfg.setProperty("zIndex",parseInt(H,10));}else{G.cfg.setProperty("zIndex",0);}},register:function(G){var J=false,H,I;if(G instanceof D){G.cfg.addProperty("manager",{value:this});this._bindFocus(G);this._bindBlur(G);this._bindDestroy(G);
-this._syncZIndex(G);this.overlays.push(G);this.bringToTop(G);J=true;}else{if(G instanceof Array){for(H=0,I=G.length;H<I;H++){J=this.register(G[H])||J;}}}return J;},bringToTop:function(M){var I=this.find(M),L,G,J;if(I){J=this.overlays;J.sort(this.compareZIndexDesc);G=J[0];if(G){L=E.getStyle(G.element,"zIndex");if(!isNaN(L)){var K=false;if(G!==I){K=true;}else{if(J.length>1){var H=E.getStyle(J[1].element,"zIndex");if(!isNaN(H)&&(L==H)){K=true;}}}if(K){I.cfg.setProperty("zindex",(parseInt(L,10)+2));}}J.sort(this.compareZIndexDesc);}}},find:function(G){var K=G instanceof D,I=this.overlays,M=I.length,J=null,L,H;if(K||typeof G=="string"){for(H=M-1;H>=0;H--){L=I[H];if((K&&(L===G))||(L.id==G)){J=L;break;}}}return J;},compareZIndexDesc:function(J,I){var H=(J.cfg)?J.cfg.getProperty("zIndex"):null,G=(I.cfg)?I.cfg.getProperty("zIndex"):null;if(H===null&&G===null){return 0;}else{if(H===null){return 1;}else{if(G===null){return -1;}else{if(H>G){return -1;}else{if(H<G){return 1;}else{return 0;}}}}}},showAll:function(){var H=this.overlays,I=H.length,G;for(G=I-1;G>=0;G--){H[G].show();}},hideAll:function(){var H=this.overlays,I=H.length,G;for(G=I-1;G>=0;G--){H[G].hide();}},toString:function(){return"OverlayManager";}};}());(function(){YAHOO.widget.Tooltip=function(P,O){YAHOO.widget.Tooltip.superclass.constructor.call(this,P,O);};var E=YAHOO.lang,N=YAHOO.util.Event,M=YAHOO.util.CustomEvent,C=YAHOO.util.Dom,J=YAHOO.widget.Tooltip,H=YAHOO.env.ua,G=(H.ie&&(H.ie<=6||document.compatMode=="BackCompat")),F,I={"PREVENT_OVERLAP":{key:"preventoverlap",value:true,validator:E.isBoolean,supercedes:["x","y","xy"]},"SHOW_DELAY":{key:"showdelay",value:200,validator:E.isNumber},"AUTO_DISMISS_DELAY":{key:"autodismissdelay",value:5000,validator:E.isNumber},"HIDE_DELAY":{key:"hidedelay",value:250,validator:E.isNumber},"TEXT":{key:"text",suppressEvent:true},"CONTAINER":{key:"container"},"DISABLED":{key:"disabled",value:false,suppressEvent:true},"XY_OFFSET":{key:"xyoffset",value:[0,25],suppressEvent:true}},A={"CONTEXT_MOUSE_OVER":"contextMouseOver","CONTEXT_MOUSE_OUT":"contextMouseOut","CONTEXT_TRIGGER":"contextTrigger"};J.CSS_TOOLTIP="yui-tt";function K(Q,O){var P=this.cfg,R=P.getProperty("width");if(R==O){P.setProperty("width",Q);}}function D(P,O){if("_originalWidth" in this){K.call(this,this._originalWidth,this._forcedWidth);}var Q=document.body,U=this.cfg,T=U.getProperty("width"),R,S;if((!T||T=="auto")&&(U.getProperty("container")!=Q||U.getProperty("x")>=C.getViewportWidth()||U.getProperty("y")>=C.getViewportHeight())){S=this.element.cloneNode(true);S.style.visibility="hidden";S.style.top="0px";S.style.left="0px";Q.appendChild(S);R=(S.offsetWidth+"px");Q.removeChild(S);S=null;U.setProperty("width",R);U.refireEvent("xy");this._originalWidth=T||"";this._forcedWidth=R;}}function B(P,O,Q){this.render(Q);}function L(){N.onDOMReady(B,this.cfg.getProperty("container"),this);}YAHOO.extend(J,YAHOO.widget.Overlay,{init:function(P,O){J.superclass.init.call(this,P);this.beforeInitEvent.fire(J);C.addClass(this.element,J.CSS_TOOLTIP);if(O){this.cfg.applyConfig(O,true);}this.cfg.queueProperty("visible",false);this.cfg.queueProperty("constraintoviewport",true);this.setBody("");this.subscribe("changeContent",D);this.subscribe("init",L);this.subscribe("render",this.onRender);this.initEvent.fire(J);},initEvents:function(){J.superclass.initEvents.call(this);var O=M.LIST;this.contextMouseOverEvent=this.createEvent(A.CONTEXT_MOUSE_OVER);this.contextMouseOverEvent.signature=O;this.contextMouseOutEvent=this.createEvent(A.CONTEXT_MOUSE_OUT);this.contextMouseOutEvent.signature=O;this.contextTriggerEvent=this.createEvent(A.CONTEXT_TRIGGER);this.contextTriggerEvent.signature=O;},initDefaultConfig:function(){J.superclass.initDefaultConfig.call(this);this.cfg.addProperty(I.PREVENT_OVERLAP.key,{value:I.PREVENT_OVERLAP.value,validator:I.PREVENT_OVERLAP.validator,supercedes:I.PREVENT_OVERLAP.supercedes});this.cfg.addProperty(I.SHOW_DELAY.key,{handler:this.configShowDelay,value:200,validator:I.SHOW_DELAY.validator});this.cfg.addProperty(I.AUTO_DISMISS_DELAY.key,{handler:this.configAutoDismissDelay,value:I.AUTO_DISMISS_DELAY.value,validator:I.AUTO_DISMISS_DELAY.validator});this.cfg.addProperty(I.HIDE_DELAY.key,{handler:this.configHideDelay,value:I.HIDE_DELAY.value,validator:I.HIDE_DELAY.validator});this.cfg.addProperty(I.TEXT.key,{handler:this.configText,suppressEvent:I.TEXT.suppressEvent});this.cfg.addProperty(I.CONTAINER.key,{handler:this.configContainer,value:document.body});this.cfg.addProperty(I.DISABLED.key,{handler:this.configContainer,value:I.DISABLED.value,supressEvent:I.DISABLED.suppressEvent});this.cfg.addProperty(I.XY_OFFSET.key,{value:I.XY_OFFSET.value.concat(),supressEvent:I.XY_OFFSET.suppressEvent});},configText:function(P,O,Q){var R=O[0];if(R){this.setBody(R);}},configContainer:function(Q,P,R){var O=P[0];if(typeof O=="string"){this.cfg.setProperty("container",document.getElementById(O),true);}},_removeEventListeners:function(){var R=this._context,O,Q,P;if(R){O=R.length;if(O>0){P=O-1;do{Q=R[P];N.removeListener(Q,"mouseover",this.onContextMouseOver);N.removeListener(Q,"mousemove",this.onContextMouseMove);N.removeListener(Q,"mouseout",this.onContextMouseOut);}while(P--);}}},configContext:function(T,P,U){var S=P[0],V,O,R,Q;if(S){if(!(S instanceof Array)){if(typeof S=="string"){this.cfg.setProperty("context",[document.getElementById(S)],true);}else{this.cfg.setProperty("context",[S],true);}S=this.cfg.getProperty("context");}this._removeEventListeners();this._context=S;V=this._context;if(V){O=V.length;if(O>0){Q=O-1;do{R=V[Q];N.on(R,"mouseover",this.onContextMouseOver,this);N.on(R,"mousemove",this.onContextMouseMove,this);N.on(R,"mouseout",this.onContextMouseOut,this);}while(Q--);}}}},onContextMouseMove:function(P,O){O.pageX=N.getPageX(P);O.pageY=N.getPageY(P);},onContextMouseOver:function(Q,P){var O=this;if(O.title){P._tempTitle=O.title;O.title="";}if(P.fireEvent("contextMouseOver",O,Q)!==false&&!P.cfg.getProperty("disabled")){if(P.hideProcId){clearTimeout(P.hideProcId);
-P.hideProcId=null;}N.on(O,"mousemove",P.onContextMouseMove,P);P.showProcId=P.doShow(Q,O);}},onContextMouseOut:function(Q,P){var O=this;if(P._tempTitle){O.title=P._tempTitle;P._tempTitle=null;}if(P.showProcId){clearTimeout(P.showProcId);P.showProcId=null;}if(P.hideProcId){clearTimeout(P.hideProcId);P.hideProcId=null;}P.fireEvent("contextMouseOut",O,Q);P.hideProcId=setTimeout(function(){P.hide();},P.cfg.getProperty("hidedelay"));},doShow:function(R,O){var T=this.cfg.getProperty("xyoffset"),P=T[0],S=T[1],Q=this;if(H.opera&&O.tagName&&O.tagName.toUpperCase()=="A"){S+=12;}return setTimeout(function(){var U=Q.cfg.getProperty("text");if(Q._tempTitle&&(U===""||YAHOO.lang.isUndefined(U)||YAHOO.lang.isNull(U))){Q.setBody(Q._tempTitle);}else{Q.cfg.refireEvent("text");}Q.moveTo(Q.pageX+P,Q.pageY+S);if(Q.cfg.getProperty("preventoverlap")){Q.preventOverlap(Q.pageX,Q.pageY);}N.removeListener(O,"mousemove",Q.onContextMouseMove);Q.contextTriggerEvent.fire(O);Q.show();Q.hideProcId=Q.doHide();},this.cfg.getProperty("showdelay"));},doHide:function(){var O=this;return setTimeout(function(){O.hide();},this.cfg.getProperty("autodismissdelay"));},preventOverlap:function(S,R){var O=this.element.offsetHeight,Q=new YAHOO.util.Point(S,R),P=C.getRegion(this.element);P.top-=5;P.left-=5;P.right+=5;P.bottom+=5;if(P.contains(Q)){this.cfg.setProperty("y",(R-O-5));}},onRender:function(S,R){function T(){var W=this.element,V=this.underlay;if(V){V.style.width=(W.offsetWidth+6)+"px";V.style.height=(W.offsetHeight+1)+"px";}}function P(){C.addClass(this.underlay,"yui-tt-shadow-visible");if(H.ie){this.forceUnderlayRedraw();}}function O(){C.removeClass(this.underlay,"yui-tt-shadow-visible");}function U(){var X=this.underlay,W,V,Z,Y;if(!X){W=this.element;V=YAHOO.widget.Module;Z=H.ie;Y=this;if(!F){F=document.createElement("div");F.className="yui-tt-shadow";}X=F.cloneNode(false);W.appendChild(X);this.underlay=X;this._shadow=this.underlay;P.call(this);this.subscribe("beforeShow",P);this.subscribe("hide",O);if(G){window.setTimeout(function(){T.call(Y);},0);this.cfg.subscribeToConfigEvent("width",T);this.cfg.subscribeToConfigEvent("height",T);this.subscribe("changeContent",T);V.textResizeEvent.subscribe(T,this,true);this.subscribe("destroy",function(){V.textResizeEvent.unsubscribe(T,this);});}}}function Q(){U.call(this);this.unsubscribe("beforeShow",Q);}if(this.cfg.getProperty("visible")){U.call(this);}else{this.subscribe("beforeShow",Q);}},forceUnderlayRedraw:function(){var O=this;C.addClass(O.underlay,"yui-force-redraw");setTimeout(function(){C.removeClass(O.underlay,"yui-force-redraw");},0);},destroy:function(){this._removeEventListeners();J.superclass.destroy.call(this);},toString:function(){return"Tooltip "+this.id;}});}());(function(){YAHOO.widget.Panel=function(V,U){YAHOO.widget.Panel.superclass.constructor.call(this,V,U);};var S=null;var E=YAHOO.lang,F=YAHOO.util,A=F.Dom,T=F.Event,M=F.CustomEvent,K=YAHOO.util.KeyListener,I=F.Config,H=YAHOO.widget.Overlay,O=YAHOO.widget.Panel,L=YAHOO.env.ua,P=(L.ie&&(L.ie<=6||document.compatMode=="BackCompat")),G,Q,C,D={"SHOW_MASK":"showMask","HIDE_MASK":"hideMask","DRAG":"drag"},N={"CLOSE":{key:"close",value:true,validator:E.isBoolean,supercedes:["visible"]},"DRAGGABLE":{key:"draggable",value:(F.DD?true:false),validator:E.isBoolean,supercedes:["visible"]},"DRAG_ONLY":{key:"dragonly",value:false,validator:E.isBoolean,supercedes:["draggable"]},"UNDERLAY":{key:"underlay",value:"shadow",supercedes:["visible"]},"MODAL":{key:"modal",value:false,validator:E.isBoolean,supercedes:["visible","zindex"]},"KEY_LISTENERS":{key:"keylisteners",suppressEvent:true,supercedes:["visible"]},"STRINGS":{key:"strings",supercedes:["close"],validator:E.isObject,value:{close:"Close"}}};O.CSS_PANEL="yui-panel";O.CSS_PANEL_CONTAINER="yui-panel-container";O.FOCUSABLE=["a","button","select","textarea","input","iframe"];function J(V,U){if(!this.header&&this.cfg.getProperty("draggable")){this.setHeader("&#160;");}}function R(V,U,W){var Z=W[0],X=W[1],Y=this.cfg,a=Y.getProperty("width");if(a==X){Y.setProperty("width",Z);}this.unsubscribe("hide",R,W);}function B(V,U){var Y,X,W;if(P){Y=this.cfg;X=Y.getProperty("width");if(!X||X=="auto"){W=(this.element.offsetWidth+"px");Y.setProperty("width",W);this.subscribe("hide",R,[(X||""),W]);}}}YAHOO.extend(O,H,{init:function(V,U){O.superclass.init.call(this,V);this.beforeInitEvent.fire(O);A.addClass(this.element,O.CSS_PANEL);this.buildWrapper();if(U){this.cfg.applyConfig(U,true);}this.subscribe("showMask",this._addFocusHandlers);this.subscribe("hideMask",this._removeFocusHandlers);this.subscribe("beforeRender",J);this.subscribe("render",function(){this.setFirstLastFocusable();this.subscribe("changeContent",this.setFirstLastFocusable);});this.subscribe("show",this.focusFirst);this.initEvent.fire(O);},_onElementFocus:function(Z){if(S===this){var Y=T.getTarget(Z),X=document.documentElement,V=(Y!==X&&Y!==window);if(V&&Y!==this.element&&Y!==this.mask&&!A.isAncestor(this.element,Y)){try{if(this.firstElement){this.firstElement.focus();}else{if(this._modalFocus){this._modalFocus.focus();}else{this.innerElement.focus();}}}catch(W){try{if(V&&Y!==document.body){Y.blur();}}catch(U){}}}}},_addFocusHandlers:function(V,U){if(!this.firstElement){if(L.webkit||L.opera){if(!this._modalFocus){this._createHiddenFocusElement();}}else{this.innerElement.tabIndex=0;}}this.setTabLoop(this.firstElement,this.lastElement);T.onFocus(document.documentElement,this._onElementFocus,this,true);S=this;},_createHiddenFocusElement:function(){var U=document.createElement("button");U.style.height="1px";U.style.width="1px";U.style.position="absolute";U.style.left="-10000em";U.style.opacity=0;U.tabIndex=-1;this.innerElement.appendChild(U);this._modalFocus=U;},_removeFocusHandlers:function(V,U){T.removeFocusListener(document.documentElement,this._onElementFocus,this);if(S==this){S=null;}},focusFirst:function(W,U,Y){var V=this.firstElement;if(U&&U[1]){T.stopEvent(U[1]);}if(V){try{V.focus();}catch(X){}}},focusLast:function(W,U,Y){var V=this.lastElement;
-if(U&&U[1]){T.stopEvent(U[1]);}if(V){try{V.focus();}catch(X){}}},setTabLoop:function(X,Z){var V=this.preventBackTab,W=this.preventTabOut,U=this.showEvent,Y=this.hideEvent;if(V){V.disable();U.unsubscribe(V.enable,V);Y.unsubscribe(V.disable,V);V=this.preventBackTab=null;}if(W){W.disable();U.unsubscribe(W.enable,W);Y.unsubscribe(W.disable,W);W=this.preventTabOut=null;}if(X){this.preventBackTab=new K(X,{shift:true,keys:9},{fn:this.focusLast,scope:this,correctScope:true});V=this.preventBackTab;U.subscribe(V.enable,V,true);Y.subscribe(V.disable,V,true);}if(Z){this.preventTabOut=new K(Z,{shift:false,keys:9},{fn:this.focusFirst,scope:this,correctScope:true});W=this.preventTabOut;U.subscribe(W.enable,W,true);Y.subscribe(W.disable,W,true);}},getFocusableElements:function(U){U=U||this.innerElement;var X={};for(var W=0;W<O.FOCUSABLE.length;W++){X[O.FOCUSABLE[W]]=true;}function V(Y){if(Y.focus&&Y.type!=="hidden"&&!Y.disabled&&X[Y.tagName.toLowerCase()]){return true;}return false;}return A.getElementsBy(V,null,U);},setFirstLastFocusable:function(){this.firstElement=null;this.lastElement=null;var U=this.getFocusableElements();this.focusableElements=U;if(U.length>0){this.firstElement=U[0];this.lastElement=U[U.length-1];}if(this.cfg.getProperty("modal")){this.setTabLoop(this.firstElement,this.lastElement);}},initEvents:function(){O.superclass.initEvents.call(this);var U=M.LIST;this.showMaskEvent=this.createEvent(D.SHOW_MASK);this.showMaskEvent.signature=U;this.hideMaskEvent=this.createEvent(D.HIDE_MASK);this.hideMaskEvent.signature=U;this.dragEvent=this.createEvent(D.DRAG);this.dragEvent.signature=U;},initDefaultConfig:function(){O.superclass.initDefaultConfig.call(this);this.cfg.addProperty(N.CLOSE.key,{handler:this.configClose,value:N.CLOSE.value,validator:N.CLOSE.validator,supercedes:N.CLOSE.supercedes});this.cfg.addProperty(N.DRAGGABLE.key,{handler:this.configDraggable,value:(F.DD)?true:false,validator:N.DRAGGABLE.validator,supercedes:N.DRAGGABLE.supercedes});this.cfg.addProperty(N.DRAG_ONLY.key,{value:N.DRAG_ONLY.value,validator:N.DRAG_ONLY.validator,supercedes:N.DRAG_ONLY.supercedes});this.cfg.addProperty(N.UNDERLAY.key,{handler:this.configUnderlay,value:N.UNDERLAY.value,supercedes:N.UNDERLAY.supercedes});this.cfg.addProperty(N.MODAL.key,{handler:this.configModal,value:N.MODAL.value,validator:N.MODAL.validator,supercedes:N.MODAL.supercedes});this.cfg.addProperty(N.KEY_LISTENERS.key,{handler:this.configKeyListeners,suppressEvent:N.KEY_LISTENERS.suppressEvent,supercedes:N.KEY_LISTENERS.supercedes});this.cfg.addProperty(N.STRINGS.key,{value:N.STRINGS.value,handler:this.configStrings,validator:N.STRINGS.validator,supercedes:N.STRINGS.supercedes});},configClose:function(X,V,Y){var Z=V[0],W=this.close,U=this.cfg.getProperty("strings");if(Z){if(!W){if(!C){C=document.createElement("a");C.className="container-close";C.href="#";}W=C.cloneNode(true);this.innerElement.appendChild(W);W.innerHTML=(U&&U.close)?U.close:"&#160;";T.on(W,"click",this._doClose,this,true);this.close=W;}else{W.style.display="block";}}else{if(W){W.style.display="none";}}},_doClose:function(U){T.preventDefault(U);this.hide();},configDraggable:function(V,U,W){var X=U[0];if(X){if(!F.DD){this.cfg.setProperty("draggable",false);return;}if(this.header){A.setStyle(this.header,"cursor","move");this.registerDragDrop();}this.subscribe("beforeShow",B);}else{if(this.dd){this.dd.unreg();}if(this.header){A.setStyle(this.header,"cursor","auto");}this.unsubscribe("beforeShow",B);}},configUnderlay:function(d,c,Z){var b=(this.platform=="mac"&&L.gecko),e=c[0].toLowerCase(),V=this.underlay,W=this.element;function X(){var f=false;if(!V){if(!Q){Q=document.createElement("div");Q.className="underlay";}V=Q.cloneNode(false);this.element.appendChild(V);this.underlay=V;if(P){this.sizeUnderlay();this.cfg.subscribeToConfigEvent("width",this.sizeUnderlay);this.cfg.subscribeToConfigEvent("height",this.sizeUnderlay);this.changeContentEvent.subscribe(this.sizeUnderlay);YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay,this,true);}if(L.webkit&&L.webkit<420){this.changeContentEvent.subscribe(this.forceUnderlayRedraw);}f=true;}}function a(){var f=X.call(this);if(!f&&P){this.sizeUnderlay();}this._underlayDeferred=false;this.beforeShowEvent.unsubscribe(a);}function Y(){if(this._underlayDeferred){this.beforeShowEvent.unsubscribe(a);this._underlayDeferred=false;}if(V){this.cfg.unsubscribeFromConfigEvent("width",this.sizeUnderlay);this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);this.changeContentEvent.unsubscribe(this.sizeUnderlay);this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay,this,true);this.element.removeChild(V);this.underlay=null;}}switch(e){case"shadow":A.removeClass(W,"matte");A.addClass(W,"shadow");break;case"matte":if(!b){Y.call(this);}A.removeClass(W,"shadow");A.addClass(W,"matte");break;default:if(!b){Y.call(this);}A.removeClass(W,"shadow");A.removeClass(W,"matte");break;}if((e=="shadow")||(b&&!V)){if(this.cfg.getProperty("visible")){var U=X.call(this);if(!U&&P){this.sizeUnderlay();}}else{if(!this._underlayDeferred){this.beforeShowEvent.subscribe(a);this._underlayDeferred=true;}}}},configModal:function(V,U,X){var W=U[0];if(W){if(!this._hasModalityEventListeners){this.subscribe("beforeShow",this.buildMask);this.subscribe("beforeShow",this.bringToTop);this.subscribe("beforeShow",this.showMask);this.subscribe("hide",this.hideMask);H.windowResizeEvent.subscribe(this.sizeMask,this,true);this._hasModalityEventListeners=true;}}else{if(this._hasModalityEventListeners){if(this.cfg.getProperty("visible")){this.hideMask();this.removeMask();}this.unsubscribe("beforeShow",this.buildMask);this.unsubscribe("beforeShow",this.bringToTop);this.unsubscribe("beforeShow",this.showMask);this.unsubscribe("hide",this.hideMask);H.windowResizeEvent.unsubscribe(this.sizeMask,this);this._hasModalityEventListeners=false;}}},removeMask:function(){var V=this.mask,U;if(V){this.hideMask();U=V.parentNode;
-if(U){U.removeChild(V);}this.mask=null;}},configKeyListeners:function(X,U,a){var W=U[0],Z,Y,V;if(W){if(W instanceof Array){Y=W.length;for(V=0;V<Y;V++){Z=W[V];if(!I.alreadySubscribed(this.showEvent,Z.enable,Z)){this.showEvent.subscribe(Z.enable,Z,true);}if(!I.alreadySubscribed(this.hideEvent,Z.disable,Z)){this.hideEvent.subscribe(Z.disable,Z,true);this.destroyEvent.subscribe(Z.disable,Z,true);}}}else{if(!I.alreadySubscribed(this.showEvent,W.enable,W)){this.showEvent.subscribe(W.enable,W,true);}if(!I.alreadySubscribed(this.hideEvent,W.disable,W)){this.hideEvent.subscribe(W.disable,W,true);this.destroyEvent.subscribe(W.disable,W,true);}}}},configStrings:function(V,U,W){var X=E.merge(N.STRINGS.value,U[0]);this.cfg.setProperty(N.STRINGS.key,X,true);},configHeight:function(X,V,Y){var U=V[0],W=this.innerElement;A.setStyle(W,"height",U);this.cfg.refireEvent("iframe");},_autoFillOnHeightChange:function(X,V,W){O.superclass._autoFillOnHeightChange.apply(this,arguments);if(P){var U=this;setTimeout(function(){U.sizeUnderlay();},0);}},configWidth:function(X,U,Y){var W=U[0],V=this.innerElement;A.setStyle(V,"width",W);this.cfg.refireEvent("iframe");},configzIndex:function(V,U,X){O.superclass.configzIndex.call(this,V,U,X);if(this.mask||this.cfg.getProperty("modal")===true){var W=A.getStyle(this.element,"zIndex");if(!W||isNaN(W)){W=0;}if(W===0){this.cfg.setProperty("zIndex",1);}else{this.stackMask();}}},buildWrapper:function(){var W=this.element.parentNode,U=this.element,V=document.createElement("div");V.className=O.CSS_PANEL_CONTAINER;V.id=U.id+"_c";if(W){W.insertBefore(V,U);}V.appendChild(U);this.element=V;this.innerElement=U;A.setStyle(this.innerElement,"visibility","inherit");},sizeUnderlay:function(){var V=this.underlay,U;if(V){U=this.element;V.style.width=U.offsetWidth+"px";V.style.height=U.offsetHeight+"px";}},registerDragDrop:function(){var V=this;if(this.header){if(!F.DD){return;}var U=(this.cfg.getProperty("dragonly")===true);this.dd=new F.DD(this.element.id,this.id,{dragOnly:U});if(!this.header.id){this.header.id=this.id+"_h";}this.dd.startDrag=function(){var X,Z,W,c,b,a;if(YAHOO.env.ua.ie==6){A.addClass(V.element,"drag");}if(V.cfg.getProperty("constraintoviewport")){var Y=H.VIEWPORT_OFFSET;X=V.element.offsetHeight;Z=V.element.offsetWidth;W=A.getViewportWidth();c=A.getViewportHeight();b=A.getDocumentScrollLeft();a=A.getDocumentScrollTop();if(X+Y<c){this.minY=a+Y;this.maxY=a+c-X-Y;}else{this.minY=a+Y;this.maxY=a+Y;}if(Z+Y<W){this.minX=b+Y;this.maxX=b+W-Z-Y;}else{this.minX=b+Y;this.maxX=b+Y;}this.constrainX=true;this.constrainY=true;}else{this.constrainX=false;this.constrainY=false;}V.dragEvent.fire("startDrag",arguments);};this.dd.onDrag=function(){V.syncPosition();V.cfg.refireEvent("iframe");if(this.platform=="mac"&&YAHOO.env.ua.gecko){this.showMacGeckoScrollbars();}V.dragEvent.fire("onDrag",arguments);};this.dd.endDrag=function(){if(YAHOO.env.ua.ie==6){A.removeClass(V.element,"drag");}V.dragEvent.fire("endDrag",arguments);V.moveEvent.fire(V.cfg.getProperty("xy"));};this.dd.setHandleElId(this.header.id);this.dd.addInvalidHandleType("INPUT");this.dd.addInvalidHandleType("SELECT");this.dd.addInvalidHandleType("TEXTAREA");}},buildMask:function(){var U=this.mask;if(!U){if(!G){G=document.createElement("div");G.className="mask";G.innerHTML="&#160;";}U=G.cloneNode(true);U.id=this.id+"_mask";document.body.insertBefore(U,document.body.firstChild);this.mask=U;if(YAHOO.env.ua.gecko&&this.platform=="mac"){A.addClass(this.mask,"block-scrollbars");}this.stackMask();}},hideMask:function(){if(this.cfg.getProperty("modal")&&this.mask){this.mask.style.display="none";A.removeClass(document.body,"masked");this.hideMaskEvent.fire();}},showMask:function(){if(this.cfg.getProperty("modal")&&this.mask){A.addClass(document.body,"masked");this.sizeMask();this.mask.style.display="block";this.showMaskEvent.fire();}},sizeMask:function(){if(this.mask){var V=this.mask,W=A.getViewportWidth(),U=A.getViewportHeight();if(V.offsetHeight>U){V.style.height=U+"px";}if(V.offsetWidth>W){V.style.width=W+"px";}V.style.height=A.getDocumentHeight()+"px";V.style.width=A.getDocumentWidth()+"px";}},stackMask:function(){if(this.mask){var U=A.getStyle(this.element,"zIndex");if(!YAHOO.lang.isUndefined(U)&&!isNaN(U)){A.setStyle(this.mask,"zIndex",U-1);}}},render:function(U){return O.superclass.render.call(this,U,this.innerElement);},_renderHeader:function(U){U=U||this.innerElement;O.superclass._renderHeader.call(this,U);},_renderBody:function(U){U=U||this.innerElement;O.superclass._renderBody.call(this,U);},_renderFooter:function(U){U=U||this.innerElement;O.superclass._renderFooter.call(this,U);},destroy:function(){H.windowResizeEvent.unsubscribe(this.sizeMask,this);this.removeMask();if(this.close){T.purgeElement(this.close);}O.superclass.destroy.call(this);},forceUnderlayRedraw:function(){var U=this.underlay;A.addClass(U,"yui-force-redraw");setTimeout(function(){A.removeClass(U,"yui-force-redraw");},0);},toString:function(){return"Panel "+this.id;}});}());(function(){YAHOO.widget.Dialog=function(J,I){YAHOO.widget.Dialog.superclass.constructor.call(this,J,I);};var B=YAHOO.util.Event,G=YAHOO.util.CustomEvent,E=YAHOO.util.Dom,A=YAHOO.widget.Dialog,F=YAHOO.lang,H={"BEFORE_SUBMIT":"beforeSubmit","SUBMIT":"submit","MANUAL_SUBMIT":"manualSubmit","ASYNC_SUBMIT":"asyncSubmit","FORM_SUBMIT":"formSubmit","CANCEL":"cancel"},C={"POST_METHOD":{key:"postmethod",value:"async"},"POST_DATA":{key:"postdata",value:null},"BUTTONS":{key:"buttons",value:"none",supercedes:["visible"]},"HIDEAFTERSUBMIT":{key:"hideaftersubmit",value:true}};A.CSS_DIALOG="yui-dialog";function D(){var L=this._aButtons,J,K,I;if(F.isArray(L)){J=L.length;if(J>0){I=J-1;do{K=L[I];if(YAHOO.widget.Button&&K instanceof YAHOO.widget.Button){K.destroy();}else{if(K.tagName.toUpperCase()=="BUTTON"){B.purgeElement(K);B.purgeElement(K,false);}}}while(I--);}}}YAHOO.extend(A,YAHOO.widget.Panel,{form:null,initDefaultConfig:function(){A.superclass.initDefaultConfig.call(this);this.callback={success:null,failure:null,argument:null};
-this.cfg.addProperty(C.POST_METHOD.key,{handler:this.configPostMethod,value:C.POST_METHOD.value,validator:function(I){if(I!="form"&&I!="async"&&I!="none"&&I!="manual"){return false;}else{return true;}}});this.cfg.addProperty(C.POST_DATA.key,{value:C.POST_DATA.value});this.cfg.addProperty(C.HIDEAFTERSUBMIT.key,{value:C.HIDEAFTERSUBMIT.value});this.cfg.addProperty(C.BUTTONS.key,{handler:this.configButtons,value:C.BUTTONS.value,supercedes:C.BUTTONS.supercedes});},initEvents:function(){A.superclass.initEvents.call(this);var I=G.LIST;this.beforeSubmitEvent=this.createEvent(H.BEFORE_SUBMIT);this.beforeSubmitEvent.signature=I;this.submitEvent=this.createEvent(H.SUBMIT);this.submitEvent.signature=I;this.manualSubmitEvent=this.createEvent(H.MANUAL_SUBMIT);this.manualSubmitEvent.signature=I;this.asyncSubmitEvent=this.createEvent(H.ASYNC_SUBMIT);this.asyncSubmitEvent.signature=I;this.formSubmitEvent=this.createEvent(H.FORM_SUBMIT);this.formSubmitEvent.signature=I;this.cancelEvent=this.createEvent(H.CANCEL);this.cancelEvent.signature=I;},init:function(J,I){A.superclass.init.call(this,J);this.beforeInitEvent.fire(A);E.addClass(this.element,A.CSS_DIALOG);this.cfg.setProperty("visible",false);if(I){this.cfg.applyConfig(I,true);}this.showEvent.subscribe(this.focusFirst,this,true);this.beforeHideEvent.subscribe(this.blurButtons,this,true);this.subscribe("changeBody",this.registerForm);this.initEvent.fire(A);},doSubmit:function(){var P=YAHOO.util.Connect,Q=this.form,K=false,N=false,R,M,L,I;switch(this.cfg.getProperty("postmethod")){case"async":R=Q.elements;M=R.length;if(M>0){L=M-1;do{if(R[L].type=="file"){K=true;break;}}while(L--);}if(K&&YAHOO.env.ua.ie&&this.isSecure){N=true;}I=this._getFormAttributes(Q);P.setForm(Q,K,N);var J=this.cfg.getProperty("postdata");var O=P.asyncRequest(I.method,I.action,this.callback,J);this.asyncSubmitEvent.fire(O);break;case"form":Q.submit();this.formSubmitEvent.fire();break;case"none":case"manual":this.manualSubmitEvent.fire();break;}},_getFormAttributes:function(K){var I={method:null,action:null};if(K){if(K.getAttributeNode){var J=K.getAttributeNode("action");var L=K.getAttributeNode("method");if(J){I.action=J.value;}if(L){I.method=L.value;}}else{I.action=K.getAttribute("action");I.method=K.getAttribute("method");}}I.method=(F.isString(I.method)?I.method:"POST").toUpperCase();I.action=F.isString(I.action)?I.action:"";return I;},registerForm:function(){var I=this.element.getElementsByTagName("form")[0];if(this.form){if(this.form==I&&E.isAncestor(this.element,this.form)){return;}else{B.purgeElement(this.form);this.form=null;}}if(!I){I=document.createElement("form");I.name="frm_"+this.id;this.body.appendChild(I);}if(I){this.form=I;B.on(I,"submit",this._submitHandler,this,true);}},_submitHandler:function(I){B.stopEvent(I);this.submit();this.form.blur();},setTabLoop:function(I,J){I=I||this.firstButton;J=this.lastButton||J;A.superclass.setTabLoop.call(this,I,J);},setFirstLastFocusable:function(){A.superclass.setFirstLastFocusable.call(this);var J,I,K,L=this.focusableElements;this.firstFormElement=null;this.lastFormElement=null;if(this.form&&L&&L.length>0){I=L.length;for(J=0;J<I;++J){K=L[J];if(this.form===K.form){this.firstFormElement=K;break;}}for(J=I-1;J>=0;--J){K=L[J];if(this.form===K.form){this.lastFormElement=K;break;}}}},configClose:function(J,I,K){A.superclass.configClose.apply(this,arguments);},_doClose:function(I){B.preventDefault(I);this.cancel();},configButtons:function(S,R,M){var N=YAHOO.widget.Button,U=R[0],K=this.innerElement,T,P,J,Q,O,I,L;D.call(this);this._aButtons=null;if(F.isArray(U)){O=document.createElement("span");O.className="button-group";Q=U.length;this._aButtons=[];this.defaultHtmlButton=null;for(L=0;L<Q;L++){T=U[L];if(N){J=new N({label:T.text});J.appendTo(O);P=J.get("element");if(T.isDefault){J.addClass("default");this.defaultHtmlButton=P;}if(F.isFunction(T.handler)){J.set("onclick",{fn:T.handler,obj:this,scope:this});}else{if(F.isObject(T.handler)&&F.isFunction(T.handler.fn)){J.set("onclick",{fn:T.handler.fn,obj:((!F.isUndefined(T.handler.obj))?T.handler.obj:this),scope:(T.handler.scope||this)});}}this._aButtons[this._aButtons.length]=J;}else{P=document.createElement("button");P.setAttribute("type","button");if(T.isDefault){P.className="default";this.defaultHtmlButton=P;}P.innerHTML=T.text;if(F.isFunction(T.handler)){B.on(P,"click",T.handler,this,true);}else{if(F.isObject(T.handler)&&F.isFunction(T.handler.fn)){B.on(P,"click",T.handler.fn,((!F.isUndefined(T.handler.obj))?T.handler.obj:this),(T.handler.scope||this));}}O.appendChild(P);this._aButtons[this._aButtons.length]=P;}T.htmlButton=P;if(L===0){this.firstButton=P;}if(L==(Q-1)){this.lastButton=P;}}this.setFooter(O);I=this.footer;if(E.inDocument(this.element)&&!E.isAncestor(K,I)){K.appendChild(I);}this.buttonSpan=O;}else{O=this.buttonSpan;I=this.footer;if(O&&I){I.removeChild(O);this.buttonSpan=null;this.firstButton=null;this.lastButton=null;this.defaultHtmlButton=null;}}this.changeContentEvent.fire();},getButtons:function(){return this._aButtons||null;},focusFirst:function(K,I,M){var J=this.firstFormElement;if(I&&I[1]){B.stopEvent(I[1]);}if(J){try{J.focus();}catch(L){}}else{if(this.defaultHtmlButton){this.focusDefaultButton();}else{this.focusFirstButton();}}},focusLast:function(K,I,M){var N=this.cfg.getProperty("buttons"),J=this.lastFormElement;if(I&&I[1]){B.stopEvent(I[1]);}if(N&&F.isArray(N)){this.focusLastButton();}else{if(J){try{J.focus();}catch(L){}}}},_getButton:function(J){var I=YAHOO.widget.Button;if(I&&J&&J.nodeName&&J.id){J=I.getButton(J.id)||J;}return J;},focusDefaultButton:function(){var I=this._getButton(this.defaultHtmlButton);if(I){try{I.focus();}catch(J){}}},blurButtons:function(){var N=this.cfg.getProperty("buttons"),K,M,J,I;if(N&&F.isArray(N)){K=N.length;if(K>0){I=(K-1);do{M=N[I];if(M){J=this._getButton(M.htmlButton);if(J){try{J.blur();}catch(L){}}}}while(I--);}}},focusFirstButton:function(){var L=this.cfg.getProperty("buttons"),K,I;if(L&&F.isArray(L)){K=L[0];if(K){I=this._getButton(K.htmlButton);
-if(I){try{I.focus();}catch(J){}}}}},focusLastButton:function(){var M=this.cfg.getProperty("buttons"),J,L,I;if(M&&F.isArray(M)){J=M.length;if(J>0){L=M[(J-1)];if(L){I=this._getButton(L.htmlButton);if(I){try{I.focus();}catch(K){}}}}}},configPostMethod:function(J,I,K){this.registerForm();},validate:function(){return true;},submit:function(){if(this.validate()){if(this.beforeSubmitEvent.fire()){this.doSubmit();this.submitEvent.fire();if(this.cfg.getProperty("hideaftersubmit")){this.hide();}return true;}else{return false;}}else{return false;}},cancel:function(){this.cancelEvent.fire();this.hide();},getData:function(){var Y=this.form,J,R,U,L,S,P,O,I,V,K,W,Z,N,a,M,X,T;function Q(c){var b=c.tagName.toUpperCase();return((b=="INPUT"||b=="TEXTAREA"||b=="SELECT")&&c.name==L);}if(Y){J=Y.elements;R=J.length;U={};for(X=0;X<R;X++){L=J[X].name;S=E.getElementsBy(Q,"*",Y);P=S.length;if(P>0){if(P==1){S=S[0];O=S.type;I=S.tagName.toUpperCase();switch(I){case"INPUT":if(O=="checkbox"){U[L]=S.checked;}else{if(O!="radio"){U[L]=S.value;}}break;case"TEXTAREA":U[L]=S.value;break;case"SELECT":V=S.options;K=V.length;W=[];for(T=0;T<K;T++){Z=V[T];if(Z.selected){M=Z.attributes.value;W[W.length]=(M&&M.specified)?Z.value:Z.text;}}U[L]=W;break;}}else{O=S[0].type;switch(O){case"radio":for(T=0;T<P;T++){N=S[T];if(N.checked){U[L]=N.value;break;}}break;case"checkbox":W=[];for(T=0;T<P;T++){a=S[T];if(a.checked){W[W.length]=a.value;}}U[L]=W;break;}}}}}return U;},destroy:function(){D.call(this);this._aButtons=null;var I=this.element.getElementsByTagName("form"),J;if(I.length>0){J=I[0];if(J){B.purgeElement(J);if(J.parentNode){J.parentNode.removeChild(J);}this.form=null;}}A.superclass.destroy.call(this);},toString:function(){return"Dialog "+this.id;}});}());(function(){YAHOO.widget.SimpleDialog=function(E,D){YAHOO.widget.SimpleDialog.superclass.constructor.call(this,E,D);};var C=YAHOO.util.Dom,B=YAHOO.widget.SimpleDialog,A={"ICON":{key:"icon",value:"none",suppressEvent:true},"TEXT":{key:"text",value:"",suppressEvent:true,supercedes:["icon"]}};B.ICON_BLOCK="blckicon";B.ICON_ALARM="alrticon";B.ICON_HELP="hlpicon";B.ICON_INFO="infoicon";B.ICON_WARN="warnicon";B.ICON_TIP="tipicon";B.ICON_CSS_CLASSNAME="yui-icon";B.CSS_SIMPLEDIALOG="yui-simple-dialog";YAHOO.extend(B,YAHOO.widget.Dialog,{initDefaultConfig:function(){B.superclass.initDefaultConfig.call(this);this.cfg.addProperty(A.ICON.key,{handler:this.configIcon,value:A.ICON.value,suppressEvent:A.ICON.suppressEvent});this.cfg.addProperty(A.TEXT.key,{handler:this.configText,value:A.TEXT.value,suppressEvent:A.TEXT.suppressEvent,supercedes:A.TEXT.supercedes});},init:function(E,D){B.superclass.init.call(this,E);this.beforeInitEvent.fire(B);C.addClass(this.element,B.CSS_SIMPLEDIALOG);this.cfg.queueProperty("postmethod","manual");if(D){this.cfg.applyConfig(D,true);}this.beforeRenderEvent.subscribe(function(){if(!this.body){this.setBody("");}},this,true);this.initEvent.fire(B);},registerForm:function(){B.superclass.registerForm.call(this);this.form.innerHTML+='<input type="hidden" name="'+this.id+'" value=""/>';},configIcon:function(K,J,H){var D=J[0],E=this.body,F=B.ICON_CSS_CLASSNAME,L,I,G;if(D&&D!="none"){L=C.getElementsByClassName(F,"*",E);if(L.length===1){I=L[0];G=I.parentNode;if(G){G.removeChild(I);I=null;}}if(D.indexOf(".")==-1){I=document.createElement("span");I.className=(F+" "+D);I.innerHTML="&#160;";}else{I=document.createElement("img");I.src=(this.imageRoot+D);I.className=F;}if(I){E.insertBefore(I,E.firstChild);}}},configText:function(E,D,F){var G=D[0];if(G){this.setBody(G);this.cfg.refireEvent("icon");}},toString:function(){return"SimpleDialog "+this.id;}});}());(function(){YAHOO.widget.ContainerEffect=function(E,H,G,D,F){if(!F){F=YAHOO.util.Anim;}this.overlay=E;this.attrIn=H;this.attrOut=G;this.targetElement=D||E.element;this.animClass=F;};var B=YAHOO.util.Dom,C=YAHOO.util.CustomEvent,A=YAHOO.widget.ContainerEffect;A.FADE=function(D,F){var G=YAHOO.util.Easing,I={attributes:{opacity:{from:0,to:1}},duration:F,method:G.easeIn},E={attributes:{opacity:{to:0}},duration:F,method:G.easeOut},H=new A(D,I,E,D.element);H.handleUnderlayStart=function(){var K=this.overlay.underlay;if(K&&YAHOO.env.ua.ie){var J=(K.filters&&K.filters.length>0);if(J){B.addClass(D.element,"yui-effect-fade");}}};H.handleUnderlayComplete=function(){var J=this.overlay.underlay;if(J&&YAHOO.env.ua.ie){B.removeClass(D.element,"yui-effect-fade");}};H.handleStartAnimateIn=function(K,J,L){B.addClass(L.overlay.element,"hide-select");if(!L.overlay.underlay){L.overlay.cfg.refireEvent("underlay");}L.handleUnderlayStart();L.overlay._setDomVisibility(true);B.setStyle(L.overlay.element,"opacity",0);};H.handleCompleteAnimateIn=function(K,J,L){B.removeClass(L.overlay.element,"hide-select");if(L.overlay.element.style.filter){L.overlay.element.style.filter=null;}L.handleUnderlayComplete();L.overlay.cfg.refireEvent("iframe");L.animateInCompleteEvent.fire();};H.handleStartAnimateOut=function(K,J,L){B.addClass(L.overlay.element,"hide-select");L.handleUnderlayStart();};H.handleCompleteAnimateOut=function(K,J,L){B.removeClass(L.overlay.element,"hide-select");if(L.overlay.element.style.filter){L.overlay.element.style.filter=null;}L.overlay._setDomVisibility(false);B.setStyle(L.overlay.element,"opacity",1);L.handleUnderlayComplete();L.overlay.cfg.refireEvent("iframe");L.animateOutCompleteEvent.fire();};H.init();return H;};A.SLIDE=function(F,D){var I=YAHOO.util.Easing,L=F.cfg.getProperty("x")||B.getX(F.element),K=F.cfg.getProperty("y")||B.getY(F.element),M=B.getClientWidth(),H=F.element.offsetWidth,J={attributes:{points:{to:[L,K]}},duration:D,method:I.easeIn},E={attributes:{points:{to:[(M+25),K]}},duration:D,method:I.easeOut},G=new A(F,J,E,F.element,YAHOO.util.Motion);G.handleStartAnimateIn=function(O,N,P){P.overlay.element.style.left=((-25)-H)+"px";P.overlay.element.style.top=K+"px";};G.handleTweenAnimateIn=function(Q,P,R){var S=B.getXY(R.overlay.element),O=S[0],N=S[1];if(B.getStyle(R.overlay.element,"visibility")=="hidden"&&O<L){R.overlay._setDomVisibility(true);
-}R.overlay.cfg.setProperty("xy",[O,N],true);R.overlay.cfg.refireEvent("iframe");};G.handleCompleteAnimateIn=function(O,N,P){P.overlay.cfg.setProperty("xy",[L,K],true);P.startX=L;P.startY=K;P.overlay.cfg.refireEvent("iframe");P.animateInCompleteEvent.fire();};G.handleStartAnimateOut=function(O,N,R){var P=B.getViewportWidth(),S=B.getXY(R.overlay.element),Q=S[1];R.animOut.attributes.points.to=[(P+25),Q];};G.handleTweenAnimateOut=function(P,O,Q){var S=B.getXY(Q.overlay.element),N=S[0],R=S[1];Q.overlay.cfg.setProperty("xy",[N,R],true);Q.overlay.cfg.refireEvent("iframe");};G.handleCompleteAnimateOut=function(O,N,P){P.overlay._setDomVisibility(false);P.overlay.cfg.setProperty("xy",[L,K]);P.animateOutCompleteEvent.fire();};G.init();return G;};A.prototype={init:function(){this.beforeAnimateInEvent=this.createEvent("beforeAnimateIn");this.beforeAnimateInEvent.signature=C.LIST;this.beforeAnimateOutEvent=this.createEvent("beforeAnimateOut");this.beforeAnimateOutEvent.signature=C.LIST;this.animateInCompleteEvent=this.createEvent("animateInComplete");this.animateInCompleteEvent.signature=C.LIST;this.animateOutCompleteEvent=this.createEvent("animateOutComplete");this.animateOutCompleteEvent.signature=C.LIST;this.animIn=new this.animClass(this.targetElement,this.attrIn.attributes,this.attrIn.duration,this.attrIn.method);this.animIn.onStart.subscribe(this.handleStartAnimateIn,this);this.animIn.onTween.subscribe(this.handleTweenAnimateIn,this);this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,this);this.animOut=new this.animClass(this.targetElement,this.attrOut.attributes,this.attrOut.duration,this.attrOut.method);this.animOut.onStart.subscribe(this.handleStartAnimateOut,this);this.animOut.onTween.subscribe(this.handleTweenAnimateOut,this);this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,this);},animateIn:function(){this.beforeAnimateInEvent.fire();this.animIn.animate();},animateOut:function(){this.beforeAnimateOutEvent.fire();this.animOut.animate();},handleStartAnimateIn:function(E,D,F){},handleTweenAnimateIn:function(E,D,F){},handleCompleteAnimateIn:function(E,D,F){},handleStartAnimateOut:function(E,D,F){},handleTweenAnimateOut:function(E,D,F){},handleCompleteAnimateOut:function(E,D,F){},toString:function(){var D="ContainerEffect";if(this.overlay){D+=" ["+this.overlay.toString()+"]";}return D;}};YAHOO.lang.augmentProto(A,YAHOO.util.EventProvider);})();YAHOO.register("container",YAHOO.widget.Module,{version:"2.8.2r1",build:"7"});/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 2.8.2r1
-*/
-(function(){var A=YAHOO.util;A.Selector={_foundCache:[],_regexCache:{},_re:{nth:/^(?:([-]?\d*)(n){1}|(odd|even)$)*([-+]?\d*)$/,attr:/(\[.*\])/g,urls:/^(?:href|src)/},document:window.document,attrAliases:{},shorthand:{"\\#(-?[_a-z]+[-\\w]*)":"[id=$1]","\\.(-?[_a-z]+[-\\w]*)":"[class~=$1]"},operators:{"=":function(B,C){return B===C;},"!=":function(B,C){return B!==C;},"~=":function(B,D){var C=" ";return(C+B+C).indexOf((C+D+C))>-1;},"|=":function(B,C){return B===C||B.slice(0,C.length+1)===C+"-";},"^=":function(B,C){return B.indexOf(C)===0;},"$=":function(B,C){return B.slice(-C.length)===C;},"*=":function(B,C){return B.indexOf(C)>-1;},"":function(B,C){return B;}},pseudos:{"root":function(B){return B===B.ownerDocument.documentElement;},"nth-child":function(B,C){return A.Selector._getNth(B,C);},"nth-last-child":function(B,C){return A.Selector._getNth(B,C,null,true);},"nth-of-type":function(B,C){return A.Selector._getNth(B,C,B.tagName);},"nth-last-of-type":function(B,C){return A.Selector._getNth(B,C,B.tagName,true);},"first-child":function(B){return A.Selector._getChildren(B.parentNode)[0]===B;},"last-child":function(C){var B=A.Selector._getChildren(C.parentNode);return B[B.length-1]===C;},"first-of-type":function(B,C){return A.Selector._getChildren(B.parentNode,B.tagName)[0];},"last-of-type":function(C,D){var B=A.Selector._getChildren(C.parentNode,C.tagName);return B[B.length-1];},"only-child":function(C){var B=A.Selector._getChildren(C.parentNode);return B.length===1&&B[0]===C;},"only-of-type":function(B){return A.Selector._getChildren(B.parentNode,B.tagName).length===1;},"empty":function(B){return B.childNodes.length===0;},"not":function(B,C){return !A.Selector.test(B,C);},"contains":function(B,D){var C=B.innerText||B.textContent||"";return C.indexOf(D)>-1;},"checked":function(B){return B.checked===true;}},test:function(F,D){F=A.Selector.document.getElementById(F)||F;if(!F){return false;}var C=D?D.split(","):[];if(C.length){for(var E=0,B=C.length;E<B;++E){if(A.Selector._test(F,C[E])){return true;}}return false;}return A.Selector._test(F,D);},_test:function(D,G,F,E){F=F||A.Selector._tokenize(G).pop()||{};if(!D.tagName||(F.tag!=="*"&&D.tagName!==F.tag)||(E&&D._found)){return false;}if(F.attributes.length){var B,H,C=A.Selector._re.urls;if(!D.attributes||!D.attributes.length){return false;}for(var I=0,K;K=F.attributes[I++];){H=(C.test(K[0]))?2:0;B=D.getAttribute(K[0],H);if(B===null||B===undefined){return false;}if(A.Selector.operators[K[1]]&&!A.Selector.operators[K[1]](B,K[2])){return false;}}}if(F.pseudos.length){for(var I=0,J=F.pseudos.length;I<J;++I){if(A.Selector.pseudos[F.pseudos[I][0]]&&!A.Selector.pseudos[F.pseudos[I][0]](D,F.pseudos[I][1])){return false;}}}return(F.previous&&F.previous.combinator!==",")?A.Selector._combinators[F.previous.combinator](D,F):true;},filter:function(E,D){E=E||[];var G,C=[],H=A.Selector._tokenize(D);if(!E.item){for(var F=0,B=E.length;F<B;++F){if(!E[F].tagName){G=A.Selector.document.getElementById(E[F]);if(G){E[F]=G;}else{}}}}C=A.Selector._filter(E,A.Selector._tokenize(D)[0]);return C;},_filter:function(E,G,H,D){var C=H?null:[],I=A.Selector._foundCache;for(var F=0,B=E.length;F<B;F++){if(!A.Selector._test(E[F],"",G,D)){continue;}if(H){return E[F];}if(D){if(E[F]._found){continue;}E[F]._found=true;I[I.length]=E[F];}C[C.length]=E[F];}return C;},query:function(C,D,E){var B=A.Selector._query(C,D,E);return B;},_query:function(H,M,N,F){var P=(N)?null:[],E;if(!H){return P;}var D=H.split(",");if(D.length>1){var O;for(var I=0,J=D.length;I<J;++I){O=A.Selector._query(D[I],M,N,true);P=N?O:P.concat(O);}A.Selector._clearFoundCache();return P;}if(M&&!M.nodeName){M=A.Selector.document.getElementById(M);if(!M){return P;}}M=M||A.Selector.document;if(M.nodeName!=="#document"){A.Dom.generateId(M);H=M.tagName+"#"+M.id+" "+H;E=M;M=M.ownerDocument;}var L=A.Selector._tokenize(H);var K=L[A.Selector._getIdTokenIndex(L)],B=[],C,G=L.pop()||{};if(K){C=A.Selector._getId(K.attributes);}if(C){E=E||A.Selector.document.getElementById(C);if(E&&(M.nodeName==="#document"||A.Dom.isAncestor(M,E))){if(A.Selector._test(E,null,K)){if(K===G){B=[E];}else{if(K.combinator===" "||K.combinator===">"){M=E;}}}}else{return P;}}if(M&&!B.length){B=M.getElementsByTagName(G.tag);}if(B.length){P=A.Selector._filter(B,G,N,F);}return P;},_clearFoundCache:function(){var E=A.Selector._foundCache;for(var C=0,B=E.length;C<B;++C){try{delete E[C]._found;}catch(D){E[C].removeAttribute("_found");}}E=[];},_getRegExp:function(D,B){var C=A.Selector._regexCache;B=B||"";if(!C[D+B]){C[D+B]=new RegExp(D,B);}return C[D+B];},_getChildren:function(){if(document.documentElement.children&&document.documentElement.children.tags){return function(C,B){return(B)?C.children.tags(B):C.children||[];};}else{return function(F,C){var E=[],G=F.childNodes;for(var D=0,B=G.length;D<B;++D){if(G[D].tagName){if(!C||G[D].tagName===C){E.push(G[D]);}}}return E;};}}(),_combinators:{" ":function(C,B){while((C=C.parentNode)){if(A.Selector._test(C,"",B.previous)){return true;}}return false;},">":function(C,B){return A.Selector._test(C.parentNode,null,B.previous);},"+":function(D,C){var B=D.previousSibling;while(B&&B.nodeType!==1){B=B.previousSibling;}if(B&&A.Selector._test(B,null,C.previous)){return true;}return false;},"~":function(D,C){var B=D.previousSibling;while(B){if(B.nodeType===1&&A.Selector._test(B,null,C.previous)){return true;}B=B.previousSibling;}return false;}},_getNth:function(C,L,N,G){A.Selector._re.nth.test(L);var K=parseInt(RegExp.$1,10),B=RegExp.$2,H=RegExp.$3,I=parseInt(RegExp.$4,10)||0,M=[],E;var J=A.Selector._getChildren(C.parentNode,N);if(H){K=2;E="+";B="n";I=(H==="odd")?1:0;}else{if(isNaN(K)){K=(B)?1:0;}}if(K===0){if(G){I=J.length-I+1;}if(J[I-1]===C){return true;}else{return false;}}else{if(K<0){G=!!G;K=Math.abs(K);}}if(!G){for(var D=I-1,F=J.length;D<F;D+=K){if(D>=0&&J[D]===C){return true;}}}else{for(var D=J.length-I,F=J.length;D>=0;D-=K){if(D<F&&J[D]===C){return true;}}}return false;},_getId:function(C){for(var D=0,B=C.length;D<B;++D){if(C[D][0]=="id"&&C[D][1]==="="){return C[D][2];
-}}},_getIdTokenIndex:function(D){for(var C=0,B=D.length;C<B;++C){if(A.Selector._getId(D[C].attributes)){return C;}}return -1;},_patterns:{tag:/^((?:-?[_a-z]+[\w-]*)|\*)/i,attributes:/^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,pseudos:/^:([-\w]+)(?:\(['"]?(.+)['"]?\))*/i,combinator:/^\s*([>+~]|\s)\s*/},_tokenize:function(B){var D={},H=[],I,G=false,F=A.Selector._patterns,C;B=A.Selector._replaceShorthand(B);do{G=false;for(var E in F){if(YAHOO.lang.hasOwnProperty(F,E)){if(E!="tag"&&E!="combinator"){D[E]=D[E]||[];}if((C=F[E].exec(B))){G=true;if(E!="tag"&&E!="combinator"){if(E==="attributes"&&C[1]==="id"){D.id=C[3];}D[E].push(C.slice(1));}else{D[E]=C[1];}B=B.replace(C[0],"");if(E==="combinator"||!B.length){D.attributes=A.Selector._fixAttributes(D.attributes);D.pseudos=D.pseudos||[];D.tag=D.tag?D.tag.toUpperCase():"*";H.push(D);D={previous:D};}}}}}while(G);return H;},_fixAttributes:function(C){var D=A.Selector.attrAliases;C=C||[];for(var E=0,B=C.length;E<B;++E){if(D[C[E][0]]){C[E][0]=D[C[E][0]];}if(!C[E][1]){C[E][1]="";}}return C;},_replaceShorthand:function(C){var D=A.Selector.shorthand;var E=C.match(A.Selector._re.attr);if(E){C=C.replace(A.Selector._re.attr,"REPLACED_ATTRIBUTE");}for(var G in D){if(YAHOO.lang.hasOwnProperty(D,G)){C=C.replace(A.Selector._getRegExp(G,"gi"),D[G]);}}if(E){for(var F=0,B=E.length;F<B;++F){C=C.replace("REPLACED_ATTRIBUTE",E[F]);}}return C;}};if(YAHOO.env.ua.ie&&YAHOO.env.ua.ie<8){A.Selector.attrAliases["class"]="className";A.Selector.attrAliases["for"]="htmlFor";}})();YAHOO.register("selector",YAHOO.util.Selector,{version:"2.8.2r1",build:"7"});
\ No newline at end of file
--- a/rhodecode/templates/admin/admin_log.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/admin_log.html	Fri Oct 07 01:08:50 2011 +0200
@@ -12,7 +12,10 @@
 	%for cnt,l in enumerate(c.users_log):
 	<tr class="parity${cnt%2}">
 		<td>${h.link_to(l.user.username,h.url('edit_user', id=l.user.user_id))}</td>
-		<td>${h.action_parser(l)}</td>
+		<td>${h.action_parser(l)[0]}
+		  <div class="journal_action_params">
+		  ${h.literal(h.action_parser(l)[1]())}</div>
+		</td>
 		<td>
 		%if l.repository:
 		  ${h.link_to(l.repository.repo_name,h.url('summary_home',repo_name=l.repository.repo_name))}
@@ -28,36 +31,23 @@
 </table>
 
 <script type="text/javascript">
-  var data_div = 'user_log';
   YUE.onDOMReady(function(){
-	YUE.on(YUD.getElementsByClassName('pager_link'),"click",function(){
-			YUD.setStyle(data_div,'opacity','0.3');});
-	YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
+	YUE.delegate("user_log","click",function(e, matchedEl, container){
+		ypjax(e.target.href,"user_log",function(){show_more_event();tooltip_activate();});
+		YUE.preventDefault(e);
+	},'.pager_link');
+	
+	YUE.delegate("user_log","click",function(e,matchedEl,container){
 	      var el = e.target;
 	      YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
 	      YUD.setStyle(el.parentNode,'display','none');
-	  });
+	  },'.show_more');
   });
 </script>
-		
-		
+
 <div class="pagination-wh pagination-left">
-${c.users_log.pager('$link_previous ~2~ $link_next',
-onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{
-success:function(o){
-    YUD.get(data_div).innerHTML=o.responseText;
-    YUE.on(YUD.getElementsByClassName('pager_link'),"click",function(){
-        YUD.setStyle(data_div,'opacity','0.3');
-    });		
-    YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
-      var el = e.target;
-      YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
-      YUD.setStyle(el.parentNode,'display','none');
-    });
-    YUD.setStyle(data_div,'opacity','1');}    
-
-},null); return false;""")}
+${c.users_log.pager('$link_previous ~2~ $link_next')}
 </div>
 %else: 
 	${_('No actions yet')} 
-%endif
+%endif
\ No newline at end of file
--- a/rhodecode/templates/admin/ldap/ldap.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/ldap/ldap.html	Fri Oct 07 01:08:50 2011 +0200
@@ -21,13 +21,13 @@
     <div class="title">
         ${self.breadcrumbs()}       
     </div>
-    <h3>${_('LDAP administration')}</h3>
     ${h.form(url('ldap_settings'))}
     <div class="form">
         <div class="fields">
 
+	  <h3>${_('Connection settings')}</h3>
             <div class="field">
-                <div class="label label-checkbox"><label for="ldap_active">${_('Enable ldap')}</label></div>
+                <div class="label label-checkbox"><label for="ldap_active">${_('Enable LDAP')}</label></div>
                 <div class="checkboxes"><div class="checkbox">${h.checkbox('ldap_active',True,class_='small')}</div></div>
             </div>
             <div class="field">
@@ -39,10 +39,6 @@
                 <div class="input">${h.text('ldap_port',class_='small')}</div>
             </div>
             <div class="field">
-                <div class="label label-checkbox"><label for="ldap_ldaps">${_('Enable LDAPS')}</label></div>
-                <div class="checkboxes"><div class="checkbox">${h.checkbox('ldap_ldaps',True,class_='small')}</div></div>
-            </div>
-            <div class="field">
                 <div class="label"><label for="ldap_dn_user">${_('Account')}</label></div>
                 <div class="input">${h.text('ldap_dn_user',class_='small')}</div>
             </div>
@@ -51,12 +47,46 @@
                 <div class="input">${h.password('ldap_dn_pass',class_='small')}</div>
             </div>
             <div class="field">
+                <div class="label"><label for="ldap_tls_kind">${_('Connection security')}</label></div>
+                <div class="select">${h.select('ldap_tls_kind',c.tls_kind_cur,c.tls_kind_choices,class_='small')}</div>
+            </div>
+            <div class="field">
+                <div class="label"><label for="ldap_tls_reqcert">${_('Certificate Checks')}</label></div>
+                <div class="select">${h.select('ldap_tls_reqcert',c.tls_reqcert_cur,c.tls_reqcert_choices,class_='small')}</div>
+            </div>
+	  <h3>${_('Search settings')}</h3>
+            <div class="field">
                 <div class="label"><label for="ldap_base_dn">${_('Base DN')}</label></div>
                 <div class="input">${h.text('ldap_base_dn',class_='small')}</div>
             </div>
+            <div class="field">
+                <div class="label"><label for="ldap_filter">${_('LDAP Filter')}</label></div>
+                <div class="input">${h.text('ldap_filter',class_='small')}</div>
+            </div>
+            <div class="field">
+                <div class="label"><label for="ldap_search_scope">${_('LDAP Search Scope')}</label></div>
+                <div class="select">${h.select('ldap_search_scope',c.search_scope_cur,c.search_scope_choices,class_='small')}</div>
+            </div>
+	  <h3>${_('Attribute mappings')}</h3>
+            <div class="field">
+                <div class="label"><label for="ldap_attr_login">${_('Login Attribute')}</label></div>
+                <div class="input">${h.text('ldap_attr_login',class_='small')}</div>
+            </div>
+            <div class="field">
+                <div class="label"><label for="ldap_attr_firstname">${_('First Name Attribute')}</label></div>
+                <div class="input">${h.text('ldap_attr_firstname',class_='small')}</div>
+            </div>
+            <div class="field">
+                <div class="label"><label for="ldap_attr_lastname">${_('Last Name Attribute')}</label></div>
+                <div class="input">${h.text('ldap_attr_lastname',class_='small')}</div>
+            </div>
+            <div class="field">
+                <div class="label"><label for="ldap_attr_email">${_('E-mail Attribute')}</label></div>
+                <div class="input">${h.text('ldap_attr_email',class_='small')}</div>
+            </div>
             
             <div class="buttons">
-            ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+            ${h.submit('save',_('Save'),class_="ui-button")}
             </div>              
         </div>
     </div>     
--- a/rhodecode/templates/admin/permissions/permissions.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/permissions/permissions.html	Fri Oct 07 01:08:50 2011 +0200
@@ -68,7 +68,7 @@
              </div>	
 				        
 	        <div class="buttons">
-	        ${h.submit('set','set',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+	        ${h.submit('set',_('set'),class_="ui-button")}
 	        </div>	                                                               
         </div>
     </div>  
--- a/rhodecode/templates/admin/repos/repo_add.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/repos/repo_add.html	Fri Oct 07 01:08:50 2011 +0200
@@ -16,53 +16,13 @@
 <%def name="page_nav()">
 	${self.menu('admin')}
 </%def>
+
 <%def name="main()">
-<div class="box">
-    <!-- box / title -->
-    <div class="title">
-        ${self.breadcrumbs()}      
-    </div>
-    ${h.form(url('repos'))}
-    <div class="form">
-        <!-- fields -->
-        <div class="fields">
-            <div class="field">
-	            <div class="label">
-	                <label for="repo_name">${_('Name')}:</label>
-	            </div>
-	            <div class="input">
-	                ${h.text('repo_name',c.new_repo,class_="small")}
-	            </div>
-             </div>
-            <div class="field">
-                <div class="label">
-                    <label for="repo_type">${_('Type')}:</label>
-                </div>
-                <div class="input">
-                    ${h.select('repo_type','hg',c.backends,class_="small")}
-                </div>
-             </div>             
-            <div class="field">
-                <div class="label label-textarea">
-                    <label for="description">${_('Description')}:</label>
-                </div>
-                <div class="textarea text-area editor">
-                    ${h.textarea('description',cols=23,rows=5)}
-                </div>
-             </div>
-            <div class="field">
-                <div class="label label-checkbox">
-                    <label for="private">${_('Private')}:</label>
-                </div>
-                <div class="checkboxes">
-                    ${h.checkbox('private',value="True")}
-                </div>
-             </div>
-	        <div class="buttons">
-	          ${h.submit('add','add',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-	        </div>                                                          
-        </div>
-    </div>    
-    ${h.end_form()}    
-</div>
-</%def>   
+	<div class="box">
+	    <!-- box / title -->
+	    <div class="title">
+	        ${self.breadcrumbs()}      
+	    </div>
+        <%include file="repo_add_base.html"/>
+    </div>        
+</%def>   
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/repos/repo_add_base.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,63 @@
+## -*- coding: utf-8 -*-
+
+${h.form(url('repos'))}
+<div class="form">
+    <!-- fields -->
+    <div class="fields">
+        <div class="field">
+            <div class="label">
+                <label for="repo_name">${_('Name')}:</label>
+            </div>
+            <div class="input">
+                ${h.text('repo_name',c.new_repo,class_="small")}
+                %if not h.HasPermissionAll('hg.admin')('repo create form'):
+                    ${h.hidden('user_created',True)}
+                %endif
+            </div>
+         </div>
+        <div class="field">
+            <div class="label">
+                <label for="clone_uri">${_('Clone from')}:</label>
+            </div>
+            <div class="input">
+                ${h.text('clone_uri',class_="small")}
+            </div>
+         </div>             
+         <div class="field">
+             <div class="label">
+                 <label for="repo_group">${_('Repository group')}:</label>
+             </div>
+             <div class="input">
+                 ${h.select('repo_group','',c.repo_groups,class_="medium")}
+             </div>
+         </div>         
+        <div class="field">
+            <div class="label">
+                <label for="repo_type">${_('Type')}:</label>
+            </div>
+            <div class="input">
+                ${h.select('repo_type','hg',c.backends,class_="small")}
+            </div>
+         </div>             
+        <div class="field">
+            <div class="label label-textarea">
+                <label for="description">${_('Description')}:</label>
+            </div>
+            <div class="textarea text-area editor">
+                ${h.textarea('description',cols=23,rows=5)}
+            </div>
+         </div>
+        <div class="field">
+            <div class="label label-checkbox">
+                <label for="private">${_('Private')}:</label>
+            </div>
+            <div class="checkboxes">
+                ${h.checkbox('private',value="True")}
+            </div>
+         </div>
+        <div class="buttons">
+          ${h.submit('add',_('add'),class_="ui-button")}
+        </div>                                                          
+    </div>
+</div>    
+${h.end_form()}    
--- a/rhodecode/templates/admin/repos/repo_add_create_repository.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/repos/repo_add_create_repository.html	Fri Oct 07 01:08:50 2011 +0200
@@ -12,54 +12,13 @@
 <%def name="page_nav()">
 	${self.menu('admin')}
 </%def>
+
 <%def name="main()">
-<div class="box">
-    <!-- box / title -->
-    <div class="title">
-        ${self.breadcrumbs()}      
-    </div>
-    ${h.form(url('repos'))}
-    <div class="form">
-        <!-- fields -->
-        <div class="fields">
-            <div class="field">
-	            <div class="label">
-	                <label for="repo_name">${_('Name')}:</label>
-	            </div>
-	            <div class="input">
-	                ${h.text('repo_name',c.new_repo,class_="small")}
-	                ${h.hidden('user_created','True')}
-	            </div>
-             </div>
-            <div class="field">
-                <div class="label">
-                    <label for="repo_type">${_('Type')}:</label>
-                </div>
-                <div class="input">
-                    ${h.select('repo_type','hg',c.backends,class_="small")}
-                </div>
-             </div>             
-            <div class="field">
-                <div class="label label-textarea">
-                    <label for="description">${_('Description')}:</label>
-                </div>
-                <div class="textarea text-area editor">
-                    ${h.textarea('description',cols=23,rows=5)}
-                </div>
-             </div>
-            <div class="field">
-                <div class="label label-checkbox">
-                    <label for="private">${_('Private')}:</label>
-                </div>
-                <div class="checkboxes">
-                    ${h.checkbox('private',value="True")}
-                </div>
-             </div>
-	        <div class="buttons">
-	          ${h.submit('add','add',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-	        </div>                                                          
+    <div class="box">
+        <!-- box / title -->
+        <div class="title">
+            ${self.breadcrumbs()}      
         </div>
-    </div>    
-    ${h.end_form()}    
-</div>
-</%def>   
+        <%include file="repo_add_base.html"/>
+    </div>        
+</%def>
\ No newline at end of file
--- a/rhodecode/templates/admin/repos/repo_edit.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/repos/repo_edit.html	Fri Oct 07 01:08:50 2011 +0200
@@ -10,7 +10,7 @@
     &raquo; 
     ${h.link_to(_('Repositories'),h.url('repos'))} 
     &raquo;
-    ${_('edit')} "${c.repo_name}"
+    ${_('edit')} &raquo; ${h.link_to(c.repo_info.just_name,h.url('summary_home',repo_name=c.repo_name))}
 </%def>
 
 <%def name="page_nav()">
@@ -34,7 +34,23 @@
                 <div class="input">
                     ${h.text('repo_name',class_="medium")}
                 </div>
-             </div>
+           </div>
+	       <div class="field">
+	           <div class="label">
+	               <label for="clone_uri">${_('Clone uri')}:</label>
+	           </div>
+	           <div class="input">
+	               ${h.text('clone_uri',class_="medium")}
+	           </div>
+	        </div>             
+	        <div class="field">
+	            <div class="label">
+	                <label for="repo_group">${_('Repository group')}:</label>
+	            </div>
+	            <div class="input">
+	                ${h.select('repo_group','',c.repo_groups,class_="medium")}
+	            </div>
+	        </div>         
             <div class="field">
                 <div class="label">
                     <label for="repo_type">${_('Type')}:</label>
@@ -42,7 +58,7 @@
                 <div class="input">
                     ${h.select('repo_type','hg',c.backends,class_="medium")}
                 </div>
-             </div>             
+            </div>             
             <div class="field">
                 <div class="label label-textarea">
                     <label for="description">${_('Description')}:</label>
@@ -67,7 +83,15 @@
                 <div class="checkboxes">
                     ${h.checkbox('enable_statistics',value="True")}
                 </div>
-            </div>             
+            </div>     
+            <div class="field">
+                <div class="label label-checkbox">
+                    <label for="enable_downloads">${_('Enable downloads')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('enable_downloads',value="True")}
+                </div>
+            </div>                      
             <div class="field">
                 <div class="label">
                     <label for="user">${_('Owner')}:</label>
@@ -85,207 +109,17 @@
                     <label for="input">${_('Permissions')}:</label>
                 </div>
                 <div class="input">
-                    <table id="permissions_manage">
-                        <tr>
-                            <td>${_('none')}</td>
-                            <td>${_('read')}</td>
-                            <td>${_('write')}</td>
-                            <td>${_('admin')}</td>
-                            <td>${_('user')}</td>
-                            <td></td>
-                        </tr>
-                        
-                        %for r2p in c.repo_info.repo_to_perm:
-                            %if r2p.user.username =='default' and c.repo_info.private:
-                                <tr>
-                                    <td colspan="4">
-                                        <span class="private_repo_msg">
-                                        ${_('private repository')}
-                                        </span>
-                                    </td>
-                                    <td class="private_repo_msg">${r2p.user.username}</td>
-                                </tr>
-                            %else:
-                            <tr id="id${id(r2p.user.username)}">
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
-                                <td>${r2p.user.username}</td>
-                                <td>
-                                  %if r2p.user.username !='default':
-                                    <span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
-                                        <script type="text/javascript">
-                                            function ajaxAction(user_id,field_id){
-                                                var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
-                                                var callback = { success:function(o){
-                                                var tr = YAHOO.util.Dom.get(String(field_id));
-                                                tr.parentNode.removeChild(tr);},failure:function(o){
-                                                    alert("${_('Failed to remove user')}");},};
-                                                var postData = '_method=delete&user_id='+user_id; 
-                                                var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
-                                        </script>           
-                                    </span>
-                                  %endif                    
-                                </td>
-                            </tr>
-                            %endif
-                        %endfor
-
-                        <tr id="add_perm_input">
-                            <td>${h.radio('perm_new_user','repository.none')}</td>
-                            <td>${h.radio('perm_new_user','repository.read')}</td>
-                            <td>${h.radio('perm_new_user','repository.write')}</td>
-                            <td>${h.radio('perm_new_user','repository.admin')}</td>
-                            <td class='ac'>
-                                <div class="perm_ac" id="perm_ac">
-                                    ${h.text('perm_new_user_name',class_='yui-ac-input')}
-                                    <div id="perm_container"></div>
-                                </div>
-                            </td>
-                            <td></td>
-                        </tr>
-                        <tr>
-                            <td colspan="6">
-                                <span id="add_perm" class="add_icon" style="cursor: pointer;">
-                                ${_('Add another user')}
-                                </span>
-                            </td>
-                        </tr>
-                    </table>             
-             </div>
+                    <%include file="repo_edit_perms.html"/>
+                </div>
              
             <div class="buttons">
-              ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-              ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+              ${h.submit('save','Save',class_="ui-button")}
+              ${h.reset('reset','Reset',class_="ui-button")}
             </div>                                                          
         </div>
     </div>
     </div>    
     ${h.end_form()}
-        <script type="text/javascript">
-            YAHOO.util.Event.onDOMReady(function(){
-                var D = YAHOO.util.Dom;
-                if(!D.hasClass('perm_new_user_name','error')){
-                    D.setStyle('add_perm_input','display','none');
-                }
-                YAHOO.util.Event.addListener('add_perm','click',function(){
-                    D.setStyle('add_perm_input','display','');
-                    D.setStyle('add_perm','opacity','0.6');
-                    D.setStyle('add_perm','cursor','default');
-                });
-            });
-        </script>
-        <script type="text/javascript">    
-        YAHOO.example.FnMultipleFields = function(){
-            var myContacts = ${c.users_array|n}
-            
-            // Define a custom search function for the DataSource
-            var matchNames = function(sQuery) {
-                // Case insensitive matching
-                var query = sQuery.toLowerCase(),
-                    contact,
-                    i=0,
-                    l=myContacts.length,
-                    matches = [];
-                
-                // Match against each name of each contact
-                for(; i<l; i++) {
-                    contact = myContacts[i];
-                    if((contact.fname.toLowerCase().indexOf(query) > -1) ||
-                        (contact.lname.toLowerCase().indexOf(query) > -1) ||
-                        (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
-                        matches[matches.length] = contact;
-                    }
-                }
-        
-                return matches;
-            };
-        
-            // Use a FunctionDataSource
-            var oDS = new YAHOO.util.FunctionDataSource(matchNames);
-            oDS.responseSchema = {
-                fields: ["id", "fname", "lname", "nname"]
-            }
-        
-            // Instantiate AutoComplete for perms
-            var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
-            oAC_perms.useShadow = false;
-            oAC_perms.resultTypeList = false;
-            
-            // Instantiate AutoComplete for owner
-            var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
-            oAC_owner.useShadow = false;
-            oAC_owner.resultTypeList = false;
-            
-            
-            // Custom formatter to highlight the matching letters
-            var custom_formatter = function(oResultData, sQuery, sResultMatch) {
-                var query = sQuery.toLowerCase(),
-                    fname = oResultData.fname,
-                    lname = oResultData.lname,
-                    nname = oResultData.nname || "", // Guard against null value
-                    query = sQuery.toLowerCase(),
-                    fnameMatchIndex = fname.toLowerCase().indexOf(query),
-                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
-                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
-                    displayfname, displaylname, displaynname;
-                    
-                if(fnameMatchIndex > -1) {
-                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
-                }
-                else {
-                    displayfname = fname;
-                }
-        
-                if(lnameMatchIndex > -1) {
-                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
-                }
-                else {
-                    displaylname = lname;
-                }
-        
-                if(nnameMatchIndex > -1) {
-                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
-                }
-                else {
-                    displaynname = nname ? "(" + nname + ")" : "";
-                }
-        
-                return displayfname + " " + displaylname + " " + displaynname;
-                
-            };
-            oAC_perms.formatResult = custom_formatter; 
-            oAC_owner.formatResult = custom_formatter;
-                            
-            // Helper function for the formatter
-            var highlightMatch = function(full, snippet, matchindex) {
-                return full.substring(0, matchindex) + 
-                        "<span class='match'>" + 
-                        full.substr(matchindex, snippet.length) + 
-                        "</span>" +
-                        full.substring(matchindex + snippet.length);
-            };
-        
-            var myHandler = function(sType, aArgs) {
-                var myAC = aArgs[0]; // reference back to the AC instance
-                var elLI = aArgs[1]; // reference to the selected LI element
-                var oData = aArgs[2]; // object literal of selected item's result data
-                myAC.getInputEl().value = oData.nname;
-            };
-
-            oAC_perms.itemSelectEvent.subscribe(myHandler);
-            oAC_owner.itemSelectEvent.subscribe(myHandler);
-            
-            return {
-                oDS: oDS,
-                oAC_perms: oAC_perms,
-                oAC_owner: oAC_owner, 
-            };
-        }();
-            
-        </script>      
-
 </div>
 
 <div class="box box-right">
@@ -294,13 +128,11 @@
     </div>
     
         <h3>${_('Statistics')}</h3>
-        
         ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')}
         <div class="form">
            <div class="fields">
-               ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('Confirm to remove current statistics');")}
-               
-               <div class="field">
+               ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")}
+               <div class="field" style="border:none">
                <ul>
                     <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
                     <li>${_('Percentage of stats gathered')}: ${c.stats_percentage} %</li>
@@ -311,21 +143,50 @@
         </div>                    
         ${h.end_form()}
         
+        %if c.repo_info.clone_uri:
+        <h3>${_('Remote')}</h3>
+        ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')}
+        <div class="form">
+           <div class="fields">
+               ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="pull_icon action_button",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
+               <div class="field" style="border:none">
+               <ul>
+                    <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li>
+               </ul> 
+               </div>              
+           </div>
+        </div>                    
+        ${h.end_form()}
+        %endif
+        
         <h3>${_('Cache')}</h3>
         ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')}
         <div class="form">
            <div class="fields">
-               ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="refresh_icon action_button",onclick="return confirm('Confirm to invalidate repository cache');")}
+               ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="refresh_icon action_button",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")}
            </div>
         </div>                    
         ${h.end_form()}
         
+        <h3>${_('Public journal')}</h3>
+        ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
+        <div class="form">
+            <div class="fields">
+                ${h.hidden('auth_token',str(h.get_token()))}
+                %if c.in_public_journal:
+                    ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="stop_following_icon action_button")}
+                %else:
+		            ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="start_following_icon action_button")}
+		        %endif
+	         </div>        
+        </div>
+        ${h.end_form()}
         
         <h3>${_('Delete')}</h3>
         ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
         <div class="form">
            <div class="fields">
-               ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
+               ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository')+"');")}
            </div>
         </div>                    
         ${h.end_form()}
@@ -333,4 +194,4 @@
 </div>
 
 
-</%def> 
\ No newline at end of file
+</%def> 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/repos/repo_edit_perms.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,281 @@
+<table id="permissions_manage">
+    <tr>
+        <td>${_('none')}</td>
+        <td>${_('read')}</td>
+        <td>${_('write')}</td>
+        <td>${_('admin')}</td>
+        <td>${_('member')}</td>
+        <td></td>
+    </tr>
+    ## USERS                        
+    %for r2p in c.repo_info.repo_to_perm:
+        %if r2p.user.username =='default' and c.repo_info.private:
+            <tr>
+                <td colspan="4">
+                    <span class="private_repo_msg">
+                    ${_('private repository')}
+                    </span>
+                </td>
+                <td class="private_repo_msg"><img style="vertical-align:bottom" src="${h.url("/images/icons/user.png")}"/>${r2p.user.username}</td>
+            </tr>
+        %else:
+        <tr id="id${id(r2p.user.username)}">
+            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.none')}</td>
+            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.read')}</td>
+            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.write')}</td>
+            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.admin')}</td>
+            <td style="white-space: nowrap;">
+                <img style="vertical-align:bottom" src="${h.url('/images/icons/user.png')}"/>${r2p.user.username}
+            </td>
+            <td>
+              %if r2p.user.username !='default':
+                <span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
+                ${_('revoke')}
+                </span>
+              %endif                    
+            </td>
+        </tr>
+        %endif
+    %endfor
+    
+    ## USERS GROUPS                          
+    %for g2p in c.repo_info.users_group_to_perm:
+        <tr id="id${id(g2p.users_group.users_group_name)}">
+            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.none')}</td>
+            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.read')}</td>
+            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.write')}</td>
+            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.admin')}</td>
+            <td style="white-space: nowrap;">
+                <img  style="vertical-align:bottom" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
+            </td>
+            <td>
+                <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
+                ${_('revoke')}
+                </span>
+            </td>
+        </tr>
+    %endfor
+    <tr id="add_perm_input">
+        <td>${h.radio('perm_new_member','repository.none')}</td>
+        <td>${h.radio('perm_new_member','repository.read')}</td>
+        <td>${h.radio('perm_new_member','repository.write')}</td>
+        <td>${h.radio('perm_new_member','repository.admin')}</td>
+        <td class='ac'>
+            <div class="perm_ac" id="perm_ac">
+                ${h.text('perm_new_member_name',class_='yui-ac-input')}
+                ${h.hidden('perm_new_member_type')}
+                <div id="perm_container"></div>
+            </div>
+        </td>
+        <td></td>
+    </tr>
+    <tr>
+        <td colspan="6">
+            <span id="add_perm" class="add_icon" style="cursor: pointer;">
+            ${_('Add another member')}
+            </span>
+        </td>
+    </tr>
+</table>
+<script type="text/javascript">
+function ajaxActionUser(user_id, field_id) {
+    var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
+    var callback = {
+        success: function (o) {
+            var tr = YUD.get(String(field_id));
+            tr.parentNode.removeChild(tr);
+        },
+        failure: function (o) {
+            alert("${_('Failed to remove user')}");
+        },
+    };
+    var postData = '_method=delete&user_id=' + user_id;
+    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
+};
+            
+function ajaxActionUsersGroup(users_group_id,field_id){
+    var sUrl = "${h.url('delete_repo_users_group',repo_name=c.repo_name)}";
+    var callback = { 
+    	success:function(o){
+    	    var tr = YUD.get(String(field_id));
+    		tr.parentNode.removeChild(tr);
+    	},
+        failure:function(o){
+            alert("${_('Failed to remove users group')}");
+        },
+    };
+    var postData = '_method=delete&users_group_id='+users_group_id; 
+    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
+};
+
+YUE.onDOMReady(function () {
+    if (!YUD.hasClass('perm_new_member_name', 'error')) {
+        YUD.setStyle('add_perm_input', 'display', 'none');
+    }
+    YAHOO.util.Event.addListener('add_perm', 'click', function () {
+        YUD.setStyle('add_perm_input', 'display', '');
+        YUD.setStyle('add_perm', 'opacity', '0.6');
+        YUD.setStyle('add_perm', 'cursor', 'default');
+    });
+});
+
+YAHOO.example.FnMultipleFields = function () {
+    var myUsers = ${c.users_array|n};
+    var myGroups = ${c.users_groups_array|n};
+
+    // Define a custom search function for the DataSource of users
+    var matchUsers = function (sQuery) {
+            // Case insensitive matching
+            var query = sQuery.toLowerCase();
+            var i = 0;
+            var l = myUsers.length;
+            var matches = [];
+
+            // Match against each name of each contact
+            for (; i < l; i++) {
+                contact = myUsers[i];
+                if ((contact.fname.toLowerCase().indexOf(query) > -1) || (contact.lname.toLowerCase().indexOf(query) > -1) || (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
+                    matches[matches.length] = contact;
+                }
+            }
+            return matches;
+        };
+
+    // Define a custom search function for the DataSource of usersGroups
+    var matchGroups = function (sQuery) {
+            // Case insensitive matching
+            var query = sQuery.toLowerCase();
+            var i = 0;
+            var l = myGroups.length;
+            var matches = [];
+
+            // Match against each name of each contact
+            for (; i < l; i++) {
+                matched_group = myGroups[i];
+                if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
+                    matches[matches.length] = matched_group;
+                }
+            }
+            return matches;
+        };
+
+    //match all
+    var matchAll = function (sQuery) {
+            u = matchUsers(sQuery);
+            g = matchGroups(sQuery);
+            return u.concat(g);
+        };
+
+    // DataScheme for members
+    var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
+    memberDS.responseSchema = {
+        fields: ["id", "fname", "lname", "nname", "grname", "grmembers"]
+    };
+
+    // DataScheme for owner
+    var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
+    ownerDS.responseSchema = {
+        fields: ["id", "fname", "lname", "nname"]
+    };
+
+    // Instantiate AutoComplete for perms
+    var membersAC = new YAHOO.widget.AutoComplete("perm_new_member_name", "perm_container", memberDS);
+    membersAC.useShadow = false;
+    membersAC.resultTypeList = false;
+
+    // Instantiate AutoComplete for owner
+    var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
+    ownerAC.useShadow = false;
+    ownerAC.resultTypeList = false;
+
+
+    // Helper highlight function for the formatter
+    var highlightMatch = function (full, snippet, matchindex) {
+            return full.substring(0, matchindex) + "<span class='match'>" + full.substr(matchindex, snippet.length) + "</span>" + full.substring(matchindex + snippet.length);
+        };
+
+    // Custom formatter to highlight the matching letters
+    var custom_formatter = function (oResultData, sQuery, sResultMatch) {
+            var query = sQuery.toLowerCase();
+
+            if (oResultData.grname != undefined) {
+                var grname = oResultData.grname;
+                var grmembers = oResultData.grmembers;
+                var grnameMatchIndex = grname.toLowerCase().indexOf(query);
+                var grprefix = "${_('Group')}: ";
+                var grsuffix = " (" + grmembers + "  ${_('members')})";
+
+                if (grnameMatchIndex > -1) {
+                    return grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix;
+                }
+
+                return grprefix + oResultData.grname + grsuffix;
+            } else if (oResultData.fname != undefined) {
+
+                var fname = oResultData.fname,
+                    lname = oResultData.lname,
+                    nname = oResultData.nname || "",
+                    // Guard against null value
+                    fnameMatchIndex = fname.toLowerCase().indexOf(query),
+                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
+                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
+                    displayfname, displaylname, displaynname;
+
+                if (fnameMatchIndex > -1) {
+                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
+                } else {
+                    displayfname = fname;
+                }
+
+                if (lnameMatchIndex > -1) {
+                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
+                } else {
+                    displaylname = lname;
+                }
+
+                if (nnameMatchIndex > -1) {
+                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
+                } else {
+                    displaynname = nname ? "(" + nname + ")" : "";
+                }
+
+                return displayfname + " " + displaylname + " " + displaynname;
+            } else {
+                return '';
+            }
+        };
+    membersAC.formatResult = custom_formatter;
+    ownerAC.formatResult = custom_formatter;
+
+    var myHandler = function (sType, aArgs) {
+
+            var myAC = aArgs[0]; // reference back to the AC instance
+            var elLI = aArgs[1]; // reference to the selected LI element
+            var oData = aArgs[2]; // object literal of selected item's result data
+            //fill the autocomplete with value
+            if (oData.nname != undefined) {
+                //users
+                myAC.getInputEl().value = oData.nname;
+                YUD.get('perm_new_member_type').value = 'user';
+            } else {
+                //groups
+                myAC.getInputEl().value = oData.grname;
+                YUD.get('perm_new_member_type').value = 'users_group';
+            }
+
+        };
+
+    membersAC.itemSelectEvent.subscribe(myHandler);
+    if(ownerAC.itemSelectEvent){
+    	ownerAC.itemSelectEvent.subscribe(myHandler);	
+    }
+
+    return {
+        memberDS: memberDS,
+        ownerDS: ownerDS,
+        membersAC: membersAC,
+        ownerAC: ownerAC,
+    };
+}();
+            
+</script>      
\ No newline at end of file
--- a/rhodecode/templates/admin/repos/repos.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/repos/repos.html	Fri Oct 07 01:08:50 2011 +0200
@@ -19,7 +19,7 @@
         ${self.breadcrumbs()}
         <ul class="links">
           <li>
-            <span>${h.link_to(u'ADD NEW REPOSITORY',h.url('new_repo'))}</span>
+            <span>${h.link_to(_(u'ADD NEW REPOSITORY'),h.url('new_repo'))}</span>
           </li>          
         </ul>        
     </div>
@@ -38,26 +38,26 @@
             <tr class="parity${cnt%2}">
                  <td>
                  ## TYPE OF REPO
-                 %if repo['repo'].dbrepo.repo_type =='hg':
-                   <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
-                 %elif repo['repo'].dbrepo.repo_type =='git':
-                   <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
+                 %if repo['dbrepo']['repo_type'] =='hg':
+                   <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
+                 %elif repo['dbrepo']['repo_type'] =='git':
+                   <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
                  %else:
                    
                  %endif
                  
                  ## PRIVATE/PUBLIC REPO                  
-                 %if repo['repo'].dbrepo.private:
-                    <img alt="${_('private')}" src="${h.url("/images/icons/lock.png")}"/>
+                 %if repo['dbrepo']['private']:
+                    <img alt="${_('private')}" src="${h.url('/images/icons/lock.png')}"/>
                  %else:
-                    <img alt="${_('public')}" src="${h.url("/images/icons/lock_open.png")}"/>
+                    <img alt="${_('public')}" src="${h.url('/images/icons/lock_open.png')}"/>
                  %endif         
                 ${h.link_to(repo['name'],h.url('edit_repo',repo_name=repo['name']))}
                 
-	            %if repo['repo'].dbrepo.fork:
-	            	<a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
+	            %if repo['dbrepo_fork']:
+	            	<a href="${h.url('summary_home',repo_name=repo['dbrepo_fork']['repo_name'])}">
 	            	<img class="icon" alt="${_('public')}"
-	            	title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}" 
+	            	title="${_('Fork of')} ${repo['dbrepo_fork']['repo_name']}" 
 	            	src="${h.url("/images/icons/arrow_divide.png")}"/></a>
 	            %endif                
                 </td>
@@ -76,7 +76,7 @@
 	            <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
                 <td>
                   ${h.form(url('repo', repo_name=repo['name']),method='delete')}
-                    ${h.submit('remove_%s' % repo['name'],'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
+                    ${h.submit('remove_%s' % repo['name'],_('delete'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository')+"');")}
                   ${h.end_form()}
                 </td>
             </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/repos_groups/repos_groups.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,21 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+<%def name="title()">
+    ${_('Repository group')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs()">
+    ${_('Groups')} 
+    %if c.group.parent_group:
+        &raquo; ${h.link_to(c.group.parent_group.group_name,
+        h.url('repos_group',id=c.group.parent_group.group_id))}
+    %endif
+    &raquo; "${c.group.group_name}" ${_('with')} 
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+<%def name="main()">
+        <%include file="/index_base.html" args="parent=self"/>
+</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/repos_groups/repos_groups_add.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,64 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Add repos group')} - ${c.rhodecode_name}
+</%def>
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} 
+    &raquo; 
+    ${h.link_to(_('Repos groups'),h.url('repos_groups'))} 
+    &raquo;
+    ${_('add new repos group')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}       
+    </div>
+    <!-- end box / title -->
+    ${h.form(url('repos_groups'))}
+    <div class="form">
+        <!-- fields -->
+        <div class="fields">
+             <div class="field">
+                <div class="label">
+                    <label for="users_group_name">${_('Group name')}:</label>
+                </div>
+                <div class="input">
+                    ${h.text('group_name',class_='medium')}
+                </div>
+             </div>
+             
+            <div class="field">
+                <div class="label label-textarea">
+                    <label for="description">${_('Description')}:</label>
+                </div>
+                <div class="textarea text-area editor">
+                    ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
+                </div>
+             </div>
+             
+             <div class="field">
+                 <div class="label">
+                     <label for="repo_group">${_('Group parent')}:</label>
+                 </div>
+                 <div class="input">
+                     ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
+                 </div>
+             </div>            
+                         
+            <div class="buttons">
+              ${h.submit('save',_('save'),class_="ui-button")}
+            </div>             
+        </div>
+    </div>
+    ${h.end_form()}
+</div>    
+</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/repos_groups/repos_groups_edit.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,64 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Edit repos group')} ${c.repos_group.group_name} - ${c.rhodecode_name}
+</%def>
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} 
+    &raquo; 
+    ${h.link_to(_('Repos groups'),h.url('repos_groups'))} 
+    &raquo;
+    ${_('edit repos group')} "${c.repos_group.group_name}"
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}       
+    </div>
+    <!-- end box / title -->
+    ${h.form(url('repos_group',id=c.repos_group.group_id),method='put')}
+    <div class="form">
+        <!-- fields -->
+        <div class="fields">
+             <div class="field">
+                <div class="label">
+                    <label for="users_group_name">${_('Group name')}:</label>
+                </div>
+                <div class="input">
+                    ${h.text('group_name',class_='medium')}
+                </div>
+             </div>
+             
+	        <div class="field">
+	            <div class="label label-textarea">
+	                <label for="description">${_('Description')}:</label>
+	            </div>
+	            <div class="textarea text-area editor">
+	                ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
+	            </div>
+	         </div>
+             
+	         <div class="field">
+	             <div class="label">
+	                 <label for="repo_group">${_('Group parent')}:</label>
+	             </div>
+	             <div class="input">
+	                 ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
+	             </div>
+	         </div>             
+                         
+            <div class="buttons">
+              ${h.submit('save',_('save'),class_="ui-button")}
+            </div>             
+        </div>
+    </div>
+    ${h.end_form()}
+</div>    
+</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/repos_groups/repos_groups_show.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,68 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Repositories groups administration')} - ${c.rhodecode_name}
+</%def>
+
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Repositories')}
+</%def>
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+        <ul class="links">
+          <li>
+            <span>${h.link_to(_(u'ADD NEW GROUP'),h.url('new_repos_group'))}</span>
+          </li>          
+        </ul>        
+    </div>
+    <!-- end box / title -->
+    <div class="table">
+           % if c.groups:
+            <table class="table_disp">
+            
+                <thead>
+                    <tr>
+                        <th class="left"><a href="#">${_('Group name')}</a></th>
+                        <th class="left"><a href="#">${_('Description')}</a></th>
+                        <th class="left"><a href="#">${_('Number of repositories')}</a></th>
+                        <th class="left">${_('action')}</th>
+                    </tr>
+                </thead>
+                
+                ## REPO GROUPS
+                
+                % for gr in c.groups:
+                  <tr>
+                      <td>
+                          <div style="white-space: nowrap">
+                          <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
+                          ${h.link_to(h.literal(' &raquo; '.join([g.group_name for g in gr.parents+[gr]])),url('edit_repos_group',id=gr.group_id))}
+                          </div>
+                      </td>
+                      <td>${gr.group_description}</td>
+                      <td><b>${gr.repositories.count()}</b></td>
+		               <td>
+		                 ${h.form(url('repos_group', id=gr.group_id),method='delete')}
+		                   ${h.submit('remove_%s' % gr.group_name,'delete',class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this group')+"');")}
+		                 ${h.end_form()}
+		               </td>                      
+                  </tr>
+                % endfor
+                
+            </table>
+            % else:
+                ${_('There are no repositories groups yet')}
+            % endif
+         
+    </div>
+</div> 
+           
+</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/settings/hooks.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,96 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Settings administration')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Settings')}
+</%def>
+
+<%def name="page_nav()">
+	${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}       
+    </div>
+    <!-- end box / title -->
+    
+    <h3>${_('Built in hooks - read only')}</h3>
+    <div class="form">
+        <div class="fields">
+          % for hook in c.hooks:
+          <div class="field">
+	        <div class="label label">
+	            <label for="${hook.ui_key}">${hook.ui_key}</label>
+	        </div>
+	        <div class="input" style="margin-left:280px">
+                  ${h.text(hook.ui_key,hook.ui_value,size=60,readonly="readonly")}
+	        </div>
+          </div>
+          % endfor
+		</div>
+    </div>
+    
+    <h3>${_('Custom hooks')}</h3>
+    ${h.form(url('admin_setting', setting_id='hooks'),method='put')}
+    <div class="form">
+        <div class="fields">
+        
+          % for hook in c.custom_hooks:
+          <div class="field"  id="${'id%s' % hook.ui_id }">
+            <div class="label label">
+                <label for="${hook.ui_key}">${hook.ui_key}</label>
+            </div>
+            <div class="input" style="margin-left:280px">                
+                ${h.hidden('hook_ui_key',hook.ui_key)}
+                ${h.hidden('hook_ui_value',hook.ui_value)}
+                ${h.text('hook_ui_value_new',hook.ui_value,size=60)}
+                <span class="delete_icon action_button" 
+                onclick="ajaxActionHook(${hook.ui_id},'${'id%s' % hook.ui_id }')">
+                ${_('remove')}
+                </span>
+            </div>
+          </div>
+          % endfor        
+        
+          <div class="field">
+            <div class="input" style="margin-left:-180px;position: absolute;">
+              <div class="input">
+                 ${h.text('new_hook_ui_key',size=30)}
+              </div>
+            </div>
+            <div class="input" style="margin-left:280px">
+                ${h.text('new_hook_ui_value',size=60)}
+            </div>
+          </div>
+          <div class="buttons" style="margin-left:280px">
+             ${h.submit('save',_('Save'),class_="ui-button")}
+          </div>          
+        </div>
+    </div>
+    ${h.end_form()}
+</div>
+<script type="text/javascript">
+function ajaxActionHook(hook_id,field_id) {
+    var sUrl = "${h.url('admin_setting', setting_id='hooks')}";
+    var callback = {
+        success: function (o) {
+            var elem = YUD.get(""+field_id);
+            elem.parentNode.removeChild(elem);
+        },
+        failure: function (o) {
+            alert("${_('Failed to remove hook')}");
+        },
+    };
+    var postData = '_method=delete&hook_id=' + hook_id;
+    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
+};
+</script>
+      
+</%def>    
--- a/rhodecode/templates/admin/settings/settings.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/settings/settings.html	Fri Oct 07 01:08:50 2011 +0200
@@ -42,7 +42,7 @@
 			</div>
                             
             <div class="buttons">
-            ${h.submit('rescan','Rescan repositories',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+            ${h.submit('rescan',_('Rescan repositories'),class_="ui-button")}
             </div>                                                          
         </div>
     </div>  
@@ -67,7 +67,7 @@
             </div>
                             
             <div class="buttons">
-            ${h.submit('reindex','Reindex',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+            ${h.submit('reindex',_('Reindex'),class_="ui-button")}
             </div>                                                          
         </div>
     </div>  
@@ -97,10 +97,19 @@
                     ${h.text('rhodecode_realm',size=30)}
                 </div>
             </div>
-                                     
+            
+            <div class="field">
+                <div class="label">
+                    <label for="ga_code">${_('GA code')}:</label>
+                </div>
+                <div class="input">
+                    ${h.text('rhodecode_ga_code',size=30)}
+                </div>
+            </div>
+                                                 
             <div class="buttons">
-                ${h.submit('save','Save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-                ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+                ${h.submit('save',_('Save settings'),class_="ui-button")}
+                ${h.reset('reset',_('Reset'),class_="ui-button")}
            </div>                                                          
         </div>
     </div>      
@@ -129,6 +138,9 @@
                 <div class="label label-checkbox">
                     <label for="web_push_ssl">${_('Hooks')}:</label>
                 </div>
+                <div class="input">
+                    ${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'))}
+                </div>                
                 <div class="checkboxes">
 					<div class="checkbox">
 						${h.checkbox('hooks_changegroup_update','True')}
@@ -156,14 +168,14 @@
                 <div class="input">
                     ${h.text('paths_root_path',size=30,readonly="readonly")}			                    
 					<span id="path_unlock" class="tooltip" 
-						title="${h.tooltip(_('This a crucial application setting. If You really sure you need to change this, you must restart application in order to make this settings take effect. Click this label to unlock.'))}">
+						title="${h.tooltip(_('This a crucial application setting. If you are really sure you need to change this, you must restart application in order to make this setting take effect. Click this label to unlock.'))}">
 		                ${_('unlock')}</span>
                 </div>
             </div>
                                      
             <div class="buttons">
-                ${h.submit('save','Save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-                ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+                ${h.submit('save',_('Save settings'),class_="ui-button")}
+                ${h.reset('reset',_('Reset'),class_="ui-button")}
            </div>                                                          
         </div>
     </div>      
--- a/rhodecode/templates/admin/users/user_add.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/users/user_add.html	Fri Oct 07 01:08:50 2011 +0200
@@ -82,10 +82,10 @@
              </div>
             
             <div class="buttons">
-              ${h.submit('save','save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+              ${h.submit('save',_('save'),class_="ui-button")}
             </div>             
     	</div>
     </div>
     ${h.end_form()}
 </div>    
-</%def>    
\ No newline at end of file
+</%def>    
--- a/rhodecode/templates/admin/users/user_edit.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/users/user_edit.html	Fri Oct 07 01:08:50 2011 +0200
@@ -18,32 +18,45 @@
 </%def>
 
 <%def name="main()">
-<div class="box">
+<div class="box box-left">
     <!-- box / title -->
     <div class="title">
         ${self.breadcrumbs()}       
     </div>
     <!-- end box / title -->
-    ${h.form(url('user', id=c.user.user_id),method='put')}
+    ${h.form(url('update_user', id=c.user.user_id),method='put')}
     <div class="form">
-        <!-- fields -->
+        <div class="field">
+           <div class="gravatar_box">
+               <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
+               <p>
+               <strong>${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong><br/> 
+               ${_('Using')} ${c.user.email}
+               </p>
+           </div>
+        </div>
+        <div class="field">
+            <div class="label">
+                <label>${_('API key')}</label> ${c.user.api_key}
+            </div>
+        </div>
+                 
         <div class="fields">
              <div class="field">
-                <div class="gravatar_box">
-              		<div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
-              		<p>
-              		<strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/> 
-              		${_('Using')} ${c.user.email}
-              		</p>
-            	</div>
-             </div>        
-        
-             <div class="field">
                 <div class="label">
                     <label for="username">${_('Username')}:</label>
                 </div>
                 <div class="input">
-                    ${h.text('username',class_='small')}
+                    ${h.text('username',class_='medium')}
+                </div>
+             </div>
+            
+             <div class="field">
+                <div class="label">
+                    <label for="ldap_dn">${_('LDAP DN')}:</label>
+                </div>
+                <div class="input">
+                    ${h.text('ldap_dn',class_='medium')}
                 </div>
              </div>
             
@@ -52,7 +65,7 @@
                     <label for="new_password">${_('New password')}:</label>
                 </div>
                 <div class="input">
-                    ${h.password('new_password',class_='small')}
+                    ${h.password('new_password',class_='medium',autocomplete="off")}
                 </div>
              </div>
             
@@ -61,7 +74,7 @@
                     <label for="name">${_('First Name')}:</label>
                 </div>
                 <div class="input">
-                    ${h.text('name',class_='small')}
+                    ${h.text('name',class_='medium')}
                 </div>
              </div>
             
@@ -70,7 +83,7 @@
                     <label for="lastname">${_('Last Name')}:</label>
                 </div>
                 <div class="input">
-                    ${h.text('lastname',class_='small')}
+                    ${h.text('lastname',class_='medium')}
                 </div>
              </div>
             
@@ -79,7 +92,7 @@
                     <label for="email">${_('Email')}:</label>
                 </div>
                 <div class="input">
-                    ${h.text('email',class_='small')}
+                    ${h.text('email',class_='medium')}
                 </div>
              </div>
             
@@ -101,11 +114,36 @@
                 </div>
              </div>             
             <div class="buttons">
-              ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-              ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+              ${h.submit('save',_('Save'),class_="ui-button")}
+              ${h.reset('reset',_('Reset'),class_="ui-button")}
             </div>             
     	</div>    
     </div>
     ${h.end_form()}
-</div>    
-</%def>  
\ No newline at end of file
+</div>
+<div class="box box-right">
+    <!-- box / title -->
+    <div class="title">
+        <h5>${_('Permissions')}</h5>       
+    </div>
+    ${h.form(url('user_perm', id=c.user.user_id),method='put')}
+    <div class="form">
+        <!-- fields -->
+        <div class="fields">
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label for="">${_('Create repositories')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('create_repo_perm',value=True)}
+                </div>
+             </div>
+            <div class="buttons">
+              ${h.submit('save',_('Save'),class_="ui-button")}
+              ${h.reset('reset',_('Reset'),class_="ui-button")}
+            </div>             
+        </div>    
+    </div>
+    ${h.end_form()}    
+</div>
+</%def>
--- a/rhodecode/templates/admin/users/user_edit_my_account.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/users/user_edit_my_account.html	Fri Oct 07 01:08:50 2011 +0200
@@ -22,6 +22,30 @@
     </div>
     <!-- end box / title -->
     <div class="ui-tabs-panel ui-widget-content ui-corner-bottom">
+    ${h.form(url('admin_settings_my_accou## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('My account')} ${c.rhodecode_user.username} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${_('My Account')}
+</%def>
+
+<%def name="page_nav()">
+	${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+
+<div class="box box-left">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}       
+    </div>
+    <!-- end box / title -->
+    <div>
     ${h.form(url('admin_settings_my_account_update'),method='put')}
 	    <div class="form">
 	    
@@ -29,6 +53,193 @@
                 <div class="gravatar_box">
                     <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
                     <p>
+                    <strong>${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong><br/> 
+                    ${_('Using')} ${c.user.email}
+                    </p>
+                </div>
+             </div>   	    
+	        <div class="field">
+	            <div class="label">
+	                <label>${_('API key')}</label> ${c.user.api_key}
+	            </div>
+	        </div>	    
+	        <div class="fields">
+	             <div class="field">
+	                <div class="label">
+	                    <label for="username">${_('Username')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('username',class_="medium")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="new_password">${_('New password')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.password('new_password',class_="medium",autocomplete="off")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="name">${_('First Name')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('name',class_="medium")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="lastname">${_('Last Name')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('lastname',class_="medium")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="email">${_('Email')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('email',class_="medium")}
+	                </div>
+	             </div>
+	            
+	            <div class="buttons">
+	              ${h.submit('save',_('Save'),class_="ui-button")}
+	              ${h.reset('reset',_('Reset'),class_="ui-button")}
+	            </div>             
+	    	</div>
+	    </div>    	
+    ${h.end_form()}
+    </div>
+</div>    
+
+<div class="box box-right">
+    <!-- box / title -->
+    <div class="title">
+        <h5>${_('My repositories')} 
+        <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
+        </h5>
+         %if h.HasPermissionAny('hg.admin','hg.create.repository')():
+         <ul class="links">
+           <li>
+             <span>${h.link_to(_('ADD REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
+           </li>          
+         </ul>           
+         %endif        
+    </div>
+    <!-- end box / title -->
+    <div class="table">
+	    <table>
+	    <thead>
+            <tr>
+            <th class="left">${_('Name')}</th>
+            <th class="left">${_('revision')}</th>
+            <th colspan="2" class="left">${_('action')}</th>            
+	    </thead>
+	     <tbody>
+	     %if c.user_repos:
+		     %for repo in c.user_repos:
+		        <tr>
+		            <td>
+                     %if repo['dbrepo']['repo_type'] =='hg':
+                       <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
+                     %elif repo['dbrepo']['repo_type'] =='git':
+                       <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
+                     %else:
+                       
+                     %endif 		            
+		             %if repo['dbrepo']['private']:
+		                <img class="icon" alt="${_('private')}" src="${h.url("/images/icons/lock.png")}"/>
+		             %else:
+		                <img class="icon" alt="${_('public')}" src="${h.url("/images/icons/lock_open.png")}"/>
+		             %endif
+		                                             
+		            ${h.link_to(repo['name'], h.url('summary_home',repo_name=repo['name']),class_="repo_name")}
+		            %if repo['dbrepo_fork']:
+		            	<a href="${h.url('summary_home',repo_name=repo['dbrepo_fork']['repo_name'])}">
+		            	<img class="icon" alt="${_('public')}"
+		            	title="${_('Fork of')} ${repo['dbrepo_fork']['repo_name']}" 
+		            	src="${h.url('/images/icons/arrow_divide.png')}"/></a>
+		            %endif		            
+		            </td> 
+		            <td><span class="tooltip" title="${repo['last_change']}">${("r%s:%s") % (repo['rev'],h.short_id(repo['tip']))}</span></td>
+		            <td><a href="${h.url('repo_settings_home',repo_name=repo['name'])}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url('/images/icons/application_form_edit.png')}"/></a></td>
+		            <td>
+	                  ${h.form(url('repo_settings_delete', repo_name=repo['name']),method='delete')}
+	                    ${h.submit('remove_%s' % repo['name'],'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
+	                  ${h.end_form()}	            
+		            </td>
+		        </tr>
+		     %endfor
+	     %else:
+	     	${_('No repositories yet')} 
+	     	%if h.HasPermissionAny('hg.admin','hg.create.repository')():
+	     		${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
+	     	%endif
+	     %endif
+	     </tbody>
+	     </table>
+    </div>
+    
+</div>
+    <script type="text/javascript">
+     var D = YAHOO.util.Dom;
+     var E = YAHOO.util.Event;
+     var S = YAHOO.util.Selector;
+     
+     var q_filter = D.get('q_filter');
+     var F = YAHOO.namespace('q_filter'); 
+     
+     E.on(q_filter,'click',function(){
+        q_filter.value = '';
+     });
+
+     F.filterTimeout = null;
+     
+     F.updateFilter  = function() { 
+        // Reset timeout 
+        F.filterTimeout = null;
+        
+        var obsolete = [];
+        var nodes = S.query('div.table tr td a.repo_name');
+        var req = q_filter.value.toLowerCase();
+        for (n in nodes){
+            D.setStyle(nodes[n].parentNode.parentNode,'display','')
+        }
+        if (req){
+            for (n in nodes){
+                if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
+                    obsolete.push(nodes[n]); 
+                }
+            }
+            if(obsolete){
+                for (n in obsolete){
+                    D.setStyle(obsolete[n].parentNode.parentNode,'display','none');
+                }
+            }
+        }
+     }
+     
+     E.on(q_filter,'keyup',function(e){
+         clearTimeout(F.filterTimeout); 
+         F.filterTimeout = setTimeout(F.updateFilter,600); 
+     });
+     
+    </script>
+</%def>  
+nt_update'),method='put')}
+	    <div class="form">
+	    
+             <div class="field">
+                <div class="gravatar_box">
+                    <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
+                    <p>
                     <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/> 
                     ${_('Using')} ${c.user.email}
                     </p>
--- a/rhodecode/templates/admin/users/users.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/admin/users/users.html	Fri Oct 07 01:08:50 2011 +0200
@@ -20,7 +20,7 @@
         ${self.breadcrumbs()}
         <ul class="links">
           <li>
-            <span>${h.link_to(u'ADD NEW USER',h.url('new_user'))}</span>
+            <span>${h.link_to(_(u'ADD NEW USER'),h.url('new_user'))}</span>
           </li>
           
         </ul>        
@@ -33,6 +33,7 @@
             <th class="left">${_('username')}</th>
             <th class="left">${_('name')}</th>
             <th class="left">${_('lastname')}</th>
+            <th class="left">${_('last login')}</th>
             <th class="left">${_('active')}</th>
             <th class="left">${_('admin')}</th>
             <th class="left">${_('ldap')}</th>
@@ -45,13 +46,14 @@
                     <td>${h.link_to(user.username,h.url('edit_user', id=user.user_id))}</td>
                     <td>${user.name}</td>
                     <td>${user.lastname}</td>
+                    <td>${user.last_login}</td>
                     <td>${h.bool2icon(user.active)}</td>
                     <td>${h.bool2icon(user.admin)}</td>
-                    <td>${h.bool2icon(user.is_ldap)}</td>
+                    <td>${h.bool2icon(bool(user.ldap_dn))}</td>
                     <td>
-                        ${h.form(url('user', id=user.user_id),method='delete')}
-                            ${h.submit('remove_','delete',id="remove_user_%s" % user.user_id,
-                            class_="delete_icon action_button",onclick="return confirm('Confirm to delete this user');")}
+                        ${h.form(url('delete_user', id=user.user_id),method='delete')}
+                            ${h.submit('remove_',_('delete'),id="remove_user_%s" % user.user_id,
+                            class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this user')+"');")}
                         ${h.end_form()}
                     </td>
                 </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/users_groups/users_group_add.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,55 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Add users group')} - ${c.rhodecode_name}
+</%def>
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} 
+    &raquo; 
+    ${h.link_to(_('Users groups'),h.url('users_groups'))} 
+    &raquo;
+    ${_('add new users group')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}       
+    </div>
+    <!-- end box / title -->
+    ${h.form(url('users_groups'))}
+    <div class="form">
+        <!-- fields -->
+        <div class="fields">
+             <div class="field">
+                <div class="label">
+                    <label for="users_group_name">${_('Group name')}:</label>
+                </div>
+                <div class="input">
+                    ${h.text('users_group_name',class_='small')}
+                </div>
+             </div>
+            
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label for="users_group_active">${_('Active')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('users_group_active',value=True)}
+                </div>
+             </div>
+            
+            <div class="buttons">
+              ${h.submit('save',_('save'),class_="ui-button")}
+            </div>             
+        </div>
+    </div>
+    ${h.end_form()}
+</div>    
+</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/users_groups/users_group_edit.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,270 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Edit users group')} ${c.users_group.users_group_name} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} 
+    &raquo; 
+    ${h.link_to(_('UsersGroups'),h.url('users_groups'))} 
+    &raquo;
+    ${_('edit')} "${c.users_group.users_group_name}"
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+<div class="box box-left">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}       
+    </div>
+    <!-- end box / title -->
+    ${h.form(url('users_group', id=c.users_group.users_group_id),method='put', id='edit_users_group')}
+    <div class="form">
+        <!-- fields -->
+	        <div class="fields">
+	             <div class="field">
+	                <div class="label">
+	                    <label for="users_group_name">${_('Group name')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('users_group_name',class_='small')}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label label-checkbox">
+	                    <label for="users_group_active">${_('Active')}:</label>
+	                </div>
+	                <div class="checkboxes">
+	                    ${h.checkbox('users_group_active',value=True)}
+	                </div>
+	             </div>
+	            <div class="field">
+                    <div class="label">
+                        <label for="users_group_active">${_('Members')}:</label>
+                    </div>
+                    <div class="select">
+	                    <table> 
+	                            <tr>
+	                                <td>
+	                                    <div>
+	                                        <div style="float:left">
+	                                            <div class="text" style="padding: 0px 0px 6px;">${_('Choosen group members')}</div>
+	                                            ${h.select('users_group_members',[x[0] for x in c.group_members],c.group_members,multiple=True,size=8,style="min-width:210px")}
+	                                           <div  id="remove_all_elements" style="cursor:pointer;text-align:center">
+	                                               ${_('Remove all elements')}
+	                                               <img alt="remove" style="vertical-align:text-bottom" src="${h.url("/images/icons/arrow_right.png")}"/>
+	                                           </div>
+	                                        </div>
+	                                        <div style="float:left;width:20px;padding-top:50px">
+	                                            <img alt="add" id="add_element" 
+	                                                style="padding:2px;cursor:pointer" 
+	                                                src="${h.url("/images/icons/arrow_left.png")}"/>
+	                                            <br />
+	                                            <img alt="remove" id="remove_element" 
+	                                                style="padding:2px;cursor:pointer" 
+	                                                src="${h.url("/images/icons/arrow_right.png")}"/>
+	                                        </div>
+	                                        <div style="float:left">
+	                                             <div class="text" style="padding: 0px 0px 6px;">${_('Available members')}</div>
+	                                             ${h.select('available_members',[],c.available_members,multiple=True,size=8,style="min-width:210px")}
+	                                             <div id="add_all_elements" style="cursor:pointer;text-align:center">
+	                                                   <img alt="add" style="vertical-align:text-bottom" src="${h.url("/images/icons/arrow_left.png")}"/>
+	                                                    ${_('Add all elements')}
+	                                             </div>	                                        
+	                                        </div>
+	                                    </div>
+	                                </td>           
+	                            </tr>       
+	                    </table>                    
+                    </div>	            
+
+                </div>			        
+                <div class="buttons">
+                  ${h.submit('save',_('save'),class_="ui-button")}
+                </div>             
+            </div>          
+    </div>        
+${h.end_form()}        
+</div>
+    
+<script type="text/javascript">
+    YAHOO.util.Event.onDOMReady(function(){
+            var D = YAHOO.util.Dom;
+            var E = YAHOO.util.Event;
+            
+            //definition of containers ID's
+            var available_container = 'available_members';
+            var selected_container = 'users_group_members';
+            
+            //form containing containers id
+            var form_id = 'edit_users_group';
+            
+            //temp container for selected storage.
+            var cache = new Array();
+            var av_cache = new Array();
+            var c =  D.get(selected_container);
+            var ac = D.get(available_container);
+            
+            //get only selected options for further fullfilment
+            for(var i = 0;node =c.options[i];i++){
+                if(node.selected){
+                    //push selected to my temp storage left overs :)
+                    cache.push(node);
+                }
+            }
+            
+            //clear 'selected' select
+            //c.options.length = 0;
+
+            //fill it with remembered options
+            //for(var i = 0;node = cache[i];i++){
+            //   c.options[i]=new Option(node.text, node.value, false, false);
+            //}
+            
+           
+            //get all available options to cache
+            for(var i = 0;node =ac.options[i];i++){
+                    //push selected to my temp storage left overs :)
+                    av_cache.push(node);
+            }            
+            
+            //fill available only with those not in choosen
+            ac.options.length=0;
+            tmp_cache = new Array();
+            
+            for(var i = 0;node = av_cache[i];i++){
+            	var add = true;
+	            for(var i2 = 0;node_2 = cache[i2];i2++){
+	                if(node.value == node_2.value){
+	                	add=false;
+	                	break;
+	                }
+	            }
+	            if(add){
+	            	tmp_cache.push(new Option(node.text, node.value, false, false));
+	            }
+            }            
+            
+            for(var i = 0;node = tmp_cache[i];i++){
+                ac.options[i] = node;
+            }
+            
+            function prompts_action_callback(e){
+                
+                var choosen = D.get(selected_container);  
+                var available = D.get(available_container);
+                
+                //get checked and unchecked options from field
+                function get_checked(from_field){
+                    //temp container for storage.
+                    var sel_cache = new Array();
+                    var oth_cache = new Array();
+                    
+                    for(var i = 0;node = from_field.options[i];i++){
+                        if(node.selected){
+                            //push selected fields :)
+                            sel_cache.push(node);
+                        }
+                        else{
+                        	oth_cache.push(node)
+                        }
+                    }                    
+                    
+                    return [sel_cache,oth_cache]
+                }
+                
+                //fill the field with given options
+                function fill_with(field,options){
+                	//clear firtst
+                	field.options.length=0;
+                    for(var i = 0;node = options[i];i++){
+                            field.options[i]=new Option(node.text, node.value, 
+                                    false, false);
+                    }
+                	
+                }
+                //adds to current field
+                function add_to(field,options){
+                    for(var i = 0;node = options[i];i++){
+                            field.appendChild(new Option(node.text, node.value, 
+                                    false, false));
+                    }
+                }
+                
+                // add action
+                if (this.id=='add_element'){
+                    var c = get_checked(available);
+                    add_to(choosen,c[0]);
+                    fill_with(available,c[1]);
+                }
+                // remove action
+                if (this.id=='remove_element'){
+                    var c = get_checked(choosen);
+                    add_to(available,c[0]);
+                    fill_with(choosen,c[1]);             
+                }                   
+                // add all elements
+                if(this.id=='add_all_elements'){
+                    for(var i=0; node = available.options[i];i++){
+                            choosen.appendChild(new Option(node.text, 
+                                    node.value, false, false));
+                    }
+                    available.options.length = 0;
+                }
+                //remove all elements
+                if(this.id=='remove_all_elements'){
+                    for(var i=0; node = choosen.options[i];i++){
+                        available.appendChild(new Option(node.text, 
+                                node.value, false, false));
+                    }
+                    choosen.options.length = 0;                	
+                }
+                
+            }
+            
+    
+            E.addListener(['add_element','remove_element',
+                           'add_all_elements','remove_all_elements'],'click',
+                           prompts_action_callback)
+
+            E.addListener(form_id,'submit',function(){
+                var choosen = D.get(selected_container);
+                for (var i = 0; i < choosen.options.length; i++) {
+                    choosen.options[i].selected = 'selected';
+                }
+            })  
+        });
+</script>    
+<div class="box box-right">
+    <!-- box / title -->
+    <div class="title">
+        <h5>${_('Permissions')}</h5>       
+    </div>
+    ${h.form(url('users_group_perm', id=c.users_group.users_group_id), method='put')}
+    <div class="form">
+        <!-- fields -->
+        <div class="fields">
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label for="">${_('Create repositories')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('create_repo_perm',value=True)}
+                </div>
+             </div>
+            <div class="buttons">
+              ${h.submit('save',_('Save'),class_="ui-button")}
+              ${h.reset('reset',_('Reset'),class_="ui-button")}
+            </div>             
+        </div>    
+    </div>
+    ${h.end_form()}    
+</div>
+</%def>  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/admin/users_groups/users_groups.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,53 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('Users groups administration')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Users groups')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('admin')}
+</%def>
+
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+        <ul class="links">
+          <li>
+            <span>${h.link_to(_(u'ADD NEW USER GROUP'),h.url('new_users_group'))}</span>
+          </li>
+          
+        </ul>        
+    </div>
+    <!-- end box / title -->
+    <div class="table">
+        <table class="table_disp">
+        <tr class="header">
+            <th class="left">${_('group name')}</th>
+            <th class="left">${_('members')}</th>
+            <th class="left">${_('active')}</th>
+            <th class="left">${_('action')}</th>
+        </tr>
+            %for cnt,u_group in enumerate(c.users_groups_list):
+                <tr class="parity${cnt%2}">
+                    <td>${h.link_to(u_group.users_group_name,h.url('edit_users_group', id=u_group.users_group_id))}</td>
+                    <td><span class="tooltip" title="${', '.join([x.user.username for x in u_group.members[:50]])}">${len(u_group.members)}</span></td>
+                    <td>${h.bool2icon(u_group.users_group_active)}</td>
+                    <td>
+                        ${h.form(url('users_group', id=u_group.users_group_id),method='delete')}
+                            ${h.submit('remove_','delete',id="remove_group_%s" % u_group.users_group_id,
+                            class_="delete_icon action_button",onclick="return confirm('Confirm to delete this users group');")}
+                        ${h.end_form()}
+                    </td>
+                </tr>
+            %endfor
+        </table>
+    </div>
+</div>
+</%def>
--- a/rhodecode/templates/base/base.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/base/base.html	Fri Oct 07 01:08:50 2011 +0200
@@ -1,113 +1,132 @@
 ## -*- coding: utf-8 -*-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>${next.title()}</title>
-    <link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
-    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-    <meta name="robots" content="index, nofollow"/>
-    <!-- stylesheets -->
-    ${self.css()}
-    <!-- scripts -->
-    ${self.js()}
-</head>
-<body>
-    <!-- header -->
-    <div id="header">
-        <!-- user -->
-        <ul id="logged-user">
-	            <li class="first">
-	                <div class="gravatar">
-	                    <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,20)}" />
-	                </div>
-		            <div class="account">
-		            %if c.rhodecode_user.username == 'default':
-                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')(): 
-                            ${h.link_to('anonymous',h.url('register'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
-                        %else:
-                            ${h.link_to('anonymous',h.url('#'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
-                        %endif		            
-                        
-                    %else:                        		            
-		            	${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
-		            %endif
-		            </div>	
-	            </li>
-	            <li>
-	               <a href="${h.url('home')}">${_('Home')}</a>
-	            </li>
-	            %if c.rhodecode_user.username != 'default':
-                <li>
-                   <a href="${h.url('journal')}">${_('Journal')}</a> 
-                   ##(${c.unread_journal})</a>
-                </li>
-                %endif
-                %if c.rhodecode_user.username == 'default':
-                    <li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
-                %else:
-                    <li class="last highlight">${h.link_to(u'Log Out',h.url('logout_home'))}</li>
-                %endif
+<%inherit file="root.html"/>
+
+<!-- HEADER -->
+<div id="header">
+    <!-- user -->
+    <ul id="logged-user">
+         <li class="first">
+			<div id="quick_login" style="display:none">
+			${h.form(h.url('login_home',came_from=h.url.current()))}
+			<div class="form">
+			    <div class="fields">
+			        <div class="field">
+			            <div class="label">
+			                <label for="username">${_('Username')}:</label>
+			            </div>
+			            <div class="input">
+			                ${h.text('username',class_='focus',size=40)}
+			            </div>
+			            
+			        </div>                     
+			        <div class="field">
+			            <div class="label">
+			                <label for="password">${_('Password')}:</label>
+			            </div>
+			            <div class="input">
+			                ${h.password('password',class_='focus',size=40)}
+			            </div>
+			            
+			        </div>
+			        <div class="buttons">
+			            <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
+                        <div class="register">
+                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
+                         ${h.link_to(_("Don't have an account ?"),h.url('register'))}
+                        %endif                        
+                        </div>
+                            ${h.submit('sign_in',_('Sign In'),class_="ui-button")}
+			        </div>
+			    </div>
+			</div>
+			${h.end_form()}
+			</div>         
+         
+             <div class="gravatar">
+                 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,20)}" />
+             </div>
+          <div class="account">
+          %if c.rhodecode_user.username == 'default':
+              <a href="${h.url('public_journal')}">${_('Public journal')}</a>   
+          %else:                        		            
+          	${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
+          %endif
+          </div>	
+         </li>
+         <li>
+            <a href="${h.url('home')}">${_('Home')}</a>
+         </li>
+         %if c.rhodecode_user.username != 'default':
+            <li>
+               <a href="${h.url('journal')}">${_('Journal')}</a> 
+               ##(${c.unread_journal}
+            </li>
+            %endif
+            %if c.rhodecode_user.username == 'default':
+                <li class="last highlight">${h.link_to(_(u'Login'),h.url('login_home'),id='quick_login_link')}</li>
+            %else:
+                <li class="last highlight">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
+            %endif
+    </ul>
+    <!-- end user -->
+    <div id="header-inner" class="title">
+        <div id="logo">
+            <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
+        </div>
+        <!-- MENU -->
+        ${self.page_nav()}
+        <!-- END MENU -->
+        ${self.body()}
+    </div>
+</div>     
+<!-- END HEADER -->
+    
+<!-- CONTENT -->
+<div id="content"> 
+    <div class="flash_msg">
+        <% messages = h.flash.pop_messages() %>
+        % if messages:
+        <ul id="flash-messages">
+            % for message in messages:
+            <li class="${message.category}_msg">${message}</li>
+            % endfor
         </ul>
-        <!-- end user -->
-        <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
-            <!-- logo -->
-            <div id="logo">
-                <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
-            </div>
-            <!-- end logo -->
-            <!-- menu -->
-            ${self.page_nav()}
-            <!-- quick -->
-        </div>
-    </div>     
-    <!-- end header -->
-    
-	<!-- CONTENT -->
-	<div id="content"> 
-        <div class="flash_msg">
-            <% messages = h.flash.pop_messages() %>
-            % if messages:
-            <ul id="flash-messages">
-                % for message in messages:
-                <li class="${message.category}_msg">${message}</li>
-                % endfor
-            </ul>
-            % endif
-        </div>	    
-	    <div id="main"> 
-	        ${next.main()}
-	    </div>
-	</div> 
-    <!-- END CONTENT -->
+        % endif
+    </div>	    
+    <div id="main"> 
+        ${next.main()}
+    </div>
+</div> 
+<!-- END CONTENT -->
 
-	<!-- footer -->
-	<div id="footer">
-	   <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
-	       <div>
-	           <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
-		       <p class="footer-link-right">
-			       <a href="${h.url('rhodecode_official')}">RhodeCode</a> 
-       	           ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski		       
-		       </p>
-	       </div>
-	   </div>
-        <script type="text/javascript">
-        function tooltip_activate(){
-        ${h.tooltip.activate()}
-        }
-        tooltip_activate();
-        </script>
-	</div>
-	<!-- end footer -->
-</body>
+<!-- FOOTER -->
+<div id="footer">
+   <div id="footer-inner" class="title">
+       <div>
+           <p class="footer-link">
+                <a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
+           </p>
+	       <p class="footer-link-right">
+	           <a href="${h.url('rhodecode_official')}">RhodeCode</a> 
+	           ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski
+	       </p>
+       </div>
+   </div>
+</div>
+<!-- END FOOTER -->
 
-</html>
+### MAKO DEFS ###
+<%def name="page_nav()">
+    ${self.menu()}
+</%def>
 
-### MAKO DEFS ### 
-<%def name="page_nav()">
-	${self.menu()}
+<%def name="breadcrumbs()">
+    <div class="breadcrumbs">
+    ${self.breadcrumbs_links()}
+    </div>
 </%def>
 
+
 <%def name="menu(current=None)">
 		<% 
 		def is_current(selected):
@@ -121,26 +140,75 @@
 				<li>
 					<a id="repo_switcher" title="${_('Switch repository')}" href="#">
                     <span class="icon">
-                        <img src="${h.url("/images/icons/database.png")}" alt="${_('Products')}" />
+                        <img src="${h.url('/images/icons/database.png')}" alt="${_('Products')}" />
                     </span>
                     <span>&darr;</span>					
 					</a>
-					<ul class="repo_switcher">
-                        %for repo in c.cached_repo_list:
-                        
-                          %if repo['repo'].dbrepo.private:
-                             <li><img src="${h.url("/images/icons/lock.png")}" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
-                          %else:
-                             <li><img src="${h.url("/images/icons/lock_open.png")}" alt="${_('Public repository')}" class="repo_switcher_type" />${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
-                          %endif  
-                        %endfor					
-					</ul>			
+					<ul id="repo_switcher_list" class="repo_switcher">
+                        <li>
+                            <a href="#">${_('loading...')}</a>
+                        </li>
+					</ul>
+					<script type="text/javascript">
+					   YUE.on('repo_switcher','mouseover',function(){
+						      function qfilter(){
+						         var S = YAHOO.util.Selector;
+						         
+						         var q_filter = YUD.get('q_filter_rs');
+						         var F = YAHOO.namespace('q_filter_rs'); 
+						         
+						         YUE.on(q_filter,'click',function(){
+						            q_filter.value = '';
+						         });
+						    
+						         F.filterTimeout = null;
+						         
+						         F.updateFilter  = function() { 
+						            // Reset timeout 
+						            F.filterTimeout = null;
+						            
+						            var obsolete = [];
+						            var nodes = S.query('ul#repo_switcher_list li a.repo_name');
+						            var req = YUD.get('q_filter_rs').value;
+						            for (n in nodes){
+						                YUD.setStyle(nodes[n].parentNode,'display','')
+						            }
+						            if (req){
+						                for (n in nodes){
+						                    if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
+						                        obsolete.push(nodes[n]); 
+						                    }
+						                }
+						                if(obsolete){
+						                    for (n in obsolete){
+						                        YUD.setStyle(obsolete[n].parentNode,'display','none');
+						                    }
+						                }
+						            }
+						         }
+						         
+						         YUE.on(q_filter,'keyup',function(e){
+						             clearTimeout(F.filterTimeout); 
+						             F.filterTimeout = setTimeout(F.updateFilter,600); 
+						         });
+						}
+						   var loaded = YUD.hasClass('repo_switcher','loaded');
+						   if(!loaded){
+							   YUD.addClass('repo_switcher','loaded');
+							   ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
+								   function(o){qfilter();},
+								   function(o){YUD.removeClass('repo_switcher','loaded');}
+								   ,null);
+						   }
+						   return false;
+					   });
+					</script>	
 				</li>
 				
 	            <li ${is_current('summary')}>
 	               <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
 	               <span class="icon">
-	                   <img src="${h.url("/images/icons/clipboard_16.png")}" alt="${_('Summary')}" />
+	                   <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
 	               </span>
 	               <span>${_('Summary')}</span>                 
 	               </a>	            
@@ -148,7 +216,7 @@
                 ##<li ${is_current('shortlog')}>
                 ##   <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
                 ##   <span class="icon">
-                ##       <img src="${h.url("/images/icons/application_view_list.png")}" alt="${_('Shortlog')}" />
+                ##       <img src="${h.url('/images/icons/application_view_list.png')}" alt="${_('Shortlog')}" />
                 ##   </span>
                 ##   <span>${_('Shortlog')}</span>                 
                 ##   </a>             
@@ -156,7 +224,7 @@
                 <li ${is_current('changelog')}>
                    <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
                    <span class="icon">
-                       <img src="${h.url("/images/icons/time.png")}" alt="${_('Changelog')}" />
+                       <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
                    </span>
                    <span>${_('Changelog')}</span>                 
                    </a>             
@@ -165,16 +233,16 @@
                 <li ${is_current('switch_to')}>
                    <a title="${_('Switch to')}" href="#">
                    <span class="icon">
-                       <img src="${h.url("/images/icons/arrow_switch.png")}" alt="${_('Switch to')}" />
+                       <img src="${h.url('/images/icons/arrow_switch.png')}" alt="${_('Switch to')}" />
                    </span>
                    <span>${_('Switch to')}</span>                 
                    </a>    
                     <ul>
                         <li>
-                            ${h.link_to('%s (%s)' % (_('branches'),len(c.repository_branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
+                            ${h.link_to('%s (%s)' % (_('branches'),len(c.rhodecode_repo.branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
                             <ul>
-                            %if c.repository_branches.values():
-						        %for cnt,branch in enumerate(c.repository_branches.items()):
+                            %if c.rhodecode_repo.branches.values():
+						        %for cnt,branch in enumerate(c.rhodecode_repo.branches.items()):
 						            <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
 						        %endfor
 						    %else:
@@ -183,10 +251,10 @@
                             </ul>                        
                         </li>
                         <li>
-                            ${h.link_to('%s (%s)' % (_('tags'),len(c.repository_tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
+                            ${h.link_to('%s (%s)' % (_('tags'),len(c.rhodecode_repo.tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
                             <ul>
-                            %if c.repository_tags.values():
-                                %for cnt,tag in enumerate(c.repository_tags.items()):
+                            %if c.rhodecode_repo.tags.values():
+                                %for cnt,tag in enumerate(c.rhodecode_repo.tags.items()):
                                  <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
                                 %endfor
                             %else:
@@ -199,7 +267,7 @@
                 <li ${is_current('files')}>
                    <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
                    <span class="icon">
-                       <img src="${h.url("/images/icons/file.png")}" alt="${_('Files')}" />
+                       <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
                    </span>
                    <span>${_('Files')}</span>                 
                    </a>             
@@ -208,7 +276,7 @@
                 <li ${is_current('options')}>
                    <a title="${_('Options')}" href="#">
                    <span class="icon">
-                       <img src="${h.url("/images/icons/table_gear.png")}" alt="${_('Admin')}" />
+                       <img src="${h.url('/images/icons/table_gear.png')}" alt="${_('Admin')}" />
                    </span>
                    <span>${_('Options')}</span>                 
                    </a>
@@ -223,14 +291,16 @@
                    	<li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
                    	<li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
                     
-                    %if h.HasPermissionAll('hg.admin')('access admin main page'):
-                    <li>
+                    % if h.HasPermissionAll('hg.admin')('access admin main page'):
+                     <li>
                        ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}  
                         <%def name="admin_menu()">
                         <ul>
                             <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
                             <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
+                            <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
                             <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
+                            <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
                             <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
                             <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
                             <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>        
@@ -238,31 +308,28 @@
                         </%def>
                         
                         ${admin_menu()}
-                    </li>
-                    %endif
-
+                     </li>
+                    % endif
                    </ul>             
                 </li>
                 
                 <li>
-                    <a title="${_('Followers')}" href="#">
+                    <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
                     <span class="icon_short">
-                        <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
+                        <img src="${h.url('/images/icons/heart.png')}" alt="${_('Followers')}" />
                     </span>
-                    <span class="short">${c.repository_followers}</span>
+                    <span id="current_followers_count" class="short">${c.repository_followers}</span>
                     </a>
                 </li>
                 <li>
-                    <a title="${_('Forks')}" href="#">
+                    <a title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
                     <span class="icon_short">
-                        <img src="${h.url("/images/icons/arrow_divide.png")}" alt="${_('Forks')}" />
+                        <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Forks')}" />
                     </span>
                     <span class="short">${c.repository_forks}</span>
                     </a>
                 </li>                
                 
-                
-                
 	        </ul>
 		%else:
 		    ##ROOT MENU
@@ -270,25 +337,25 @@
                 <li>
                     <a title="${_('Home')}"  href="${h.url('home')}">
                     <span class="icon">
-                        <img src="${h.url("/images/icons/home_16.png")}" alt="${_('Home')}" />
+                        <img src="${h.url('/images/icons/home_16.png')}" alt="${_('Home')}" />
                     </span>
                     <span>${_('Home')}</span>                 
                     </a>        
                 </li>
-                %if c.rhodecode_user.username != 'default':
-                <li>
+                % if c.rhodecode_user.username != 'default':
+                 <li>
                     <a title="${_('Journal')}"  href="${h.url('journal')}">
                     <span class="icon">
-                        <img src="${h.url("/images/icons/book.png")}" alt="${_('Journal')}" />
+                        <img src="${h.url('/images/icons/book.png')}" alt="${_('Journal')}" />
                     </span>
                     <span>${_('Journal')}</span>                 
                     </a>        
-                </li>
-                %endif          
+                 </li>
+                % endif
                 <li>
                     <a title="${_('Search')}"  href="${h.url('search')}">
                     <span class="icon">
-                        <img src="${h.url("/images/icons/search_16.png")}" alt="${_('Search')}" />
+                        <img src="${h.url('/images/icons/search_16.png')}" alt="${_('Search')}" />
                     </span>
                     <span>${_('Search')}</span>                 
                     </a>        
@@ -298,7 +365,7 @@
                 <li ${is_current('admin')}>
                    <a title="${_('Admin')}" href="${h.url('admin_home')}">
                    <span class="icon">
-                       <img src="${h.url("/images/icons/cog_edit.png")}" alt="${_('Admin')}" />
+                       <img src="${h.url('/images/icons/cog_edit.png')}" alt="${_('Admin')}" />
                    </span>
                    <span>${_('Admin')}</span>                 
                    </a>
@@ -308,70 +375,3 @@
 			</ul>
 		%endif    
 </%def>
-
-
-<%def name="css()">
-<link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
-<link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css')}"  />
-<link rel="stylesheet" type="text/css" href="${h.url('/css/diff.css')}"  />
-</%def>
-
-<%def name="js()">
-##<script type="text/javascript" src="${h.url('/js/yui/utilities/utilities.js')}"></script>
-##<script type="text/javascript" src="${h.url('/js/yui/container/container.js')}"></script>
-##<script type="text/javascript" src="${h.url('/js/yui/datasource/datasource.js')}"></script>
-##<script type="text/javascript" src="${h.url('/js/yui/autocomplete/autocomplete.js')}"></script>
-##<script type="text/javascript" src="${h.url('/js/yui/selector/selector-min.js')}"></script>
-
-<script type="text/javascript" src="${h.url('/js/yui2a.js')}"></script>
-<!--[if IE]><script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script><![endif]-->
-<script type="text/javascript" src="${h.url('/js/yui.flot.js')}"></script>
-
-<script type="text/javascript">
-var base_url  = "${h.url('toggle_following')}";
-var YUC = YAHOO.util.Connect;
-var YUD = YAHOO.util.Dom;
-var YUE = YAHOO.util.Event;
-
-function onSuccess(target){
-	
-	var f = YUD.get(target.id);
-    if(f.getAttribute('class')=='follow'){
-        f.setAttribute('class','following');
-        f.setAttribute('title',"${_('Stop following this repository')}");
-    }
-    else{
-        f.setAttribute('class','follow');
-        f.setAttribute('title',"${_('Start following this repository')}");
-    }
-}
-
-function toggleFollowingUser(fallows_user_id,token){
-    args = 'follows_user_id='+fallows_user_id;
-    args+= '&amp;auth_token='+token;
-    YUC.asyncRequest('POST',base_url,{
-        success:function(o){
-        	onSuccess();
-        }
-    },args); return false;
-}
-
-function toggleFollowingRepo(target,fallows_repo_id,token){
-
-    args = 'follows_repo_id='+fallows_repo_id;
-    args+= '&amp;auth_token='+token;
-    YUC.asyncRequest('POST',base_url,{
-        success:function(o){
-        	onSuccess(target);
-        }
-    },args); return false;
-}    
-</script>
-
-</%def>
-
-<%def name="breadcrumbs()">
-    <div class="breadcrumbs">
-    ${self.breadcrumbs_links()}
-    </div>
-</%def>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/base/root.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,144 @@
+## -*- coding: utf-8 -*-
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>${self.title()}</title>
+        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+        <meta name="robots" content="index, nofollow"/>
+        <link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
+
+        ## CSS ###
+        <%def name="css()">
+            <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen"/>
+            <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css')}"/>
+            <link rel="stylesheet" type="text/css" href="${h.url('/css/diff.css')}"/>
+            ## EXTRA FOR CSS
+            ${self.css_extra()}
+        </%def>
+        <%def name="css_extra()">
+        </%def>
+                    
+        ${self.css()}
+        
+        %if c.ga_code:
+        <!-- Analytics -->
+	     <script type="text/javascript">
+	      var _gaq = _gaq || [];
+	      _gaq.push(['_setAccount', '${c.ga_code}']);
+	      _gaq.push(['_trackPageview']);
+	    
+	      (function() {
+	        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+	        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+	        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+	      })();
+	     </script>
+	    %endif
+        
+        ## JAVASCRIPT ##
+        <%def name="js()">
+            <script type="text/javascript" src="${h.url('/js/yui.2.9.js')}"></script>
+            <!--[if IE]>
+               <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
+            <![endif]-->
+            <script type="text/javascript" src="${h.url('/js/yui.flot.js')}"></script>
+            <script type="text/javascript" src="${h.url('/js/rhodecode.js')}"></script>
+           ## EXTRA FOR JS
+           ${self.js_extra()}
+        
+            <script type="text/javascript">
+            var base_url  = "${h.url('toggle_following')}";
+            function onSuccess(target){
+                var f = YUD.get(target.id);
+                var f_cnt = YUD.get('current_followers_count');
+                
+                if(f.getAttribute('class')=='follow'){
+                    f.setAttribute('class','following');
+                    f.setAttribute('title',"${_('Stop following this repository')}");
+                    
+                    if(f_cnt){
+                        var cnt = Number(f_cnt.innerHTML)+1;
+                        f_cnt.innerHTML = cnt;
+                    }
+                }
+                else{
+                    f.setAttribute('class','follow');
+                    f.setAttribute('title',"${_('Start following this repository')}");
+                    if(f_cnt){
+                        var cnt = Number(f_cnt.innerHTML)+1;
+                        f_cnt.innerHTML = cnt;
+                    }      
+                }
+            }
+            
+            function toggleFollowingUser(target,fallows_user_id,token,user_id){
+                args = 'follows_user_id='+fallows_user_id;
+                args+= '&amp;auth_token='+token;
+                if(user_id != undefined){
+                    args+="&amp;user_id="+user_id;
+                }
+                YUC.asyncRequest('POST',base_url,{
+                    success:function(o){
+                        onSuccess(target);
+                    }
+                },args);
+                return false;
+            }
+            
+            function toggleFollowingRepo(target,fallows_repo_id,token,user_id){
+            
+                args = 'follows_repo_id='+fallows_repo_id;
+                args+= '&amp;auth_token='+token;
+                if(user_id != undefined){
+                    args+="&amp;user_id="+user_id;
+                }    
+                YUC.asyncRequest('POST',base_url,{
+                    success:function(o){
+                        onSuccess(target);
+                    }
+                },args); 
+                return false;
+            }
+           YUE.onDOMReady(function(){
+               
+             YUE.on('quick_login_link','click',function(e){
+                 
+                 if(YUD.hasClass('quick_login_link','enabled')){
+                     YUD.setStyle('quick_login','display','none');
+                     YUD.removeClass('quick_login_link','enabled');
+                 }
+                 else{
+                     YUD.setStyle('quick_login','display','');
+                     YUD.addClass('quick_login_link','enabled');
+                     YUD.get('username').focus();
+                 }
+                 //make sure we don't redirect 
+                 YUE.preventDefault(e);
+             });
+               
+            tooltip_activate();
+            show_more_event();
+            
+            YUE.on(YUQ('.quick_repo_menu'),'click',function(e){
+            	var menu = e.currentTarget.firstElementChild;
+            	if(YUD.hasClass(menu,'hidden')){
+            		YUD.addClass(e.currentTarget,'active');
+            		YUD.removeClass(menu,'hidden');
+            	}else{
+            		YUD.removeClass(e.currentTarget,'active');
+            		YUD.addClass(menu,'hidden');
+            	}
+            })
+            
+           })   
+            </script>
+        
+        </%def>
+        <%def name="js_extra()">
+        </%def>      
+        ${self.js()}
+    </head>
+    <body id="body">
+        ${next.body()}
+    </body>
+</html>
\ No newline at end of file
--- a/rhodecode/templates/branches/branches_data.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/branches/branches_data.html	Fri Oct 07 01:08:50 2011 +0200
@@ -9,8 +9,7 @@
         </tr>
 		%for cnt,branch in enumerate(c.repo_branches.items()):
 		<tr class="parity${cnt%2}">
-            <td><span class="tooltip" title="${h.age(branch[1].date)}">
-                      ${branch[1].date}</span>
+            <td><span class="tooltip" title="${h.age(branch[1].date)}">${branch[1].date}</span>
             </td>
             <td>
                 <span class="logtags">
@@ -27,8 +26,28 @@
 			</td>
 		</tr>	
 		%endfor
+        % if hasattr(c,'repo_closed_branches') and c.repo_closed_branches:
+          %for cnt,branch in enumerate(c.repo_closed_branches.items()):
+          <tr class="parity${cnt%2}">
+              <td><span class="tooltip" title="${h.age(branch[1].date)}">${branch[1].date}</span>
+              </td>
+              <td>
+                  <span class="logtags">
+                      <span class="branchtag">${h.link_to(branch[0]+' [closed]',
+                      h.url('changeset_home',repo_name=c.repo_name,revision=branch[1].raw_id))}</span>
+                  </span>         
+              </td>       
+              <td title="${branch[1].author}">${h.person(branch[1].author)}</td>
+              <td>r${branch[1].revision}:${h.short_id(branch[1].raw_id)}</td>
+              <td class="nowrap">
+              ${h.link_to(_('changeset'),h.url('changeset_home',repo_name=c.repo_name,revision=branch[1].raw_id))}
+              |
+              ${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name,revision=branch[1].raw_id))}
+              </td>
+          </tr>   
+          %endfor
+        %endif  
     </table>
 %else:
-	${_('There are no branches yet')}
-%endif
-
+    ${_('There are no branches yet')}
+%endif
\ No newline at end of file
--- a/rhodecode/templates/changelog/changelog.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/changelog/changelog.html	Fri Oct 07 01:08:50 2011 +0200
@@ -34,36 +34,37 @@
 					<div class="container_header">
 				        ${h.form(h.url.current(),method='get')}
 				        <div class="info_box">
-				          <span>${_('Show')}:</span>
+				          ${h.submit('set',_('Show'),class_="ui-button-small")}
 				          ${h.text('size',size=1,value=c.size)}
-				          <span>${_('revisions')}</span>
-				          ${h.submit('set',_('set'))}
-				          
+				          <span class="rev">${_('revisions')}</span>
 				        </div>
 				        ${h.end_form()}
+					<div id="rev_range_container" style="display:none"></div>
 					</div>
+					
 				%for cnt,cs in enumerate(c.pagination):
 					<div id="chg_${cnt+1}" class="container">
 						<div class="left">
-							<div class="date">${_('commit')} ${cs.revision}: ${h.short_id(cs.raw_id)}@${cs.date}</div>
+							<div class="date">
+							${h.checkbox(cs.short_id,class_="changeset_range")}
+							<span>${_('commit')} ${cs.revision}: ${h.short_id(cs.raw_id)}@${cs.date}</span>
+							</div>
 							<div class="author">
 								<div class="gravatar">
-									<img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),20)}"/>
+									<img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),16)}"/>
 								</div>
-								<span>${h.person(cs.author)}</span><br/>
-								<span><a href="mailto:${h.email_or_none(cs.author)}">${h.email_or_none(cs.author)}</a></span><br/>
+								<div title="${h.email_or_none(cs.author)}" class="user">${h.person(cs.author)}</div>
+								##<span><a href="mailto:${h.email_or_none(cs.author)}">${h.email_or_none(cs.author)}</a></span><br/>
 							</div>
 							<div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
 						</div>	
 						<div class="right">
-									<div class="changes">
-										<span class="removed tooltip" title="${_('removed')}${h.literal(h.changed_tooltip(cs.removed))}">${len(cs.removed)}</span>
-										<span class="changed tooltip" title="${_('changed')}${h.literal(h.changed_tooltip(cs.changed))}">${len(cs.changed)}</span>
-										<span class="added tooltip" title="${_('added')}${h.literal(h.changed_tooltip(cs.added))}">${len(cs.added)}</span>
+									<div id="${cs.raw_id}_changes_info" class="changes">
+                                        <span id="${cs.raw_id}" class="changed_total tooltip" title="${_('Affected number of files, click to show more details')}">${len(cs.affected_files)}</span>
 									</div>					
 										%if len(cs.parents)>1:
 										<div class="merge">
-											${_('merge')}<img alt="merge" src="${h.url("/images/icons/arrow_join.png")}"/>
+											${_('merge')}<img alt="merge" src="${h.url('/images/icons/arrow_join.png')}"/>
 										</div>
 										%endif
 								   %if cs.parents:							
@@ -99,19 +100,72 @@
 			<script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
 			<script type="text/javascript">
 				YAHOO.util.Event.onDOMReady(function(){
-					function set_canvas() {
+					
+                    //Monitor range checkboxes and build a link to changesets
+                    //ranges 
+                    var checkboxes = YUD.getElementsByClassName('changeset_range');
+                    var url_tmpl = "${h.url('changeset_home',repo_name=c.repo_name,revision='__REVRANGE__')}";
+                    YUE.on(checkboxes,'click',function(e){      
+                        var checked_checkboxes = [];
+                        for (pos in checkboxes){
+                            if(checkboxes[pos].checked){
+                                checked_checkboxes.push(checkboxes[pos]);
+                            }
+                        }
+                        if(checked_checkboxes.length>1){
+                        	var rev_end = checked_checkboxes[0].name;
+                        	var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
+                        	
+                            var url = url_tmpl.replace('__REVRANGE__',
+                            		rev_start+'...'+rev_end);
+                            
+                        var link = "<a href="+url+">${_('Show selected changes __S -> __E')}</a>"
+                        link = link.replace('__S',rev_start);
+                        link = link.replace('__E',rev_end);
+                        YUD.get('rev_range_container').innerHTML = link;
+                        YUD.setStyle('rev_range_container','display','');
+                        }
+                        else{
+                        	YUD.setStyle('rev_range_container','display','none');
+                        	
+                        }
+                    });					
+					
+                    //Fetch changeset details 
+                    YUE.on(YUD.getElementsByClassName('changed_total'),'click',function(e){
+                    	var id = e.currentTarget.id
+                    	var url = "${h.url('changelog_details',repo_name=c.repo_name,cs='__CS__')}"
+                    	var url = url.replace('__CS__',id);
+                    	ypjax(url,id+'_changes_info',function(){tooltip_activate()});
+                    });
+                    
+                    
+					function set_canvas(heads) {
 						var c = document.getElementById('graph_nodes');
 						var t = document.getElementById('graph_content');
 						canvas = document.getElementById('graph_canvas');
 						var div_h = t.clientHeight;
 						c.style.height=div_h+'px';
 						canvas.setAttribute('height',div_h);
-						canvas.setAttribute('width',160);
+						c.style.height=max_w+'px';
+						canvas.setAttribute('width',max_w);
 					};
-					set_canvas();
+					var heads = 1;
+					var max_heads = 0;
 					var jsdata = ${c.jsdata|n};
+					
+					for( var i=0;i<jsdata.length;i++){
+					    var m = Math.max.apply(Math, jsdata[i][1]);
+					    if (m>max_heads){
+					        max_heads = m;
+					    }
+					}
+					var max_w = Math.max(100,max_heads*25);
+					set_canvas(max_w);
+					
 					var r = new BranchRenderer();
-					r.render(jsdata); 
+					r.render(jsdata,max_w);
+					
 				});
 			</script>
 		%else:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/changelog/changelog_details.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,9 @@
+% if len(c.cs.affected_files) <= c.affected_files_cut_off:                     
+<span class="removed tooltip" title="<b>${_('removed')}</b>${h.changed_tooltip(c.cs.removed)}">${len(c.cs.removed)}</span>
+<span class="changed tooltip" title="<b>${_('changed')}</b>${h.changed_tooltip(c.cs.changed)}">${len(c.cs.changed)}</span>
+<span class="added tooltip" title="<b>${_('added')}</b>${h.changed_tooltip(c.cs.added)}">${len(c.cs.added)}</span>
+% else:
+ <span class="removed tooltip" title="${_('affected %s files') % len(c.cs.affected_files)}">!</span>
+ <span class="changed tooltip" title="${_('affected %s files') % len(c.cs.affected_files)}">!</span>
+ <span class="added tooltip"   title="${_('affected %s files') % len(c.cs.affected_files)}">!</span>                                         
+% endif
\ No newline at end of file
--- a/rhodecode/templates/changeset/changeset.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/changeset/changeset.html	Fri Oct 07 01:08:50 2011 +0200
@@ -25,7 +25,7 @@
         ${self.breadcrumbs()}
     </div>
     <div class="table">
-		<div id="body" class="diffblock">
+		<div class="diffblock">
 			<div class="code-header">
 				<div>
 				${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
@@ -51,9 +51,15 @@
 	             </div>
 	             <div class="right">
 		             <div class="changes">
+                        % if len(c.changeset.affected_files) <= c.affected_files_cut_off:	             
 		                 <span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span>
 		                 <span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span>
 		                 <span class="added" title="${_('added')}">${len(c.changeset.added)}</span>
+	                    % else:
+                         <span class="removed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
+                         <span class="changed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
+                         <span class="added"   title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>	                    
+	                    % endif		                 
 		             </div>                  
 		                 %if len(c.changeset.parents)>1:
 		                 <div class="merge">
@@ -80,21 +86,30 @@
 		         </span>                                                                 
 	                </div>              
 	        </div>
-	        <span style="font-size:1.1em;font-weight: bold">${_('Files affected')}</span>
+	        <span style="font-size:1.1em;font-weight: bold">
+	        ${_('%s files affected with %s additions and %s deletions.') % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}
+	        </span>
 	        <div class="cs_files">
-	                %for change,filenode,diff,cs1,cs2 in c.changes:
-	                    <div class="cs_${change}">${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.repo_name_slug('CHANGE-%s' % h.safe_unicode(filenode.path))))}</div>
+	                %for change,filenode,diff,cs1,cs2,stat in c.changes:
+	                    <div class="cs_${change}">
+		                    <div class="node">${h.link_to(h.safe_unicode(filenode.path),
+		                                        h.url.current(anchor=h.repo_name_slug('C%s' % h.safe_unicode(filenode.path))))}</div>
+		                    <div class="changes">${h.fancy_file_stats(stat)}</div>
+	                    </div>
 	                %endfor
+	                % if c.cut_off:
+	                  ${_('Changeset was too big and was cut off...')}
+	                % endif
 	        </div>         
 	    </div>
 	    
     </div>
     	
-	%for change,filenode,diff,cs1,cs2 in c.changes:
+	%for change,filenode,diff,cs1,cs2,stat in c.changes:
 		%if change !='removed':
 		<div style="clear:both;height:10px"></div>
-		<div id="body" class="diffblock">
-			<div id="${h.repo_name_slug('CHANGE-%s' % h.safe_unicode(filenode.path))}" class="code-header">
+		<div class="diffblock">
+			<div id="${h.repo_name_slug('C%s' % h.safe_unicode(filenode.path))}" class="code-header">
 				<div class="changeset_header">
 					<span class="changeset_file">
 						${h.link_to_if(change!='removed',h.safe_unicode(filenode.path),h.url('files_home',repo_name=c.repo_name,
@@ -120,7 +135,5 @@
 		</div>
 		%endif
 	%endfor 
-    </div>
-</div>    
-	
-</%def>
\ No newline at end of file
+    </div>	
+</%def>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/changeset/changeset_range.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,97 @@
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${c.repo_name} ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo;
+    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    &raquo;
+    ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('changelog')}     
+</%def>
+
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+    </div>
+    <div class="table">
+		<div id="body" class="diffblock">
+			<div class="code-header">
+				<div>
+				${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)}
+				<h3>${_('Compare View')}</h3>
+				 ##&raquo; <span>${h.link_to(_('raw diff'),
+				##h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
+				 ##&raquo; <span>${h.link_to(_('download diff'),
+				##h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
+				</div>
+			</div>
+		</div>
+	    <div id="changeset_compare_view_content">
+			<div class="container">
+			<table class="compare_view_commits">
+            %for cs in c.cs_ranges:
+                <tr>
+                <td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),14)}"/></div></td>
+                <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td>
+                <td><div class="author">${h.person(cs.author)}</div></td>
+                <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
+                <td><div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div></td>
+                </tr>
+            %endfor
+            </table>
+	        </div>
+	        <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
+	        <div class="cs_files">
+	               %for cs in c.cs_ranges:
+	                   <div class="cur_cs">r${cs}</div>
+	                %for change,filenode,diff,cs1,cs2,st in c.changes[cs.raw_id]:
+	                    <div class="cs_${change}">${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.repo_name_slug('C%s-%s' % (cs.short_id,h.safe_unicode(filenode.path)))))}</div>
+	                %endfor
+	               %endfor 
+	        </div>         
+	    </div>
+	    
+    </div>
+   %for cs in c.cs_ranges:    	
+	%for change,filenode,diff,cs1,cs2,st in c.changes[cs.raw_id]:
+		%if change !='removed':
+		<div style="clear:both;height:10px"></div>
+		<div class="diffblock">
+			<div id="${h.repo_name_slug('C%s-%s' % (cs.short_id,h.safe_unicode(filenode.path)))}" class="code-header">
+				<div class="changeset_header">
+					<span class="changeset_file">
+						${h.link_to_if(change!='removed',h.safe_unicode(filenode.path),h.url('files_home',repo_name=c.repo_name,
+						revision=filenode.changeset.raw_id,f_path=h.safe_unicode(filenode.path)))}
+					</span>
+					%if 1:
+					&raquo; <span>${h.link_to(_('diff'),
+					h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff'))}</span>
+					&raquo; <span>${h.link_to(_('raw diff'),
+					h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw'))}</span>
+					&raquo; <span>${h.link_to(_('download diff'),
+					h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download'))}</span>
+					%endif
+				</div>
+			</div>
+			<div class="code-body">        
+					%if diff:
+						${diff|n}
+					%else:
+						${_('No changes in this file')}
+					%endif
+			</div>
+		</div>
+		%endif
+	%endfor
+   %endfor  
+    </div>
+</%def>
\ No newline at end of file
--- a/rhodecode/templates/changeset/raw_changeset.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/changeset/raw_changeset.html	Fri Oct 07 01:08:50 2011 +0200
@@ -1,8 +1,8 @@
-# ${c.scm_type} changeset patch
+# ${c.scm_type.upper()} changeset patch
 # User ${c.changeset.author|n}
 # Date ${c.changeset.date}
 # Node ID ${c.changeset.raw_id}
-# ${c.parent_tmpl}
+${c.parent_tmpl}
 ${c.changeset.message}
 
 ${c.diffs|n}
\ No newline at end of file
--- a/rhodecode/templates/errors/error_404.html	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-## -*- coding: utf-8 -*-
-<%inherit file="./../base/base.html"/>
-            
-<%def name="title()">
-    ${_('Repository not found')}
-</%def>
-
-<%def name="breadcrumbs()">
-	${h.link_to(u'Home',h.url('home'))}
-	 / 
-	${h.link_to(u'Admin',h.url('admin_home'))}
-</%def>
-
-<%def name="page_nav()">
-	${self.menu('admin')}
-</%def>
-<%def name="js()">
-
-</%def>
-<%def name="main()">
-
-    <h2 class="no-link no-border">${_('Not Found')}</h2>
-    <p class="normal">${_('The specified repository "%s" is unknown, sorry.') % c.repo_name}</p>
-    <p class="normal">
-    <a href="${h.url('new_repo',repo=c.repo_name_cleaned)}">
-    ${_('Create "%s" repository as %s' % (c.repo_name,c.repo_name_cleaned))}</a>
-
-    </p>
-    <p class="normal">${h.link_to(_('Go back to the main repository list page'),h.url('home'))}</p>
-    <div class="page-footer">
-    </div>
-</%def>
\ No newline at end of file
--- a/rhodecode/templates/errors/error_document.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/errors/error_document.html	Fri Oct 07 01:08:50 2011 +0200
@@ -7,7 +7,7 @@
 	    %if c.redirect_time:
 	        <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
 	    %endif        
-		<link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
+        <link rel="icon" href="${h.url("/images/hgicon.png")}" type="image/png" />
         <meta name="robots" content="index, nofollow"/>
             
         <!-- stylesheets -->
--- a/rhodecode/templates/files/file_diff.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/files/file_diff.html	Fri Oct 07 01:08:50 2011 +0200
@@ -38,6 +38,9 @@
 			<div class="code-body">
 		 			%if c.no_changes:
 		            	${_('No changes')}
+		            %elif c.big_diff:
+		                ${_('Diff is to big to display')} ${h.link_to(_('raw diff'),
+                           h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))}
 		            %else:        
 						${c.cur_diff|n}
 		            %endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/files/files_add.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,111 @@
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${c.repo_name} ${_('Edit file')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="js_extra()">
+<script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
+</%def>
+<%def name="css_extra()">
+<link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo;
+    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    &raquo;
+    ${_('add file')} @ R${c.cs.revision}:${h.short_id(c.cs.raw_id)}
+</%def>
+
+<%def name="page_nav()">
+		${self.menu('files')}     
+</%def>
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+        <ul class="links">
+            <li>
+              <span style="text-transform: uppercase;">
+              <a href="#">${_('branch')}: ${c.cs.branch}</a></span>
+            </li>          
+        </ul>          
+    </div>
+    <div class="table">
+		<div id="files_data">
+		  ${h.form(h.url.current(),method='post',id='eform',enctype="multipart/form-data")}
+            <h3>${_('Add new file')}</h3>
+            <div class="form">
+                    <div class="fields">
+                         <div class="field">
+                            <div class="label">
+                                <label for="location">${_('Location')}</label>
+                            </div>
+                            <div class="input">
+                                <input type="text" value="${c.f_path}" size="30" name="location" id="location">
+                                ${_('use / to separate directories')}
+                            </div>
+                         </div>
+                                      
+                        <div id="filename_container" class="field file">
+                            <div class="label">
+                                <label for="filename">${_('File Name')}:</label>
+                            </div>
+                            <div class="input">
+                                <input type="text" value="" size="30" name="filename" id="filename">
+                                <input type="button" class="ui-button-small" value="upload file" id="upload_file_enable">
+                            </div>
+                        </div>
+                        <div id="upload_file_container" class="field" style="display:none">
+                          <div class="label">
+                              <label for="location">${_('Upload file')}</label>
+                          </div>
+                          <div class="file">
+                              <input type="file"  size="30" name="upload_file" id="upload_file">
+                              <input type="button" class="ui-button-small" value="create file" id="file_enable">                        
+                          </div>
+                        </div>                                                                      
+                    </div>
+            </div>            
+			<div id="body" class="codeblock">
+			    <div id="editor_container">    
+                    <pre id="editor_pre"></pre>
+				    <textarea id="editor" name="content" style="display:none"></textarea>
+                </div>
+				<div style="padding: 10px;color:#666666">${_('commit message')}</div>
+				<textarea id="commit" name="message" style="height: 100px;width: 99%;margin-left:4px"></textarea>
+			</div>
+			<div style="text-align: right;padding-top: 5px">
+			<input id="reset" type="button" value="${_('Reset')}" class="ui-button-small" />
+			${h.submit('commit',_('Commit changes'),class_="ui-button-small-blue")}
+			</div>
+			${h.end_form()}
+			<script type="text/javascript">
+			 var myCodeMirror = CodeMirror.fromTextArea(YUD.get('editor'),{
+	                mode:  "null",
+	                lineNumbers:true
+	              });
+			 YUE.on('reset','click',function(e){
+				 window.location="${h.url('files_home',repo_name=c.repo_name,revision=c.cs.revision,f_path=c.f_path)}";
+			 });
+             
+			 YUE.on('file_enable','click',function(){
+                 YUD.setStyle('editor_container','display','');
+                 YUD.setStyle('upload_file_container','display','none');
+                 YUD.setStyle('filename_container','display','');
+             });
+             
+			 YUE.on('upload_file_enable','click',function(){
+				 YUD.setStyle('editor_container','display','none');
+				 YUD.setStyle('upload_file_container','display','');
+				 YUD.setStyle('filename_container','display','none');
+			 });
+			 
+			</script>
+		</div>    
+    </div>
+</div>    
+</%def>   
\ No newline at end of file
--- a/rhodecode/templates/files/files_annotate.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/files/files_annotate.html	Fri Oct 07 01:08:50 2011 +0200
@@ -44,6 +44,12 @@
 						h.url('files_raw_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
 					/ ${h.link_to(_('download as raw'),
 						h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
+                    % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
+                     % if not c.file.is_binary:                   
+                    / ${h.link_to(_('edit'),
+                        h.url('files_edit_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))}
+                     % endif 
+                    % endif						
 				</dd>
 			    <dt>${_('History')}</dt>
 			    <dd>
@@ -51,8 +57,8 @@
 			        ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
 			        ${h.hidden('diff2',c.file.last_changeset.raw_id)}
 			        ${h.select('diff1',c.file.last_changeset.raw_id,c.file_history)}
-			        ${h.submit('diff','diff to revision',class_="ui-button")}
-			        ${h.submit('show_rev','show at revision',class_="ui-button")}
+			        ${h.submit('diff','diff to revision',class_="ui-button-small")}
+			        ${h.submit('show_rev','show at revision',class_="ui-button-small")}
 			        ${h.end_form()}
 			        </div>
 			    </dd>					
@@ -64,28 +70,67 @@
 				</div>
 				<div class="code-body">
 			       %if c.file.is_binary:
-			           ${_('Binary file')}
+			           ${_('Binary file (%s)') % c.file.mimetype}
 			       %else:				
 					% if c.file.size < c.cut_off_limit:
-						${h.pygmentize_annotation(c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
+						${h.pygmentize_annotation(c.repo_name,c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
 					%else:
-						${_('File is to big to display')} ${h.link_to(_('show as raw'),
+						${_('File is too big to display')} ${h.link_to(_('show as raw'),
 						h.url('files_raw_home',repo_name=c.repo_name,revision=c.cs.revision,f_path=c.f_path))}
 					%endif
-		            <script type="text/javascript">
-		            YAHOO.util.Event.onDOMReady(function(){
-		                YAHOO.util.Event.addListener('show_rev','click',function(e){
-		                    YAHOO.util.Event.preventDefault(e);
-		                    var cs = YAHOO.util.Dom.get('diff1').value;
-		                    var url = "${h.url('files_annotate_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
-		                    window.location = url;
-		                    });
-		               });
-		            </script>				
+			       <script type="text/javascript">
+			           function highlight_lines(lines){
+			               for(pos in lines){
+			                 YUD.setStyle('L'+lines[pos],'background-color','#FFFFBE');                       
+			               }
+			           }       
+			           page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
+			           if (page_highlights.length == 2){
+			              highlight_ranges  = page_highlights[1].split(",");
+			
+			              var h_lines = [];
+			              for (pos in highlight_ranges){
+			                   var _range = highlight_ranges[pos].split('-');
+			                   if(_range.length == 2){
+			                       var start = parseInt(_range[0]);
+			                       var end = parseInt(_range[1]);
+			                       if (start < end){
+			                           for(var i=start;i<=end;i++){
+			                               h_lines.push(i);
+			                           }
+			                       } 
+			                   }
+			                   else{
+			                       h_lines.push(parseInt(highlight_ranges[pos]));
+			                   }
+			             }
+			           highlight_lines(h_lines);
+			           
+			           //remember original location 
+			           var old_hash  = location.href.substring(location.href.indexOf('#'));
+			           
+			           // this makes a jump to anchor moved by 3 posstions for padding 
+			           window.location.hash = '#L'+Math.max(parseInt(h_lines[0])-3,1);
+			           
+			           //sets old anchor 
+			           window.location.hash = old_hash;
+			           
+			           }
+			       </script>					
 				   %endif				
 				</div>
 			</div>
+            <script type="text/javascript">
+            YAHOO.util.Event.onDOMReady(function(){
+                YUE.on('show_rev','click',function(e){
+                    YAHOO.util.Event.preventDefault(e);
+                    var cs = YAHOO.util.Dom.get('diff1').value;
+                    var url = "${h.url('files_annotate_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
+                    window.location = url;
+                    });
+               });
+            </script>			
 		</div>    
     </div>
 </div>    
-</%def>   
\ No newline at end of file
+</%def>   
--- a/rhodecode/templates/files/files_browser.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/files/files_browser.html	Fri Oct 07 01:08:50 2011 +0200
@@ -6,20 +6,154 @@
 	%endif
 </%def>
 <div id="body" class="browserblock">
-	<div class="browser-header">
-		${h.form(h.url.current())}
-		<div class="info_box">
-          <span >${_('view')}@rev</span> 
-          <a href="${c.url_prev}" title="${_('previous revision')}">&laquo;</a>
-          ${h.text('at_rev',value=c.changeset.revision,size=3)}
-          <a href="${c.url_next}" title="${_('next revision')}">&raquo;</a>
-          ${h.submit('view','view')}
-	    </div>           
-		${h.end_form()}
-	</div>
-	<div class="browser-branch">
-	</div>
-	<div style="clear:both"></div>
+    <div class="browser-header">
+		<div class="browser-nav">
+			${h.form(h.url.current())}
+			<div class="info_box">
+	          <span class="rev">${_('view')}@rev</span> 
+	          <a class="rev" href="${c.url_prev}" title="${_('previous revision')}">&laquo;</a>
+	          ${h.text('at_rev',value=c.changeset.revision,size=5)}
+	          <a class="rev" href="${c.url_next}" title="${_('next revision')}">&raquo;</a>
+	          ## ${h.submit('view',_('view'),class_="ui-button-small")}
+		    </div>           
+			${h.end_form()}
+		</div>
+	    <div class="browser-branch">
+	       ${h.checkbox('stay_at_branch',c.changeset.branch,c.changeset.branch==c.branch)}
+	       <label>${_('follow current branch')}</label>
+	    </div>
+        <div class="browser-search">
+              <div id="search_activate_id" class="search_activate">
+                  <a id="filter_activate" href="#">${_('search file list')}</a>
+              </div>
+              % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):            
+                    <div  id="add_node_id" class="add_node">
+                        <a href="${h.url('files_add_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path)}">${_('add new file')}</a>
+                    </div>
+              % endif               
+        <div>
+            <div id="node_filter_box_loading" style="display:none">${_('Loading file list...')}</div>
+            <div id="node_filter_box" style="display:none">
+            ${h.files_breadcrumbs(c.repo_name,c.changeset.raw_id,c.files_list.path)}/<input type="text" value="type to search..." name="filter" size="25" id="node_filter" autocomplete="off">
+            
+            <script type="text/javascript">
+            
+            YUE.on('stay_at_branch','click',function(e){
+                if(e.target.checked){
+                    var uri = "${h.url.current(branch='__BRANCH__')}"
+                    uri = uri.replace('__BRANCH__',e.target.value);
+                    window.location = uri;
+                }
+                else{
+                    window.location = "${h.url.current()}";
+                }
+                
+            })            
+            
+            var n_filter = YUD.get('node_filter');
+            var F = YAHOO.namespace('node_filter');
+            
+            var url = '${h.url("files_nodelist_home",repo_name="__REPO__",revision="__REVISION__",f_path="__FPATH__")}';
+            var node_url = '${h.url("files_home",repo_name="__REPO__",revision="__REVISION__",f_path="__FPATH__")}';
+            
+            url  = url.replace('__REPO__','${c.repo_name}');
+            url  = url.replace('__REVISION__','${c.changeset.raw_id}');
+            url  = url.replace('__FPATH__','${c.files_list.path}');
+
+            node_url  = node_url.replace('__REPO__','${c.repo_name}');
+            node_url  = node_url.replace('__REVISION__','${c.changeset.raw_id}');
+            
+            
+            F.filterTimeout = null;
+            var nodes = null;
+            
+            
+            F.initFilter = function(){
+              YUD.setStyle('node_filter_box_loading','display','');
+              YUD.setStyle('search_activate_id','display','none');
+              YUD.setStyle('add_node_id','display','none');
+              YUC.initHeader('X-PARTIAL-XHR',true);
+              YUC.asyncRequest('GET',url,{
+                  success:function(o){
+                  	nodes = JSON.parse(o.responseText);
+                  	YUD.setStyle('node_filter_box_loading','display','none');
+                  	YUD.setStyle('node_filter_box','display','');
+                  },
+                  failure:function(o){
+                      console.log('failed to load');
+                  }
+              },null);            
+            }
+            
+            F.updateFilter  = function(e) {
+            	
+            	return function(){
+                    // Reset timeout 
+                    F.filterTimeout = null;
+                    var query = e.target.value;
+                    var match = [];
+                    var matches = 0;
+                    var matches_max = 20;
+                    if (query != ""){
+                        for(var i=0;i<nodes.length;i++){
+                            var pos = nodes[i].toLowerCase().indexOf(query)
+                            if(query && pos != -1){
+                                
+                                matches++
+                                //show only certain amount to not kill browser 
+                                if (matches > matches_max){
+                                    break;
+                                }
+                                
+                                var n = nodes[i];
+                                var n_hl = n.substring(0,pos)
+                                  +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
+                                  +n.substring(pos+query.length)                    
+                                match.push('<tr><td><a class="browser-file" href="{0}">{1}</a></td><td colspan="5"></td></tr>'.format(node_url.replace('__FPATH__',n),n_hl));
+                            }
+                            if(match.length >= matches_max){
+                                match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format("${_('search truncated')}"));
+                            }
+                            
+                        }                    	
+                    }
+                    
+                    if(query != ""){
+                        YUD.setStyle('tbody','display','none');
+                        YUD.setStyle('tbody_filtered','display','');
+                        
+                        if (match.length==0){
+                          match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format("${_('no matching files')}"));
+                        }                        	
+                        
+                    	YUD.get('tbody_filtered').innerHTML = match.join("");	
+                    }
+                    else{
+                    	YUD.setStyle('tbody','display','');
+                    	YUD.setStyle('tbody_filtered','display','none');
+                    }
+                    
+            	}
+            }
+            
+            
+            YUE.on(YUD.get('filter_activate'),'click',function(){
+                F.initFilter();
+            })
+            YUE.on(n_filter,'click',function(){
+                n_filter.value = '';
+             });
+            YUE.on(n_filter,'keyup',function(e){
+                clearTimeout(F.filterTimeout); 
+                F.filterTimeout = setTimeout(F.updateFilter(e),600);
+            });            
+            </script>
+            
+            </div>        
+        </div>
+        </div>      
+    </div>
+    
 	<div class="browser-body">
 		<table class="code-browser">
 		         <thead>
@@ -32,7 +166,8 @@
 		                 <th>${_('Last commiter')}</th>
 		             </tr>
 		         </thead>
-
+                
+                <tbody id="tbody">
           		%if c.files_list.parent:
          		<tr class="parity0">
 	          		<td>		          		
@@ -80,6 +215,9 @@
 		             </td>
 				</tr>
 			%endfor
+                </tbody>
+                <tbody id="tbody_filtered" style="display:none">
+                </tbody>                
 		</table>
 	</div>
 </div>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/files/files_edit.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,64 @@
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${c.repo_name} ${_('Edit file')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="js_extra()">
+<script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
+</%def>
+<%def name="css_extra()">
+<link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo;
+    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    &raquo;
+    ${_('edit file')} @ R${c.cs.revision}:${h.short_id(c.cs.raw_id)}
+</%def>
+
+<%def name="page_nav()">
+		${self.menu('files')}     
+</%def>
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+        <ul class="links">
+            <li>
+              <span style="text-transform: uppercase;">
+              <a href="#">${_('branch')}: ${c.cs.branch}</a></span>
+            </li>          
+        </ul>          
+    </div>
+    <div class="table">
+		<div id="files_data">
+			<h3 class="files_location">${_('Location')}: ${h.files_breadcrumbs(c.repo_name,c.cs.revision,c.file.path)}</h3>
+			${h.form(h.url.current(),method='post',id='eform')}
+			<div id="body" class="codeblock">
+			    <pre id="editor_pre"></pre>
+				<textarea id="editor" name="content" style="display:none">${c.file.content|n}</textarea>
+				<div style="padding: 10px;color:#666666">${_('commit message')}</div>
+				<textarea id="commit" name="message" style="height: 60px;width: 99%;margin-left:4px"></textarea>
+			</div>
+			<div style="text-align: right;padding-top: 5px">
+			<input id="reset" type="button" value="${_('Reset')}" class="ui-button-small" />
+			${h.submit('commit',_('Commit changes'),class_="ui-button-small-blue")}
+			</div>
+			${h.end_form()}
+			<script type="text/javascript">
+			 var myCodeMirror = CodeMirror.fromTextArea(YUD.get('editor'),{
+	                mode:  "null",
+	                lineNumbers:true
+	              });
+			 YUE.on('reset','click',function(){
+				 window.location="${h.url('files_home',repo_name=c.repo_name,revision=c.cs.revision,f_path=c.file.path)}";
+			 })
+			</script>
+		</div>    
+    </div>
+</div>    
+</%def>   
\ No newline at end of file
--- a/rhodecode/templates/files/files_source.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/files/files_source.html	Fri Oct 07 01:08:50 2011 +0200
@@ -15,6 +15,12 @@
 			h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}			
 		 / ${h.link_to(_('download as raw'),
 			h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
+        % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):			
+         % if not c.files_list.is_binary:
+         / ${h.link_to(_('edit'),
+            h.url('files_edit_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
+         % endif
+        % endif			
 	</dd>
 	<dt>${_('History')}</dt>
 	<dd>
@@ -22,8 +28,8 @@
 		${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
 		${h.hidden('diff2',c.files_list.last_changeset.raw_id)}
 		${h.select('diff1',c.files_list.last_changeset.raw_id,c.file_history)}
-		${h.submit('diff','diff to revision',class_="ui-button")}
-		${h.submit('show_rev','show at revision',class_="ui-button")}
+		${h.submit('diff','diff to revision',class_="ui-button-small")}
+		${h.submit('show_rev','show at revision',class_="ui-button-small")}
 		${h.end_form()}
 		</div>
 	</dd>
@@ -37,25 +43,132 @@
 	</div>
 	<div class="code-body">
 	   %if c.files_list.is_binary:
-	       ${_('Binary file')}
+	       ${_('Binary file (%s)') % c.files_list.mimetype}
 	   %else:
 		% if c.files_list.size < c.cut_off_limit:
 			${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
 		%else:
-			${_('File is to big to display')} ${h.link_to(_('show as raw'),
+			${_('File is too big to display')} ${h.link_to(_('show as raw'),
 			h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
 		%endif
-	   %endif
+       <script type="text/javascript">
+           function highlight_lines(lines){
+               for(pos in lines){
+                 YUD.setStyle('L'+lines[pos],'background-color','#FFFFBE');                       
+               }
+           }       
+           page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
+           if (page_highlights.length == 2){
+              highlight_ranges  = page_highlights[1].split(",");
+
+              var h_lines = [];
+              for (pos in highlight_ranges){
+                   var _range = highlight_ranges[pos].split('-');
+                   if(_range.length == 2){
+                       var start = parseInt(_range[0]);
+                       var end = parseInt(_range[1]);
+                       if (start < end){
+                           for(var i=start;i<=end;i++){
+                               h_lines.push(i);
+                           }
+                       } 
+                   }
+                   else{
+                       h_lines.push(parseInt(highlight_ranges[pos]));
+                   }
+             }
+           highlight_lines(h_lines);
+           
+           //remember original location 
+           var old_hash  = location.href.substring(location.href.indexOf('#'));
+           
+           // this makes a jump to anchor moved by 3 posstions for padding 
+           window.location.hash = '#L'+Math.max(parseInt(h_lines[0])-3,1);
+           
+           //sets old anchor 
+           window.location.hash = old_hash;
+           
+           }
+       </script>
+     %endif		
 	</div>
 </div>
 
 <script type="text/javascript">
-YAHOO.util.Event.onDOMReady(function(){
-    YAHOO.util.Event.addListener('show_rev','click',function(e){
-    	YAHOO.util.Event.preventDefault(e);
+YUE.onDOMReady(function(){
+    YUE.on('show_rev','click',function(e){
+    	YUE.preventDefault(e);
         var cs = YAHOO.util.Dom.get('diff1').value;
         var url = "${h.url('files_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
         window.location = url;
-        });
+    });
+    
+    function getIdentNode(n){
+    	//iterate thru nodes untill matched interesting node !
+    	
+    	if (typeof n == 'undefined'){
+    		return -1
+    	}
+    	
+    	if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
+   			return n
+   		}
+    	else{
+    		return getIdentNode(n.parentNode);
+    	}
+    }
+    
+    function getSelectionLink() {
+        //get selection from start/to nodes    	
+        if (typeof window.getSelection != "undefined") {
+        	s = window.getSelection();
+
+           	from = getIdentNode(s.anchorNode);
+           	till = getIdentNode(s.focusNode);
+            
+            f_int = parseInt(from.id.replace('L',''));
+            t_int = parseInt(till.id.replace('L',''));
+            
+            if (f_int > t_int){
+            	//highlight from bottom 
+            	offset = -35;
+            	ranges = [t_int,f_int];
+            	
+            }
+            else{
+            	//highligth from top 
+            	offset = 35;
+            	ranges = [f_int,t_int];
+            }
+            
+            if (ranges[0] != ranges[1]){
+	            if(YUD.get('linktt') == null){
+	                hl_div = document.createElement('div');
+	                hl_div.id = 'linktt';
+	            }
+	            anchor = '#L'+ranges[0]+'-'+ranges[1];
+	            hl_div.innerHTML = '';
+	            l = document.createElement('a');
+	            l.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
+	            l.innerHTML = "${_('Selection link')}"
+	            hl_div.appendChild(l);
+	            
+	            YUD.get('body').appendChild(hl_div);
+	            
+	            xy = YUD.getXY(till.id);
+	            
+	            YUD.addClass('linktt','yui-tt');
+	            YUD.setStyle('linktt','top',xy[1]+offset+'px');
+	            YUD.setStyle('linktt','left',xy[0]+'px');
+	            YUD.setStyle('linktt','visibility','visible');
+            }
+            else{
+            	YUD.setStyle('linktt','visibility','hidden');
+            }
+        }
+   }
+    
+    YUE.on('hlcode','mouseup',getSelectionLink)
+    
    });
-</script>
\ No newline at end of file
+</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/followers/followers.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,32 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${c.repo_name} ${_('Followers')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo; 
+    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    &raquo;
+    ${_('followers')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('followers')}
+</%def>
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+    </div>
+    <!-- end box / title -->
+    <div class="table">
+        <div id="followers">
+            ${c.followers_data}
+        </div>   
+    </div>
+</div>    
+</%def> 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/followers/followers_data.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,28 @@
+## -*- coding: utf-8 -*-
+
+% for f in c.followers_pager:
+    <div>
+        <div class="follower_user">
+            <div class="gravatar">
+                <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
+            </div>
+            <span style="font-size: 20px"> <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname})</span>
+        </div>
+        <div style="clear:both;padding-top: 10px"></div>
+        <div class="follower_date">${_('Started following')} - 
+        <span class="tooltip" title="${f.follows_from}"> ${h.age(f.follows_from)}</span></div>
+        <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>
+    </div>                
+% endfor 
+
+<div class="pagination-wh pagination-left">
+<script type="text/javascript">
+YUE.onDOMReady(function(){
+    YUE.delegate("followers","click",function(e, matchedEl, container){
+        ypjax(e.target.href,"followers",function(){show_more_event();tooltip_activate();});
+        YUE.preventDefault(e);
+    },'.pager_link');
+});
+</script>
+${c.followers_pager.pager('$link_previous ~2~ $link_next')}
+</div>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/forks/forks.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,32 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${c.repo_name} ${_('Forks')} - ${c.rhodecode_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo; 
+    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    &raquo;
+    ${_('forks')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('forks')}
+</%def>
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+    </div>
+    <!-- end box / title -->
+    <div class="table">
+        <div id="forks">
+            ${c.forks_data}
+        </div>   
+    </div>
+</div>    
+</%def> 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/forks/forks_data.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,35 @@
+## -*- coding: utf-8 -*-
+
+% if c.forks_pager:
+	% for f in c.forks_pager:
+	    <div>
+	        <div class="fork_user">
+	            <div class="gravatar">
+	                <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
+	            </div>
+	            <span style="font-size: 20px">
+	             <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname}) / 
+	              ${h.link_to(f.repo_name,h.url('summary_home',repo_name=f.repo_name))}
+	             </span>
+	             <div style="padding:5px 3px 3px 42px;">${f.description}</div>
+	        </div>
+	        <div style="clear:both;padding-top: 10px"></div>
+	        <div class="follower_date">${_('forked')} - 
+	        <span class="tooltip" title="${f.created_on}"> ${h.age(f.created_on)}</span></div>
+	        <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>            
+	    </div>
+	% endfor
+  <div class="pagination-wh pagination-left">
+  <script type="text/javascript">
+  YUE.onDOMReady(function(){
+      YUE.delegate("forks","click",function(e, matchedEl, container){
+          ypjax(e.target.href,"forks",function(){show_more_event();tooltip_activate();});
+          YUE.preventDefault(e);
+      },'.pager_link');
+  });
+  </script>
+  ${c.forks_pager.pager('$link_previous ~2~ $link_next')}
+  </div>  
+% else:
+	${_('There are no forks yet')} 
+% endif
\ No newline at end of file
--- a/rhodecode/templates/index.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/index.html	Fri Oct 07 01:08:50 2011 +0200
@@ -10,159 +10,5 @@
 	${self.menu('home')}
 </%def>
 <%def name="main()">
-	<%def name="get_sort(name)">
-		<%name_slug = name.lower().replace(' ','_') %>
-		
-		%if name_slug == c.sort_slug:
-		  %if c.sort_by.startswith('-'):
-		    <a href="?sort=${name_slug}">${name}&uarr;</a>
-		  %else:
-		    <a href="?sort=-${name_slug}">${name}&darr;</a>
-		  %endif:
-		%else:
-		    <a href="?sort=${name_slug}">${name}</a>
-		%endif
-	</%def>
-	
-    <div class="box">
-	    <!-- box / title -->
-	    <div class="title">
-	        <h5>${_('Dashboard')}
-	        <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
-	        </h5>
-	        %if c.rhodecode_user.username != 'default':
-		        %if h.HasPermissionAny('hg.admin','hg.create.repository')():
-		        <ul class="links">
-		          <li>
-		            <span>${h.link_to(_('ADD NEW REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
-		          </li>          
-		        </ul>  	        
-		        %endif
-		    %endif
-	    </div>
-	    <!-- end box / title -->
-        <div class="table">
-            <table>
-            <thead>
-	            <tr>
-			        <th class="left">${get_sort(_('Name'))}</th>
-			        <th class="left">${get_sort(_('Description'))}</th>
-			        <th class="left">${get_sort(_('Last change'))}</th>
-			        <th class="left">${get_sort(_('Tip'))}</th>
-			        <th class="left">${get_sort(_('Owner'))}</th>
-			        <th class="left">${_('RSS')}</th>
-			        <th class="left">${_('Atom')}</th>
-	            </tr>
-            </thead>
-            <tbody>
-		    %for cnt,repo in enumerate(c.repos_list):
-		        <tr class="parity${cnt%2}">
-		            <td>
-		            <div style="white-space: nowrap">
-		             ## TYPE OF REPO
-		             %if repo['repo'].dbrepo.repo_type =='hg':
-		               <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
-		             %elif repo['repo'].dbrepo.repo_type =='git':
-		               <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
-		             %else:
-		               
-		             %endif 
-		            
-		             ##PRIVATE/PUBLIC
-		             %if repo['repo'].dbrepo.private:
-		                <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
-		             %else:
-		                <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
-		             %endif
-		            
-		            ##NAME   
-		            ${h.link_to(repo['name'],
-		                h.url('summary_home',repo_name=repo['name']),class_="repo_name")}
-		            %if repo['repo'].dbrepo.fork:
-		            	<a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
-		            	<img class="icon" alt="${_('fork')}"
-		            	title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}" 
-		            	src="${h.url("/images/icons/arrow_divide.png")}"/></a>
-		            %endif
-		            </div>
-		            </td>
-		            ##DESCRIPTION
-		            <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
-		               ${h.truncate(repo['description'],60)}</span>
-		            </td>
-		            ##LAST CHANGE
-		            <td>
-		              <span class="tooltip" title="${repo['last_change']}">
-		              ${h.age(repo['last_change'])}</span>
-		            </td>
-		            <td>
-		            	%if repo['rev']>=0:
-		            	${h.link_to('r%s:%s' % (repo['rev'],h.short_id(repo['tip'])),
-		                h.url('changeset_home',repo_name=repo['name'],revision=repo['tip']),
-		                class_="tooltip",
-		                title=h.tooltip(repo['last_msg']))}
-		            	%else:
-		            		${_('No changesets yet')}
-		            	%endif    
-		            </td>
-		            <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
-		            <td>
-		                <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=repo['name'])}"></a>
-		            </td>        
-		            <td>
-		                <a title="${_('Subscribe to %s atom feed')%repo['name']}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'])}"></a>
-		            </td>
-		        </tr>
-		    %endfor
-            </tbody>
-            </table>
-            </div>
-    </div>
-    
-    
-    <script type="text/javascript">
-     var D = YAHOO.util.Dom;
-     var E = YAHOO.util.Event;
-     var S = YAHOO.util.Selector;
-     
-     var q_filter = D.get('q_filter');
-     var F = YAHOO.namespace('q_filter'); 
-     
-     E.on(q_filter,'click',function(){
-    	q_filter.value = '';
-     });
-
-     F.filterTimeout = null;
-     
-     F.updateFilter  = function() { 
-    	// Reset timeout 
-        F.filterTimeout = null;
-    	
-        var obsolete = [];
-        var nodes = S.query('div.table tr td div a.repo_name');
-        var req = D.get('q_filter').value;
-        for (n in nodes){
-            D.setStyle(nodes[n].parentNode.parentNode.parentNode,'display','')
-        }
-        if (req){
-	        for (n in nodes){
-	        	if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
-	        		obsolete.push(nodes[n]); 
-	        	}
-	    	}
-	        if(obsolete){
-		        for (n in obsolete){
-		        	D.setStyle(obsolete[n].parentNode.parentNode.parentNode,'display','none');
-		        }
-	        }
-        }
-     }
-     
-     E.on(q_filter,'keyup',function(e){
-    	 clearTimeout(F.filterTimeout); 
-    	 setTimeout(F.updateFilter,600); 
-     });
-     
-    </script>
-    	
+    	<%include file="index_base.html" args="parent=self"/>
 </%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/index_base.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,226 @@
+<%page args="parent" /> 
+    <div class="box">
+        <!-- box / title -->
+        <div class="title">
+            <h5>
+            <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
+            ${parent.breadcrumbs()} <span id="repo_count"></span> ${_('repositories')} 
+            </h5>
+            %if c.rhodecode_user.username != 'default':
+                %if h.HasPermissionAny('hg.admin','hg.create.repository')():
+                <ul class="links">
+                  <li>
+                    <span>${h.link_to(_('ADD NEW REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
+                  </li>          
+                </ul>           
+                %endif
+            %endif
+        </div>
+        <!-- end box / title -->
+        <div class="table">
+           % if c.groups:
+            <table>
+                <thead>
+                    <tr>
+                        <th class="left"><a href="#">${_('Group name')}</a></th>
+                        <th class="left"><a href="#">${_('Description')}</a></th>
+                        ##<th class="left"><a href="#">${_('Number of repositories')}</a></th>
+                    </tr>
+                </thead>
+                
+                ## REPO GROUPS
+                
+                % for gr in c.groups:
+                  <tr>
+                      <td>
+                          <div style="white-space: nowrap">
+                          <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
+                          ${h.link_to(gr.group_name,url('repos_group',id=gr.group_id))}
+                          </div>
+                      </td>
+                      <td>${gr.group_description}</td>
+                      ##<td><b>${gr.repositories.count()}</b></td>
+                  </tr>
+                % endfor
+                
+            </table>
+            <div style="height: 20px"></div>
+            % endif
+            <div id="welcome" style="display:none;text-align:center">
+                <h1><a href="${h.url('home')}">${c.rhodecode_name} ${c.rhodecode_version}</a></h1>
+            </div>
+            <table id="repos_list">
+            <thead>
+                <tr>
+                    <th class="left"></th>
+                    <th class="left">${_('Name')}</th>
+                    <th class="left">${_('Description')}</th>
+                    <th class="left">${_('Last change')}</th>
+                    <th class="left">${_('Tip')}</th>
+                    <th class="left">${_('Owner')}</th>
+                    <th class="left">${_('RSS')}</th>
+                    <th class="left">${_('Atom')}</th>
+                </tr>
+            </thead>
+            <tbody>
+            %for cnt,repo in enumerate(c.repos_list):
+                <tr class="parity${cnt%2}">
+                    <td class="quick_repo_menu">
+                    <ul class="menu_items hidden">
+                      <li>
+                         <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=repo['name'])}">
+                         <span class="icon">
+                             <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
+                         </span>
+                         <span>${_('Summary')}</span>                 
+                         </a>             
+                      </li>
+                      <li>
+                         <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=repo['name'])}">
+                         <span class="icon">
+                             <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
+                         </span>
+                         <span>${_('Changelog')}</span>                 
+                         </a>             
+                      </li>
+                      <li>
+                         <a title="${_('Files')}" href="${h.url('files_home',repo_name=repo['name'])}">
+                         <span class="icon">
+                             <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
+                         </span>
+                         <span>${_('Files')}</span>                 
+                         </a>             
+                      </li>                                    
+                    </ul>
+                    </td>
+                    <td>
+                    ## TYPE OF REPO
+                    <div style="white-space: nowrap">
+                     %if repo['dbrepo']['repo_type'] =='hg':
+                       <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
+                     %elif repo['dbrepo']['repo_type'] =='git':
+                       <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
+                     %endif 
+                    
+                     ##PRIVATE/PUBLIC
+                     %if repo['dbrepo']['private']:
+                        <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
+                     %else:
+                        <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
+                     %endif
+                    
+                    ##NAME   
+                    ${h.link_to(repo['name'],
+                        h.url('summary_home',repo_name=repo['name']),class_="repo_name")}
+                    %if repo['dbrepo_fork']:
+                        <a href="${h.url('summary_home',repo_name=repo['dbrepo_fork']['repo_name'])}">
+                        <img class="icon" alt="${_('fork')}"
+                        title="${_('Fork of')} ${repo['dbrepo_fork']['repo_name']}" 
+                        src="${h.url('/images/icons/arrow_divide.png')}"/></a>
+                    %endif
+                    </div>
+                    </td>
+                    ##DESCRIPTION
+                    <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
+                       ${h.truncate(repo['description'],60)}</span>
+                    </td>
+                    ##LAST CHANGE
+                    <td>
+                      <span class="tooltip" title="${repo['last_change']}">
+                      ${h.age(repo['last_change'])}</span>
+                    </td>
+                    <td>
+                        %if repo['rev']>=0:
+                        <a title="${h.tooltip('%s\n%s' % (repo['author'],repo['last_msg']))}" class="tooltip" href="${h.url('changeset_home',repo_name=repo['name'],revision=repo['tip'])}">${'r%s:%s' % (repo['rev'],h.short_id(repo['tip']))}</a>
+                        %else:
+                            ${_('No changesets yet')}
+                        %endif    
+                    </td>
+                    <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
+                    <td>
+                      %if c.rhodecode_user.username != 'default':
+                        <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=repo['name'],api_key=c.rhodecode_user.api_key)}"></a>
+                      %else:
+                        <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=repo['name'])}"></a>
+                      %endif:                       
+                    </td>        
+                    <td>
+                      %if c.rhodecode_user.username != 'default':
+                        <a title="${_('Subscribe to %s atom feed')%repo['name']}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'],api_key=c.rhodecode_user.api_key)}"></a>
+                      %else:
+                        <a title="${_('Subscribe to %s atom feed')%repo['name']}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'])}"></a>
+                      %endif:
+                    </td>
+                </tr>
+            %endfor
+            </tbody>
+            </table>
+            </div>
+    </div>
+    
+    
+    <script type="text/javascript">
+     var D = YAHOO.util.Dom;
+     var E = YAHOO.util.Event;
+     var S = YAHOO.util.Selector;
+     
+     var q_filter = D.get('q_filter');
+     var F = YAHOO.namespace('q_filter'); 
+     
+     E.on(q_filter,'click',function(){
+        q_filter.value = '';
+     });
+
+     F.filterTimeout = null;
+     
+     function set_count(count){
+    
+    	 if(count == 0){
+    		 YUD.setStyle('repos_list','display','none');
+    		 YUD.setStyle('welcome','display','');
+    	 }
+    	 else{
+    		 YUD.setStyle('repos_list','display','');
+    		 YUD.setStyle('welcome','display','none');
+    	 }
+    	 YUD.get('repo_count').innerHTML = count;
+    	 
+     }
+     
+     
+     //set initial count for repos
+     var nodes = S.query('div.table tr td div a.repo_name');
+     
+     set_count(nodes.length)
+     F.updateFilter  = function() { 
+        // Reset timeout 
+        F.filterTimeout = null;
+        
+        var obsolete = [];
+        nodes = S.query('div.table tr td div a.repo_name');
+        var req = q_filter.value.toLowerCase();
+        for (n in nodes){
+            D.setStyle(nodes[n].parentNode.parentNode.parentNode,'display','')
+        }
+        if (req){
+            for (n in nodes){
+                if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
+                    obsolete.push(nodes[n]); 
+                }
+            }
+            if(obsolete){
+                for (n in obsolete){
+                    D.setStyle(obsolete[n].parentNode.parentNode.parentNode,'display','none');
+                }
+            }
+        }
+        // set new count into dashboard
+        set_count(nodes.length - obsolete.length)
+     }
+     
+     E.on(q_filter,'keyup',function(e){
+         clearTimeout(F.filterTimeout); 
+         F.filterTimeout = setTimeout(F.updateFilter,600); 
+     });
+     
+    </script>
--- a/rhodecode/templates/journal.html	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-## -*- coding: utf-8 -*-
-<%inherit file="base/base.html"/>
-<%def name="title()">
-    ${_('Journal')} - ${c.rhodecode_name}
-</%def>
-<%def name="breadcrumbs()">
-	${c.rhodecode_name}
-</%def>
-<%def name="page_nav()">
-	${self.menu('home')}
-</%def>
-<%def name="main()">
-	
-    <div class="box box-left">
-	    <!-- box / title -->
-	    <div class="title">
-	        <h5>${_('Journal')}</h5>
-	    </div>
-	    <div>
-	    %if c.journal:
-            %for entry in c.journal:
-            <div style="padding:10px">
-                <div class="gravatar">
-                    <img alt="gravatar" src="${h.gravatar_url(entry.user.email)}"/>
-                </div>
-                <div>${entry.user.name} ${entry.user.lastname}</div>
-                <div style="padding-left: 45px;padding-top:5px;min-height:20px">${h.action_parser(entry)}</div>
-                <div style="float: left; padding-top: 8px;padding-left:18px">
-                ${h.action_parser_icon(entry)}
-                </div>
-                <div style="margin-left: 45px;padding-top: 10px">
-                <span style="font-weight: bold;font-size: 1.1em">
-		        %if entry.repository:
-		          ${h.link_to(entry.repository.repo_name,
-		                      h.url('summary_home',repo_name=entry.repository.repo_name))}
-		        %else:
-		          ${entry.repository_name}
-		        %endif             
-                </span> - <span title="${entry.action_date}">${h.age(entry.action_date)}</span>
-                </div>
-            </div>
-            <div style="clear:both;border-bottom:1px dashed #DDD;padding:3px 3px;margin:0px 10px 0px 10px"></div>
-            %endfor
-        %else:
-            ${_('No entries yet')}
-        %endif   
-	    </div>
-    </div>
-    
-    <div class="box box-right">
-        <!-- box / title -->
-        <div class="title">
-            <h5>${_('Following')}</h5>
-        </div>
-        <div>
-        %if c.following:
-            %for entry in c.following:
-                <div class="currently_following">
-                    %if entry.follows_user_id:
-                      <img title="${_('following user')}" alt="${_('user')}" src="${h.url("/images/icons/user.png")}"/>
-                      ${entry.follows_user.full_contact}
-                    %endif
-                    
-                    %if entry.follows_repo_id:
-                    
-                      %if entry.follows_repository.private:
-                        <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
-                      %else:
-                        <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
-                      %endif
-                      
-                      ${h.link_to(entry.follows_repository.repo_name,h.url('summary_home',
-                        repo_name=entry.follows_repository.repo_name))}
-                      
-                    %endif
-                </div>
-            %endfor
-        %else:
-            ${_('You are not following any users or repositories')}
-        %endif               
-        </div>
-    </div>
-    
-    <script type="text/javascript">
-    YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
-        var el = e.target;
-        YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
-        YUD.setStyle(el.parentNode,'display','none');
-    });    
-    </script>
-    
-</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/journal/journal.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,69 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+<%def name="title()">
+    ${_('Journal')} - ${c.rhodecode_name}
+</%def>
+<%def name="breadcrumbs()">
+	${c.rhodecode_name}
+</%def>
+<%def name="page_nav()">
+	${self.menu('home')}
+</%def>
+<%def name="main()">
+	
+    <div class="box box-left">
+	    <!-- box / title -->
+	    <div class="title">
+	        <h5>${_('Journal')}</h5>
+	    </div>
+		<script type="text/javascript">
+		function show_more_event(){
+		YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
+		    var el = e.target;
+		    YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
+		    YUD.setStyle(el.parentNode,'display','none');
+		});
+		}
+		</script> 	    
+	    <div id="journal">${c.journal_data}</div>
+    </div>
+    
+    <div class="box box-right">
+        <!-- box / title -->
+        <div class="title">
+            <h5>${_('Following')}</h5>
+        </div>
+        <div>
+		%if c.following:
+		    %for entry in c.following:
+		        <div class="currently_following">
+		            %if entry.follows_user_id:
+		              <img title="${_('following user')}" alt="${_('user')}" src="${h.url("/images/icons/user.png")}"/>
+		              ${entry.follows_user.full_contact}
+		            %endif
+		            
+		            %if entry.follows_repo_id:
+		              
+		              <div style="float:left;padding-right:5px">
+                      <span id="follow_toggle_${entry.follows_repository.repo_id}" class="following" title="${_('Stop following this repository')}"
+                            onclick="javascript:toggleFollowingRepo(this,${entry.follows_repository.repo_id},'${str(h.get_token())}')">
+                      </span>		            
+		              </div>
+		              %if entry.follows_repository.private:
+		                <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
+		              %else:
+		                <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
+		              %endif
+		              
+		              ${h.link_to(entry.follows_repository.repo_name,h.url('summary_home',
+		                repo_name=entry.follows_repository.repo_name))}
+		              
+		            %endif
+		        </div>
+		    %endfor
+		%else:
+		    ${_('You are not following any users or repositories')}
+		%endif
+        </div>
+    </div>    
+</%def>    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/journal/journal_data.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,47 @@
+## -*- coding: utf-8 -*-
+
+%if c.journal_day_aggreagate:
+    %for day,items in c.journal_day_aggreagate:
+    <div class="journal_day">${day}</div>
+        % for user,entries in items:
+	        <div class="journal_container">
+	            <div class="gravatar">
+	                <img alt="gravatar" src="${h.gravatar_url(user.email,24)}"/>
+	            </div>
+	            <div class="journal_user">${user.name} ${user.lastname}</div>
+	            <div class="journal_action_container">
+	            % for entry in entries:
+		            <div class="journal_icon"> ${h.action_parser_icon(entry)}</div>
+		            <div class="journal_action">${h.action_parser(entry)[0]}</div>
+		            <div class="journal_repo">
+		                <span class="journal_repo_name">
+		                %if entry.repository is not None:
+		                  ${h.link_to(entry.repository.repo_name,
+		                              h.url('summary_home',repo_name=entry.repository.repo_name))}
+		                %else:
+		                  ${entry.repository_name}
+		                %endif             
+		                </span>
+		            </div>
+		            <div class="journal_action_params">${h.literal(h.action_parser(entry)[1]())}</div>
+		            <div class="date"><span class="tooltip" title="${entry.action_date}">${h.age(entry.action_date)}</span></div>
+	            %endfor
+	            </div>
+	        </div>
+        %endfor
+    %endfor
+    
+<div class="pagination-wh pagination-left">
+<script type="text/javascript">
+YUE.onDOMReady(function(){
+    YUE.delegate("journal","click",function(e, matchedEl, container){
+    	ypjax(e.target.href,"journal",function(){show_more_event();tooltip_activate();});
+        YUE.preventDefault(e);
+    },'.pager_link');
+});
+</script>
+${c.journal_pager.pager('$link_previous ~2~ $link_next')}
+</div>
+%else:
+    ${_('No entries yet')}
+%endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/journal/public_journal.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,41 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+<%def name="title()">
+    ${_('Journal')} - ${c.rhodecode_name}
+</%def>
+<%def name="breadcrumbs()">
+	${c.rhodecode_name}
+</%def>
+<%def name="page_nav()">
+	${self.menu('home')}
+</%def>
+<%def name="main()">
+	
+    <div class="box">
+	    <!-- box / title -->
+	    <div class="title">
+	        <h5>${_('Public Journal')}</h5>
+                <ul class="links">
+                  <li>
+                    <span>${h.link_to(_('RSS'),h.url('public_journal_rss'),class_='rss_icon')}</span>
+                  </li>
+                  <li>
+                    <span>${h.link_to(_('Atom'),h.url('public_journal_atom'),class_='atom_icon')}</span>
+                  </li>                  
+                  
+                </ul>  	        
+	        
+	    </div>
+		<script type="text/javascript">
+		function show_more_event(){
+		YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
+		    var el = e.target;
+		    YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
+		    YUD.setStyle(el.parentNode,'display','none');
+		});
+		}
+		</script> 	    
+	    <div id="journal">${c.journal_data}</div>
+    </div>
+     
+</%def>    
--- a/rhodecode/templates/login.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/login.html	Fri Oct 07 01:08:50 2011 +0200
@@ -1,82 +1,77 @@
 ## -*- coding: utf-8 -*-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>${_('Sign In')} - ${c.rhodecode_name}</title>
-        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-        <link rel="icon" href="${h.url("/images/icons/database_gear.png")}" type="image/png" />
-        <meta name="robots" content="index, nofollow"/>
-            
-        <!-- stylesheets -->
-        <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
+<%inherit file="base/root.html"/>
+
+<%def name="title()">
+    ${_('Sign In')} - ${c.rhodecode_name}
+</%def>
 
-    </head>
-    <body>
-        <div id="login">
-        <div class="flash_msg">
-            <% messages = h.flash.pop_messages() %>
-            % if messages:
-            <ul id="flash-messages">
-                % for message in messages:
-                <li class="${message.category}_msg">${message}</li>
-                % endfor
-            </ul>
-            % endif
-        </div>          
-            <!-- login -->
-            <div class="title top-left-rounded-corner top-right-rounded-corner">
-                <h5>${_('Sign In to')} ${c.rhodecode_name}</h5>
-            </div>
-            <div class="inner">            
-                ${h.form(h.url.current(came_from=c.came_from))}
-                <div class="form">
-                    <!-- fields -->
+<div id="login">
+<div class="flash_msg">
+    <% messages = h.flash.pop_messages() %>
+    % if messages:
+    <ul id="flash-messages">
+        % for message in messages:
+        <li class="${message.category}_msg">${message}</li>
+        % endfor
+    </ul>
+    % endif
+</div>          
+    <!-- login -->
+    <div class="title top-left-rounded-corner top-right-rounded-corner">
+        <h5>${_('Sign In to')} ${c.rhodecode_name}</h5>
+    </div>
+    <div class="inner">            
+        ${h.form(h.url.current(came_from=c.came_from))}
+        <div class="form">
+            <!-- fields -->
 
-                    <div class="fields">
-                        <div class="field">
-                            <div class="label">
-                                <label for="username">${_('Username')}:</label>
-                            </div>
-                            <div class="input">
-                                ${h.text('username',class_='focus',size=40)}
-                            </div>
-                            
-                        </div>                     
-                        <div class="field">
-                            <div class="label">
-                                <label for="password">${_('Password')}:</label>
-                            </div>
-                            <div class="input">
-                                ${h.password('password',class_='focus',size=40)}
-                            </div>
-                            
-                        </div>
-                        ##<div class="field">
-                        ##    <div class="checkbox">
-                        ##        <input type="checkbox" id="remember" name="remember" />
-                        ##        <label for="remember">Remember me</label>
-                        ##    </div>
-                        ##</div>
-                        <div class="buttons">
-                            ${h.submit('sign_in','Sign In',class_="ui-button")}
-                        </div>
+            <div class="fields">
+                <div class="field">
+                    <div class="label">
+                        <label for="username">${_('Username')}:</label>
+                    </div>
+                    <div class="input">
+                        ${h.text('username',class_='focus',size=40)}
+                    </div>
+                    
+                </div>                     
+                <div class="field">
+                    <div class="label">
+                        <label for="password">${_('Password')}:</label>
+                    </div>
+                    <div class="input">
+                        ${h.password('password',class_='focus',size=40)}
                     </div>
-                    <!-- end fields -->
-                    <!-- links -->
-                    <div class="links">
-                        ${h.link_to(_('Forgot your password ?'),h.url('reset_password'))}
-                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
-	                         / 
-	                        ${h.link_to(_("Don't have an account ?"),h.url('register'))}
-                        %endif
-                    </div>
+                    
+                </div>
+                ##<div class="field">
+                ##    <div class="checkbox">
+                ##        <input type="checkbox" id="remember" name="remember" />
+                ##        <label for="remember">Remember me</label>
+                ##    </div>
+                ##</div>
+                <div class="buttons">
+                    ${h.submit('sign_in',_('Sign In'),class_="ui-button")}
+                </div>
+            </div>
+            <!-- end fields -->
+            <!-- links -->
+            <div class="links">
+                ${h.link_to(_('Forgot your password ?'),h.url('reset_password'))}
+                %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
+                  / 
+                 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
+                %endif
+            </div>
 
-                    <!-- end links -->
-                </div>
-                ${h.end_form()}
-            </div>
-            <!-- end login -->
+            <!-- end links -->
         </div>
-    </body>
-</html>
-
+        ${h.end_form()}
+        <script type="text/javascript">
+        YUE.onDOMReady(function(){
+        	YUD.get('username').focus();
+        })
+        </script>
+    </div>
+    <!-- end login -->
+</div>
--- a/rhodecode/templates/password_reset.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/password_reset.html	Fri Oct 07 01:08:50 2011 +0200
@@ -1,48 +1,44 @@
 ## -*- coding: utf-8 -*-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>${_('Reset You password')} - ${c.rhodecode_name}</title>
-        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-        <link rel="icon" href="${h.url("/images/hgicon.png")}" type="image/png" />
-        <meta name="robots" content="index, nofollow"/>
-            
-        <!-- stylesheets -->
-        <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
+<%inherit file="base/root.html"/>
+
+<%def name="title()">
+    ${_('Reset your password')} - ${c.rhodecode_name}
+</%def>
 
-    </head>
-    <body>
-		<div id="register">
-			
-			<div class="title top-left-rounded-corner top-right-rounded-corner">
-				<h5>${_('Reset You password to')} ${c.rhodecode_name}</h5>
-			</div>
-			<div class="inner">
-			    ${h.form(url('password_reset'))}
-			    <div class="form">
-			        <!-- fields -->
-			        <div class="fields">
-			            
-			             <div class="field">
-			                <div class="label">
-			                    <label for="email">${_('Email address')}:</label>
-			                </div>
-			                <div class="input">
-			                    ${h.text('email')}
-			                </div>
-			             </div>
-			                        
-			            <div class="buttons">
-				            <div class="nohighlight">
-				              ${h.submit('send','Reset my password',class_="ui-button")}
-							  	<div class="activation_msg">${_('Your new password will be send to matching email address')}</div>
-				            </div>
-			            </div>             
-			    	</div>
-			    </div>
-			    ${h.end_form()}
-			</div>    
+<div id="register">
+	
+	<div class="title top-left-rounded-corner top-right-rounded-corner">
+		<h5>${_('Reset your password to')} ${c.rhodecode_name}</h5>
+	</div>
+	<div class="inner">
+	    ${h.form(url('password_reset'))}
+	    <div class="form">
+	        <!-- fields -->
+	        <div class="fields">
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="email">${_('Email address')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('email')}
+	                </div>
+	             </div>
+	                        
+	            <div class="buttons">
+		            <div class="nohighlight">
+		              ${h.submit('send',_('Reset my password'),class_="ui-button")}
+					  	<div class="activation_msg">${_('Password reset link will be send to matching email address')}</div>
+		            </div>
+	            </div>             
+	    	</div>
 	    </div>
-    </body>
-</html>
+	    ${h.end_form()}
+        <script type="text/javascript">
+        YUE.onDOMReady(function(){
+            YUD.get('email').focus();
+        })
+        </script>	    
+	</div>    
+   </div>
 
--- a/rhodecode/templates/register.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/register.html	Fri Oct 07 01:08:50 2011 +0200
@@ -1,96 +1,92 @@
 ## -*- coding: utf-8 -*-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>${_('Sign Up')} - ${c.rhodecode_name}</title>
-        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-        <link rel="icon" href="${h.url("/images/hgicon.png")}" type="image/png" />
-        <meta name="robots" content="index, nofollow"/>
-            
-        <!-- stylesheets -->
-        <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
+<%inherit file="base/root.html"/>
 
-    </head>
-    <body>
-		<div id="register">
-			
-			<div class="title top-left-rounded-corner top-right-rounded-corner">
-				<h5>${_('Sign Up to')} ${c.rhodecode_name}</h5>
-			</div>
-			<div class="inner">
-			    ${h.form(url('register'))}
-			    <div class="form">
-			        <!-- fields -->
-			        <div class="fields">
-			             <div class="field">
-			                <div class="label">
-			                    <label for="username">${_('Username')}:</label>
-			                </div>
-			                <div class="input">
-			                    ${h.text('username',class_="medium")}
-			                </div>
-			             </div>
-			            
-			             <div class="field">
-			                <div class="label">
-			                    <label for="password">${_('Password')}:</label>
-			                </div>
-			                <div class="input">
-			                    ${h.password('password',class_="medium")}
-			                </div>
-			             </div>
-                         
-                         <div class="field">
-                            <div class="label">
-                                <label for="password">${_('Re-enter password')}:</label>
-                            </div>
-                            <div class="input">
-                                ${h.password('password_confirmation',class_="medium")}
-                            </div>
-                         </div>
-                         			            
-			             <div class="field">
-			                <div class="label">
-			                    <label for="name">${_('First Name')}:</label>
-			                </div>
-			                <div class="input">
-			                    ${h.text('name',class_="medium")}
-			                </div>
-			             </div>
-			            
-			             <div class="field">
-			                <div class="label">
-			                    <label for="lastname">${_('Last Name')}:</label>
-			                </div>
-			                <div class="input">
-			                    ${h.text('lastname',class_="medium")}
-			                </div>
-			             </div>
-			            
-			             <div class="field">
-			                <div class="label">
-			                    <label for="email">${_('Email')}:</label>
-			                </div>
-			                <div class="input">
-			                    ${h.text('email',class_="medium")}
-			                </div>
-			             </div>
-			                        
-			            <div class="buttons">
-				            <div class="nohighlight">
-				              ${h.submit('sign_up','Sign Up',class_="ui-button")}
-				              %if c.auto_active:
-							  	<div class="activation_msg">${_('Your account will be activated right after registration')}</div>
-							  %else:
-							  	<div class="activation_msg">${_('Your account must wait for activation by administrator')}</div>
-							  %endif
-				            </div>
-			            </div>             
-			    	</div>
-			    </div>
-			    ${h.end_form()}
-			</div>    
+<%def name="title()">
+    ${_('Sign Up')} - ${c.rhodecode_name}
+</%def>
+    
+<div id="register">
+	
+	<div class="title top-left-rounded-corner top-right-rounded-corner">
+		<h5>${_('Sign Up to')} ${c.rhodecode_name}</h5>
+	</div>
+	<div class="inner">
+	    ${h.form(url('register'))}
+	    <div class="form">
+	        <!-- fields -->
+	        <div class="fields">
+	             <div class="field">
+	                <div class="label">
+	                    <label for="username">${_('Username')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('username',class_="medium")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="password">${_('Password')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.password('password',class_="medium")}
+	                </div>
+	             </div>
+                       
+                       <div class="field">
+                          <div class="label">
+                              <label for="password">${_('Re-enter password')}:</label>
+                          </div>
+                          <div class="input">
+                              ${h.password('password_confirmation',class_="medium")}
+                          </div>
+                       </div>
+                       			            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="name">${_('First Name')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('name',class_="medium")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="lastname">${_('Last Name')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('lastname',class_="medium")}
+	                </div>
+	             </div>
+	            
+	             <div class="field">
+	                <div class="label">
+	                    <label for="email">${_('Email')}:</label>
+	                </div>
+	                <div class="input">
+	                    ${h.text('email',class_="medium")}
+	                </div>
+	             </div>
+	                        
+	            <div class="buttons">
+		            <div class="nohighlight">
+		              ${h.submit('sign_up',_('Sign Up'),class_="ui-button")}
+		              %if c.auto_active:
+					  	<div class="activation_msg">${_('Your account will be activated right after registration')}</div>
+					  %else:
+					  	<div class="activation_msg">${_('Your account must wait for activation by administrator')}</div>
+					  %endif
+		            </div>
+	            </div>             
+	    	</div>
 	    </div>
-    </body>
-</html>
+	    ${h.end_form()}
+        <script type="text/javascript">
+        YUE.onDOMReady(function(){
+            YUD.get('username').focus();
+        })
+        </script>	    
+	</div>    
+ </div>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/repo_switcher_list.html	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,23 @@
+## -*- coding: utf-8 -*-
+
+<li class="qfilter_rs">
+<input type="text" 
+style="border:0"        
+value="quick filter..." 
+name="filter" size="15" id="q_filter_rs" />
+</li>
+    
+%for repo in c.repos_list:
+     
+      %if repo['dbrepo']['private']:
+         <li>
+             <img src="${h.url("/images/icons/lock.png")}" alt="${_('Private repository')}" class="repo_switcher_type"/>
+             ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])}
+          </li>
+      %else:
+         <li>
+             <img src="${h.url("/images/icons/lock_open.png")}" alt="${_('Public repository')}" class="repo_switcher_type" />
+             ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])}
+         </li>
+      %endif  
+%endfor
\ No newline at end of file
--- a/rhodecode/templates/search/search.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/search/search.html	Fri Oct 07 01:08:50 2011 +0200
@@ -43,7 +43,7 @@
              </div> 			
 				<div class="input">${h.text('q',c.cur_query,class_="small")}
 					<div class="button highlight">
-						<input type="submit" value="${_('Search')}" class="ui-button ui-widget ui-state-default ui-corner-all"/>
+						<input type="submit" value="${_('Search')}" class="ui-button"/>
 					</div>
 				</div>
 				<div style="font-weight: bold;clear:Both;margin-left:200px">${c.runtime}</div>		
@@ -54,7 +54,7 @@
 	                <label for="type">${_('Search in')}</label>
 	            </div>
                 <div class="select">
-                    ${h.select('type',c.cur_type,[('content',_('Source codes')),
+                    ${h.select('type',c.cur_type,[('content',_('File contents')),
                         ##('commit',_('Commit messages')),
                         ('path',_('File names')),
                         ##('repository',_('Repository names')),
--- a/rhodecode/templates/settings/repo_fork.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/settings/repo_fork.html	Fri Oct 07 01:08:50 2011 +0200
@@ -6,6 +6,8 @@
 </%def>
 
 <%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo;
     ${h.link_to(c.repo_info.repo_name,h.url('summary_home',repo_name=c.repo_info.repo_name))} 
     &raquo;
     ${_('fork')}
@@ -50,7 +52,7 @@
                 </div>
              </div>
 	        <div class="buttons">
-	          ${h.submit('','fork this repository',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+	          ${h.submit('',_('fork this repository'),class_="ui-button")}
 	        </div>                                                          
         </div>
     </div>    
--- a/rhodecode/templates/settings/repo_settings.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/settings/repo_settings.html	Fri Oct 07 01:08:50 2011 +0200
@@ -6,6 +6,8 @@
 </%def>
 
 <%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo;
     ${h.link_to(c.repo_info.repo_name,h.url('summary_home',repo_name=c.repo_info.repo_name))} 
     &raquo; 
     ${_('Settings')} 
@@ -56,206 +58,16 @@
                     <label for="">${_('Permissions')}:</label>
                 </div>
                 <div class="input">
-                    <table id="permissions_manage">
-                        <tr>
-                            <td>${_('none')}</td>
-                            <td>${_('read')}</td>
-                            <td>${_('write')}</td>
-                            <td>${_('admin')}</td>
-                            <td>${_('user')}</td>
-                            <td></td>
-                        </tr>
-                        
-                        %for r2p in c.repo_info.repo_to_perm:
-                            %if r2p.user.username =='default' and c.repo_info.private:
-                                <tr>
-                                    <td colspan="4">
-                                        <span class="private_repo_msg">
-                                        ${_('private repository')}
-                                        </span>
-                                    </td>
-                                    <td class="private_repo_msg">${r2p.user.username}</td>
-                                </tr>
-                            %else:
-                            <tr id="id${id(r2p.user.username)}">
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
-                                <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
-                                <td>${r2p.user.username}</td>
-                                <td>
-                                  %if r2p.user.username !='default':
-                                    <span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
-                                        <script type="text/javascript">
-                                            function ajaxAction(user_id,field_id){
-                                                var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
-                                                var callback = { success:function(o){
-                                                var tr = YAHOO.util.Dom.get(String(field_id));
-                                                tr.parentNode.removeChild(tr);},failure:function(o){
-                                                	alert("${_('Failed to remove user')}");},};
-                                                var postData = '_method=delete&user_id='+user_id; 
-                                                var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
-                                        </script>           
-                                    </span>
-                                  %endif                    
-                                </td>
-                            </tr>
-                            %endif
-                        %endfor
-
-
-                        <tr id="add_perm_input">
-                            <td>${h.radio('perm_new_user','repository.none')}</td>
-                            <td>${h.radio('perm_new_user','repository.read')}</td>
-                            <td>${h.radio('perm_new_user','repository.write')}</td>
-                            <td>${h.radio('perm_new_user','repository.admin')}</td>
-                            <td class='ac'>
-                                <div class="perm_ac" id="perm_ac">
-                                    ${h.text('perm_new_user_name',class_='yui-ac-input')}
-                                    <div id="perm_container"></div>
-                                </div>
-                            </td>
-                            <td></td>
-                        </tr>
-                        <tr>
-                            <td colspan="6">
-                                <span id="add_perm" class="add_icon" style="cursor: pointer;">
-                                ${_('Add another user')}
-                                </span>
-                            </td>
-                        </tr>
-                    </table>             
-             </div>
+                    <%include file="../admin/repos/repo_edit_perms.html"/>
+                </div>
              
             <div class="buttons">
-              ${h.submit('update','Update',class_="ui-button ui-widget ui-state-default ui-corner-all")}
-              ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+              ${h.submit('save','Save',class_="ui-button")}
+              ${h.reset('reset','Reset',class_="ui-button")}
             </div>                                                          
         </div>
     </div>    
     ${h.end_form()}
-        <script type="text/javascript">
-            YAHOO.util.Event.onDOMReady(function(){
-                var D = YAHOO.util.Dom;
-                if(!D.hasClass('perm_new_user_name','error')){
-                    D.setStyle('add_perm_input','display','none');
-                }
-                YAHOO.util.Event.addListener('add_perm','click',function(){
-                    D.setStyle('add_perm_input','display','');
-                    D.setStyle('add_perm','opacity','0.6');
-                    D.setStyle('add_perm','cursor','default');
-                });
-            });
-        </script>
-        <script type="text/javascript">    
-        YAHOO.example.FnMultipleFields = function(){
-            var myContacts = ${c.users_array|n}
-            
-            // Define a custom search function for the DataSource
-            var matchNames = function(sQuery) {
-                // Case insensitive matching
-                var query = sQuery.toLowerCase(),
-                    contact,
-                    i=0,
-                    l=myContacts.length,
-                    matches = [];
-                
-                // Match against each name of each contact
-                for(; i<l; i++) {
-                    contact = myContacts[i];
-                    if((contact.fname.toLowerCase().indexOf(query) > -1) ||
-                        (contact.lname.toLowerCase().indexOf(query) > -1) ||
-                        (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
-                        matches[matches.length] = contact;
-                    }
-                }
-        
-                return matches;
-            };
-        
-            // Use a FunctionDataSource
-            var oDS = new YAHOO.util.FunctionDataSource(matchNames);
-            oDS.responseSchema = {
-                fields: ["id", "fname", "lname", "nname"]
-            }
-        
-            // Instantiate AutoComplete for perms
-            var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
-            oAC_perms.useShadow = false;
-            oAC_perms.resultTypeList = false;
-            
-            // Instantiate AutoComplete for owner
-            var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
-            oAC_owner.useShadow = false;
-            oAC_owner.resultTypeList = false;
-            
-            
-            // Custom formatter to highlight the matching letters
-            var custom_formatter = function(oResultData, sQuery, sResultMatch) {
-                var query = sQuery.toLowerCase(),
-                    fname = oResultData.fname,
-                    lname = oResultData.lname,
-                    nname = oResultData.nname || "", // Guard against null value
-                    query = sQuery.toLowerCase(),
-                    fnameMatchIndex = fname.toLowerCase().indexOf(query),
-                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
-                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
-                    displayfname, displaylname, displaynname;
-                    
-                if(fnameMatchIndex > -1) {
-                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
-                }
-                else {
-                    displayfname = fname;
-                }
-        
-                if(lnameMatchIndex > -1) {
-                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
-                }
-                else {
-                    displaylname = lname;
-                }
-        
-                if(nnameMatchIndex > -1) {
-                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
-                }
-                else {
-                    displaynname = nname ? "(" + nname + ")" : "";
-                }
-        
-                return displayfname + " " + displaylname + " " + displaynname;
-                
-            };
-            oAC_perms.formatResult = custom_formatter; 
-            oAC_owner.formatResult = custom_formatter;
-                            
-            // Helper function for the formatter
-            var highlightMatch = function(full, snippet, matchindex) {
-                return full.substring(0, matchindex) + 
-                        "<span class='match'>" + 
-                        full.substr(matchindex, snippet.length) + 
-                        "</span>" +
-                        full.substring(matchindex + snippet.length);
-            };
-        
-            var myHandler = function(sType, aArgs) {
-                var myAC = aArgs[0]; // reference back to the AC instance
-                var elLI = aArgs[1]; // reference to the selected LI element
-                var oData = aArgs[2]; // object literal of selected item's result data
-                myAC.getInputEl().value = oData.nname;
-            };
-
-            oAC_perms.itemSelectEvent.subscribe(myHandler);
-            //oAC_owner.itemSelectEvent.subscribe(myHandler);
-            
-            return {
-                oDS: oDS,
-                oAC_perms: oAC_perms,
-                oAC_owner: oAC_owner, 
-            };
-        }();
-            
-        </script>      
 </div>
 </div>
 </%def> 
--- a/rhodecode/templates/shortlog/shortlog_data.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/shortlog/shortlog_data.html	Fri Oct 07 01:08:50 2011 +0200
@@ -46,19 +46,16 @@
 </table>
 
 <script type="text/javascript">
-  var data_div = 'shortlog_data';
-  YAHOO.util.Event.onDOMReady(function(){
-    YAHOO.util.Event.addListener(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
-            YAHOO.util.Dom.setStyle('shortlog_data','opacity','0.3');});});
+  YUE.onDOMReady(function(){
+    YUE.delegate("shortlog_data","click",function(e, matchedEl, container){
+        ypjax(e.target.href,"shortlog_data",function(){tooltip_activate();});
+        YUE.preventDefault(e);
+    },'.pager_link');	  
+  });
 </script>
 
 <div class="pagination-wh pagination-left">
-${c.repo_changesets.pager('$link_previous ~2~ $link_next',     
-onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{
-success:function(o){YAHOO.util.Dom.get(data_div).innerHTML=o.responseText;
-YAHOO.util.Event.addListener(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
-        YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');});       
-YAHOO.util.Dom.setStyle(data_div,'opacity','1');}},null); return false;""")}
+${c.repo_changesets.pager('$link_previous ~2~ $link_next')}
 </div>
 %else:
     ${_('There are no changes yet')}
--- a/rhodecode/templates/summary/summary.html	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/templates/summary/summary.html	Fri Oct 07 01:08:50 2011 +0200
@@ -7,7 +7,7 @@
 <%def name="breadcrumbs_links()">
     ${h.link_to(u'Home',h.url('/'))}
     &raquo; 
-    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    ${h.link_to(c.dbrepo.just_name,h.url('summary_home',repo_name=c.repo_name))}
     &raquo;
     ${_('summary')}
 </%def>
@@ -24,48 +24,65 @@
     </div>
     <!-- end box / title -->
 	<div class="form">
-	  <div class="fields">
+	  <div id="summary" class="fields">
 		 
 			 <div class="field">
 			  <div class="label">
 			      <label>${_('Name')}:</label>
 			  </div>
 			  <div class="input-short">
-		         %if c.repo_info.dbrepo.repo_type =='hg':
+                  %if c.rhodecode_user.username != 'default':
+                      %if c.following:
+                      <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
+                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
+                      </span>                 
+                      %else:
+                      <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
+                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
+                      </span>
+                      %endif
+                  %endif:			  
+                 
+                 ##REPO TYPE
+		         %if c.dbrepo.repo_type =='hg':
 		           <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
 		         %endif
-		         %if c.repo_info.dbrepo.repo_type =='git':
+		         %if c.dbrepo.repo_type =='git':
 		           <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
 		         %endif 
-                                 			  
-	             %if c.repo_info.dbrepo.private:
+                            
+                 ##PUBLIC/PRIVATE     			  
+	             %if c.dbrepo.private:
 	                <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
 	             %else:
 	                <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
 	             %endif
-			      <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
-			      %if c.rhodecode_user.username != 'default':
-				      %if c.following:
-	                  <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
-	                        onclick="javascript:toggleFollowingRepo(this,${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
-	                  </span>			      
-				      %else:
-				      <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
-				            onclick="javascript:toggleFollowingRepo(this,${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
-				      </span>
-				      %endif
-				  %endif:
-			      <br/>
-		            %if c.repo_info.dbrepo.fork:
-		            	<span style="margin-top:5px">
-		            	<a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
-		            	<img class="icon" alt="${_('public')}"
-		            	title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}" 
-		            	src="${h.url("/images/icons/arrow_divide.png")}"/>
-		            	${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
-		            	</a>
-		            	</span>
-		            %endif			      
+	             
+	              ##REPO NAME
+			      <span class="repo_name">${h.repo_link(c.dbrepo.groups_and_repo)}</span>
+                  
+                  ##FORK
+		          %if c.dbrepo.fork:
+	            	<div style="margin-top:5px;clear:both"">
+	            	<a href="${h.url('summary_home',repo_name=c.dbrepo.fork.repo_name)}">
+	            	<img class="icon" alt="${_('public')}"
+	            	title="${_('Fork of')} ${c.dbrepo.fork.repo_name}" 
+	            	src="${h.url("/images/icons/arrow_divide.png")}"/>
+	            	${_('Fork of')} ${c.dbrepo.fork.repo_name}
+	            	</a>
+	            	</div>
+		          %endif
+		          ##REMOTE
+				  %if c.dbrepo.clone_uri:
+                    <div style="margin-top:5px;clear:both">
+                    <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}">
+                    <img class="icon" alt="${_('remote clone')}"
+                    title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}" 
+                    src="${h.url("/images/icons/connect.png")}"/>
+                    ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
+                    </a>
+                    </div>					
+				  %endif		            		      
 			  </div>
 			 </div>
 			
@@ -74,9 +91,7 @@
 			  <div class="label">
 			      <label>${_('Description')}:</label>
 			  </div>
-			  <div class="input-short">
-			      ${c.repo_info.dbrepo.description}
-			  </div>
+			  <div class="input-short desc">${h.urlify_text(c.dbrepo.description)}</div>
 			 </div>
 			
 			
@@ -86,11 +101,11 @@
 			  </div>
 			  <div class="input-short">
 			  	<div class="gravatar">
-			  		<img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
+			  		<img alt="gravatar" src="${h.gravatar_url(c.dbrepo.user.email)}"/>
 			  	</div>
-			  		${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
-			  		${_('Name')}: ${c.repo_info.dbrepo.user.name} ${c.repo_info.dbrepo.user.lastname}<br/>
-			  		${_('Email')}: <a href="mailto:${c.repo_info.dbrepo.user.email}">${c.repo_info.dbrepo.user.email}</a>
+			  		${_('Username')}: ${c.dbrepo.user.username}<br/>
+			  		${_('Name')}: ${c.dbrepo.user.name} ${c.dbrepo.user.lastname}<br/>
+			  		${_('Email')}: <a href="mailto:${c.dbrepo.user.email}">${c.dbrepo.user.email}</a>
 			  </div>
 			 </div>
 			
@@ -99,8 +114,11 @@
 			      <label>${_('Last change')}:</label>
 			  </div>
 			  <div class="input-short">
-			      ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change} 
-			      ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author} 
+                  <b>${'r%s:%s' % (h.get_changeset_safe(c.rhodecode_repo,'tip').revision,
+                            h.get_changeset_safe(c.rhodecode_repo,'tip').short_id)}</b> - 
+			      <span class="tooltip" title="${c.rhodecode_repo.last_change}">
+			      ${h.age(c.rhodecode_repo.last_change)}</span><br/>
+			      ${_('by')} ${h.get_changeset_safe(c.rhodecode_repo,'tip').author} 
 			      
 			  </div>
 			 </div>
@@ -110,7 +128,7 @@
 			      <label>${_('Clone url')}:</label>
 			  </div>
 			  <div class="input-short">
-			      <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
+			      <input type="text" id="clone_url" readonly="readonly" value="${c.rhodecode_repo.alias} clone ${c.clone_repo_url}" size="70"/>
 			  </div>
 			 </div>
 			 
@@ -119,96 +137,7 @@
 			      <label>${_('Trending source files')}:</label>
 			  </div>
 			  <div class="input-short">
-			    <div id="lang_stats">
-			    
-			    </div> 			  
-			  	<script type="text/javascript">
-				  	YUE.onDOMReady(function(e){
-				  	    id = 'clone_url';
-				  	    YUE.on(id,'click',function(e){
-				  	        YUD.get('clone_url').select();
-				  	    })
-				  	})
-			  		var data = ${c.trending_languages|n};
-			  		var total = 0;
-			  		var no_data = true;
-			  		for (k in data){
-			  		    total += data[k];
-			  		    no_data = false;
-			  		} 
-					var tbl = document.createElement('table');
-					tbl.setAttribute('class','trending_language_tbl');
-					var cnt =0;
-			  		for (k in data){
-			  			cnt+=1;
-			  			var hide = cnt>2;
-				  		var tr = document.createElement('tr');
-				  		if (hide){
-				  			tr.setAttribute('style','display:none');
-				  			tr.setAttribute('class','stats_hidden');
-				  		}
-				  		var percentage = Math.round((data[k]/total*100),2);
-						var value = data[k];
-				  		var td1 = document.createElement('td');
-				  		td1.width=150;
-				  		var trending_language_label = document.createElement('div');
-				  		trending_language_label.innerHTML = k;
-				  		td1.appendChild(trending_language_label);
-
-				  		var td2 = document.createElement('td');
-				  		td2.setAttribute('style','padding-right:14px !important');
-			  		    var trending_language = document.createElement('div');
-			  		    var nr_files = value+" ${_('files')}";
-			  		    
-			  		    trending_language.title = k+" "+nr_files;
-			  		    
-			  		    if (percentage>20){
-			  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";	
-			  		    }
-			  		    else{
-			  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
-			  		    }
-			  		    
-			  		    trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
-			  		    trending_language.style.width=percentage+"%";
-						td2.appendChild(trending_language);
-						
-						tr.appendChild(td1);
-						tr.appendChild(td2);
-			  		    tbl.appendChild(tr);
-			  		    if(cnt == 3){
-			  		    	var show_more = document.createElement('tr');
-			  		    	var td=document.createElement('td');
-			  		    	lnk = document.createElement('a');
-			  		    	lnk.href='#';
-			  		    	lnk.innerHTML = "${_("show more")}";
-			  		    	lnk.id='code_stats_show_more';
-			  		        td.appendChild(lnk);
-			  		    	show_more.appendChild(td);
-			  		    	show_more.appendChild(document.createElement('td'));
-			  		    	tbl.appendChild(show_more);
-			  		    }
-			  		    
-			  		}
-			  		if(no_data){
-			  			var tr = document.createElement('tr');
-			  			var td1 = document.createElement('td');
-			  			td1.innerHTML = "${c.no_data_msg}";
-			  			tr.appendChild(td1);
-			  			tbl.appendChild(tr);
-					}
-			  		YUD.get('lang_stats').appendChild(tbl);
-			  		YUE.on('code_stats_show_more','click',function(){
-			  			l = YUD.getElementsByClassName('stats_hidden')
-			  			for (e in l){
-			  			    YUD.setStyle(l[e],'display','');
-			  			};
-			  			YUD.setStyle(YUD.get('code_stats_show_more'),
-			  					'display','none');
-			  		})
-			  		
-			  	</script>
- 
+			    <div id="lang_stats"></div> 			   
 			  </div>
 			 </div>
 			 			
@@ -217,14 +146,28 @@
 			      <label>${_('Download')}:</label>
 			  </div>
 			  <div class="input-short">
-		        %for cnt,archive in enumerate(c.repo_info._get_archives()):
-		             %if cnt >=1:
-		             |
-		             %endif
-		             ${h.link_to(archive['type'],
-		                h.url('files_archive_home',repo_name=c.repo_info.name,
-		                revision='tip',fileformat=archive['extension']),class_="archive_icon")}
-		        %endfor
+		        %if len(c.rhodecode_repo.revisions) == 0:
+		          ${_('There are no downloads yet')}
+		        %elif c.enable_downloads is False:
+		          ${_('Downloads are disabled for this repository')}
+                    %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
+                        [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
+                    %endif  		          
+		        %else:
+			        ${h.select('download_options',c.rhodecode_repo.get_changeset().raw_id,c.download_options)}
+			        %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
+			             %if cnt >=1:
+			             |
+			             %endif
+			             <span class="tooltip" title="${_('Download %s as %s') %('tip',archive['type'])}" 
+			                  id="${archive['type']+'_link'}">${h.link_to(archive['type'],
+			                h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
+			                fname='tip'+archive['extension']),class_="archive_icon")}</span>
+			        %endfor
+                    <span style="vertical-align: bottom">
+                        <input id="archive_subrepos" type="checkbox" name="subrepos"/> <span class="tooltip" title="${_('Check this to download archive with subrepos')}" >${_('with subrepos')}</span>
+                    </span>
+			    %endif
 			  </div>
 			 </div>
 			 
@@ -233,12 +176,134 @@
 			      <label>${_('Feeds')}:</label>
 			  </div>
 			  <div class="input-short">
-	            ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
-	            ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
+			   %if c.rhodecode_user.username != 'default':
+	            ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='rss_icon')}
+	            ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='atom_icon')}
+	           %else:
+                ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name),class_='rss_icon')}
+                ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name),class_='atom_icon')}	           
+	           %endif 
 			  </div>
 			 </div>				 			 			 
 	  </div>		 
-	</div>				
+	</div>
+  	<script type="text/javascript">
+	  	YUE.onDOMReady(function(e){
+	  	    id = 'clone_url';
+	  	    YUE.on(id,'click',function(e){
+	  	    	if(YUD.hasClass(id,'selected')){
+	  	    		return
+	  	    	}
+	  	    	else{
+	                YUD.addClass(id,'selected');
+	                YUD.get(id).select();	  	    		
+	  	    	}
+
+	  	    })
+	  	})
+  		var data = ${c.trending_languages|n};
+  		var total = 0;
+  		var no_data = true;
+  		for (k in data){
+  		    total += data[k].count;
+  		    no_data = false;
+  		} 
+		var tbl = document.createElement('table');
+		tbl.setAttribute('class','trending_language_tbl');
+		var cnt = 0;
+  		for (k in data){
+  			cnt += 1;
+  			var hide = cnt>2;
+	  		var tr = document.createElement('tr');
+	  		if (hide){
+	  			tr.setAttribute('style','display:none');
+	  			tr.setAttribute('class','stats_hidden');
+	  		}
+	  		var percentage = Math.round((data[k].count/total*100),2);
+			var value = data[k].count;
+	  		var td1 = document.createElement('td');
+	  		td1.width = 150;
+	  		var trending_language_label = document.createElement('div');
+	  		trending_language_label.innerHTML = data[k].desc+" ("+k+")";
+	  		td1.appendChild(trending_language_label);
+
+	  		var td2 = document.createElement('td');
+	  		td2.setAttribute('style','padding-right:14px !important');
+  		    var trending_language = document.createElement('div');
+  		    var nr_files = value+" ${_('files')}";
+  		    
+  		    trending_language.title = k+" "+nr_files;
+  		    
+  		    if (percentage>22){
+  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";	
+  		    }
+  		    else{
+  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
+  		    }
+  		    
+  		    trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
+  		    trending_language.style.width=percentage+"%";
+			td2.appendChild(trending_language);
+			
+			tr.appendChild(td1);
+			tr.appendChild(td2);
+  		    tbl.appendChild(tr);
+  		    if(cnt == 3){
+  		    	var show_more = document.createElement('tr');
+  		    	var td = document.createElement('td');
+  		    	lnk = document.createElement('a');
+  		    	
+  		    	lnk.href='#';
+  		    	lnk.innerHTML = "${_('show more')}";
+  		    	lnk.id='code_stats_show_more';
+  		        td.appendChild(lnk);
+  		        
+  		    	show_more.appendChild(td);
+  		    	show_more.appendChild(document.createElement('td'));
+  		    	tbl.appendChild(show_more);
+  		    }
+  		    
+  		}
+  		if(no_data){
+  			var tr = document.createElement('tr');
+  			var td1 = document.createElement('td');
+  			td1.innerHTML = "${c.no_data_msg}";
+  			tr.appendChild(td1);
+  			tbl.appendChild(tr);
+		}
+  		YUD.get('lang_stats').appendChild(tbl);
+  		YUE.on('code_stats_show_more','click',function(){
+  			l = YUD.getElementsByClassName('stats_hidden')
+  			for (e in l){
+  			    YUD.setStyle(l[e],'display','');
+  			};
+  			YUD.setStyle(YUD.get('code_stats_show_more'),
+  					'display','none');
+  		})
+  	
+             var tmpl_links = {}
+              %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
+                tmpl_links['${archive['type']}'] = '${h.link_to(archive['type'],
+                     h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
+                     fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_="archive_icon")}';
+              %endfor
+              
+             YUE.on(['download_options','archive_subrepos'],'change',function(e){
+            	 var sm = YUD.get('download_options');
+                 var new_cs = sm.options[sm.selectedIndex];
+                 
+                 for(k in tmpl_links){
+                	 var s = YUD.get(k+'_link');
+                	 title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
+                	 s.title = title_tmpl.replace('__CS_NAME__',new_cs.text);
+                	 s.title = s.title.replace('__CS_EXT__',k);
+                	 var url = tmpl_links[k].replace('__CS__',new_cs.value);
+                	 var subrepos = YUD.get('archive_subrepos').checked
+                	 url = url.replace('__SUB__',subrepos);
+                	 s.innerHTML = url 
+                 }
+             });
+  	</script>    				
 </div>
         
 <div class="box box-right"  style="min-height:455px">
@@ -248,10 +313,17 @@
     </div>
     
     <div class="graph">
-        
+         <div style="padding:0 10px 10px 15px;font-size: 1.2em;">
          %if c.no_data:
-           <div style="padding:0 10px 10px 15px;font-size: 1.2em;">${c.no_data_msg}</div>
-        %endif:  
+           ${c.no_data_msg}
+           %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
+                [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
+           %endif         
+           
+        %else:
+            ${_('Loaded in')} ${c.stats_percentage} %
+        %endif
+        </div>  
         <div id="commit_history" style="width:450px;height:300px;float:left"></div>
         <div style="clear: both;height: 10px"></div>
         <div id="overview" style="width:450px;height:100px;float:left"></div>
@@ -384,43 +456,33 @@
 		    function getDataAccordingToRanges(ranges) {
 		    	
 		        var data = [];
+		        var new_dataset = {};
 		        var keys = [];
+		        var max_commits = 0;
 				for(var key in dataset){
-					var push = false;
 					
-					//method1 slow !!
-		            //*
 		            for(var ds in dataset[key].data){
 			            commit_data = dataset[key].data[ds];
 			            if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
-			            	push = true;
-			            	break;
+
+			            	if(new_dataset[key] === undefined){
+			            		new_dataset[key] = {data:[],schema:["commits"],label:key};	
+			            	}
+			            	new_dataset[key].data.push(commit_data);
 					    }
 				    }
-					//*/
-				    
-				    /*//method2 sorted commit data !!!
-				    
-				    var first_commit = dataset[key].data[0].time;
-				    var last_commit = dataset[key].data[dataset[key].data.length-1].time;
-				    
-				    if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
-						push = true;
-					}
-				    //*/
-				    
-				    if(push){			
-				    	data.push(dataset[key]);
-				    }
+		            if (new_dataset[key] !== undefined){
+		            	data.push(new_dataset[key]);	
+		            }
 				}
-				if(data.length >= 1){
-					return data;
-				} 
+
+				if (data.length > 0){
+					return data;	
+				}
 				else{
 					//just return dummy data for graph to plot itself
 					return [getDummyData('')];	
 				}
-				
 		    }
 		    
 			/**
@@ -469,7 +531,7 @@
 		       //resubscribe plothover
 		       plot.subscribe("plothover", plothover);
 		        
-		       // don't fire event on the overview to prevent eternal loop
+		       // don't fire event on the overview to prevent eternal loop 
 		       overview.setSelection(cur_ranges, true);
 	
 		    }
@@ -481,7 +543,7 @@
 		     */
 		    function plotselected(ranges,cur_data) {
 			    //updates the data for new plot
-	    		data = getDataAccordingToRanges(ranges);
+	    		var data = getDataAccordingToRanges(ranges);
 	    		generateCheckboxes(data);
 	    		
 		    	var new_options = YAHOO.lang.merge(plot_options, {
@@ -491,13 +553,8 @@
 		  	      		mode:"time",
 		  	      		timeformat: "%d/%m",
 		        	},
-		        	yaxis: { 
-                        min: ranges.yaxis.from, 
-                        max: ranges.yaxis.to,
-                    },
-                    		        	
 		    	});
-		    	// do the zooming
+		    	// do the zooming 
 		        plot = YAHOO.widget.Flot(plotContainer, data, new_options);
 
 		        plot.subscribe("plotselected", plotselected);
@@ -508,7 +565,7 @@
 		        // don't fire event on the overview to prevent eternal loop
 		        overview.setSelection(ranges, true);
 
-		        //resubscribe choiced
+		        //resubscribe choiced 
 		        YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
 		    }
 		    
@@ -576,25 +633,25 @@
 		     * MAIN EXECUTION
 		     */
 			
-			var data = getDataAccordingToRanges(initial_ranges);
+			var data = getDataAccordingToRanges(initial_ranges);    
 			generateCheckboxes(data);
 			
-		    //main plot
+		    //main plot 
 		    var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
 		    
-			//overview
-			var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
+			//overview 
+			var overview = YAHOO.widget.Flot(overviewContainer, 
+					overview_dataset, overview_options);
 			
-			//show initial selection on overview
+			//show initial selection on overview 
 			overview.setSelection(initial_ranges);    
 			
 		    plot.subscribe("plotselected", plotselected);
+		    plot.subscribe("plothover", plothover)
 		    
 		    overview.subscribe("plotselected", function (ranges) {
 		        plot.setSelection(ranges);
 		    });		
-				
-		    plot.subscribe("plothover", plothover);
 
 		    YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
 		}
--- a/rhodecode/tests/__init__.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/__init__.py	Fri Oct 07 01:08:50 2011 +0200
@@ -7,6 +7,9 @@
 This module initializes the application via ``websetup`` (`paster
 setup-app`) and provides the base testing objects.
 """
+import os
+from os.path import join as jn
+
 from unittest import TestCase
 
 from paste.deploy import loadapp
@@ -14,7 +17,7 @@
 from pylons import config, url
 from routes.util import URLGenerator
 from webtest import TestApp
-import os
+
 from rhodecode.model import meta
 import logging
 
@@ -24,19 +27,22 @@
 import pylons.test
 
 __all__ = ['environ', 'url', 'TestController', 'TESTS_TMP_PATH', 'HG_REPO',
-           'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', 'GIT_FORK', ]
+           'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', 'GIT_FORK',
+           'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS' ]
 
 # Invoke websetup with the current config file
 #SetupCommand('setup-app').run([config_file])
 
 ##RUNNING DESIRED TESTS
-#nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
-
+# nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
+# nosetests --pdb --pdb-failures 
 environ = {}
 
 #SOME GLOBALS FOR TESTS
-TESTS_TMP_PATH = '/tmp'
-
+from tempfile import _RandomNameSequence
+TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
+TEST_USER_ADMIN_LOGIN = 'test_admin'
+TEST_USER_ADMIN_PASS = 'test12'
 HG_REPO = 'vcs_test_hg'
 GIT_REPO = 'vcs_test_git'
 
@@ -58,15 +64,22 @@
         self.index_location = config['app_conf']['index_dir']
         TestCase.__init__(self, *args, **kwargs)
 
-    def log_user(self, username='test_admin', password='test12'):
+    def log_user(self, username=TEST_USER_ADMIN_LOGIN,
+                 password=TEST_USER_ADMIN_PASS):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username':username,
                                   'password':password})
-        print response
 
         if 'invalid user name' in response.body:
-            assert False, 'could not login using %s %s' % (username, password)
+            self.fail('could not login using %s %s' % (username, password))
+
+        self.assertEqual(response.status, '302 Found')
+        self.assertEqual(response.session['rhodecode_user'].username, username)
+        return response.follow()
 
-        assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
-        assert response.session['rhodecode_user'].username == username, 'wrong logged in user got %s expected %s' % (response.session['rhodecode_user'].username, username)
-        return response.follow()
+
+
+    def checkSessionFlash(self, response, msg):
+        self.assertTrue('flash' in response.session)
+        self.assertTrue(msg in response.session['flash'][0][1])
+
--- a/rhodecode/tests/functional/test_admin_ldap_settings.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_admin_ldap_settings.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,7 +1,87 @@
 from rhodecode.tests import *
+from rhodecode.model.db import RhodeCodeSettings
+from nose.plugins.skip import SkipTest
+
+skip_ldap_test = False
+try:
+    import ldap
+except ImportError:
+    # means that python-ldap is not installed
+    skip_ldap_test = True
+    pass
 
 class TestLdapSettingsController(TestController):
 
     def test_index(self):
-        response = self.app.get(url(controller='admin/ldap_settings', action='index'))
-        # Test response...
+        self.log_user()
+        response = self.app.get(url(controller='admin/ldap_settings',
+                                    action='index'))
+        self.assertTrue('LDAP administration' in response.body)
+
+    def test_ldap_save_settings(self):
+        self.log_user()
+        if skip_ldap_test:
+            raise SkipTest('skipping due to missing ldap lib')
+        
+        test_url = url(controller='admin/ldap_settings',
+                       action='ldap_settings')
+
+        response = self.app.post(url=test_url,
+            params={'ldap_host' : u'dc.example.com',
+                    'ldap_port' : '999',
+                    'ldap_tls_kind' : 'PLAIN',
+                    'ldap_tls_reqcert' : 'NEVER',
+                    'ldap_dn_user':'test_user',
+                    'ldap_dn_pass':'test_pass',
+                    'ldap_base_dn':'test_base_dn',
+                    'ldap_filter':'test_filter',
+                    'ldap_search_scope':'BASE',
+                    'ldap_attr_login':'test_attr_login',
+                    'ldap_attr_firstname':'ima',
+                    'ldap_attr_lastname':'tester',
+                    'ldap_attr_email':'test@example.com' })
+
+        new_settings = RhodeCodeSettings.get_ldap_settings()
+        self.assertEqual(new_settings['ldap_host'], u'dc.example.com',
+                         'fail db write compare')
+
+        self.checkSessionFlash(response,
+                               'Ldap settings updated successfully')
+
+    def test_ldap_error_form(self):
+        self.log_user()
+        if skip_ldap_test:
+            raise SkipTest('skipping due to missing ldap lib')
+                
+        test_url = url(controller='admin/ldap_settings',
+                       action='ldap_settings')
+
+        response = self.app.post(url=test_url,
+            params={'ldap_host' : '',
+                    'ldap_port' : 'i-should-be-number',
+                    'ldap_tls_kind' : 'PLAIN',
+                    'ldap_tls_reqcert' : 'NEVER',
+                    'ldap_dn_user':'',
+                    'ldap_dn_pass':'',
+                    'ldap_base_dn':'',
+                    'ldap_filter':'',
+                    'ldap_search_scope':'BASE',
+                    'ldap_attr_login':'', #  <----- missing required input
+                    'ldap_attr_firstname':'',
+                    'ldap_attr_lastname':'',
+                    'ldap_attr_email':'' })
+        
+        self.assertTrue("""<span class="error-message">The LDAP Login"""
+                        """ attribute of the CN must be specified""" in
+                        response.body)
+        
+        
+        
+        self.assertTrue("""<span class="error-message">Please """
+                        """enter a number</span>""" in response.body)
+
+    def test_ldap_login(self):
+        pass
+
+    def test_ldap_login_incorrect(self):
+        pass
--- a/rhodecode/tests/functional/test_admin_repos.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_admin_repos.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,8 +1,18 @@
+# -*- coding: utf-8 -*-
+
+import os
+import vcs
+
 from rhodecode.model.db import Repository
 from rhodecode.tests import *
 
 class TestAdminReposController(TestController):
 
+
+    def __make_repo(self):
+        pass
+
+
     def test_index(self):
         self.log_user()
         response = self.app.get(url('repos'))
@@ -18,23 +28,72 @@
         private = False
         response = self.app.post(url('repos'), {'repo_name':repo_name,
                                                 'repo_type':'hg',
+                                                'clone_uri':'',
+                                                'repo_group':'',
                                                 'description':description,
                                                 'private':private})
 
-
-        #test if we have a message for that repository
-        assert '''created repository %s''' % (repo_name) in response.session['flash'][0], 'No flash message about new repo'
+        self.checkSessionFlash(response, 'created repository %s' % (repo_name))
 
-        #test if the fork was created in the database
-        new_repo = self.sa.query(Repository).filter(Repository.repo_name == repo_name).one()
+        #test if the repo was created in the database
+        new_repo = self.sa.query(Repository).filter(Repository.repo_name ==
+                                                    repo_name).one()
 
-        assert new_repo.repo_name == repo_name, 'wrong name of repo name in db'
-        assert new_repo.description == description, 'wrong description'
+        self.assertEqual(new_repo.repo_name, repo_name)
+        self.assertEqual(new_repo.description, description)
 
         #test if repository is visible in the list ?
         response = response.follow()
 
-        assert repo_name in response.body, 'missing new repo from the main repos list'
+        self.assertTrue(repo_name in response.body)
+
+
+        #test if repository was created on filesystem
+        try:
+            vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
+        except:
+            self.fail('no repo in filesystem')
+
+
+    def test_create_hg_non_ascii(self):
+        self.log_user()
+        non_ascii = "ąęł"
+        repo_name = "%s%s" % (NEW_HG_REPO, non_ascii)
+        repo_name_unicode = repo_name.decode('utf8')
+        description = 'description for newly created repo' + non_ascii
+        description_unicode = description.decode('utf8')
+        private = False
+        response = self.app.post(url('repos'), {'repo_name':repo_name,
+                                                'repo_type':'hg',
+                                                'clone_uri':'',
+                                                'repo_group':'',
+                                                'description':description,
+                                                'private':private})
+        self.checkSessionFlash(response,
+                               'created repository %s' % (repo_name_unicode))
+
+        #test if the repo was created in the database
+        new_repo = self.sa.query(Repository).filter(Repository.repo_name ==
+                                                repo_name_unicode).one()
+
+        self.assertEqual(new_repo.repo_name, repo_name_unicode)
+        self.assertEqual(new_repo.description, description_unicode)
+
+        #test if repository is visible in the list ?
+        response = response.follow()
+
+        self.assertTrue(repo_name in response.body)
+
+        #test if repository was created on filesystem
+        try:
+            vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
+        except:
+            self.fail('no repo in filesystem')
+
+
+    def test_create_hg_in_group(self):
+        #TODO: write test !
+        pass
 
     def test_create_git(self):
         return
@@ -44,6 +103,8 @@
         private = False
         response = self.app.post(url('repos'), {'repo_name':repo_name,
                                                 'repo_type':'git',
+                                                'clone_uri':'',
+                                                'repo_group':'',
                                                 'description':description,
                                                 'private':private})
 
@@ -62,6 +123,11 @@
 
         assert repo_name in response.body, 'missing new repo from the main repos list'
 
+        #test if repository was created on filesystem
+        try:
+            vcs.get_repo(os.path.join(TESTS_TMP_PATH, repo_name))
+        except:
+            assert False , 'no repo in filesystem'
 
     def test_new(self):
         self.log_user()
@@ -74,58 +140,74 @@
         response = self.app.put(url('repo', repo_name=HG_REPO))
 
     def test_update_browser_fakeout(self):
-        response = self.app.post(url('repo', repo_name=HG_REPO), params=dict(_method='put'))
+        response = self.app.post(url('repo', repo_name=HG_REPO),
+                                 params=dict(_method='put'))
 
     def test_delete(self):
         self.log_user()
         repo_name = 'vcs_test_new_to_delete'
         description = 'description for newly created repo'
         private = False
+
         response = self.app.post(url('repos'), {'repo_name':repo_name,
                                                 'repo_type':'hg',
-                                               'description':description,
-                                               'private':private})
-
+                                                'clone_uri':'',
+                                                'repo_group':'',
+                                                'description':description,
+                                                'private':private})
+        self.assertTrue('flash' in response.session)
 
         #test if we have a message for that repository
-        assert '''created repository %s''' % (repo_name) in response.session['flash'][0], 'No flash message about new repo'
+        self.assertTrue('''created repository %s''' % (repo_name) in
+                        response.session['flash'][0])
 
         #test if the repo was created in the database
-        new_repo = self.sa.query(Repository).filter(Repository.repo_name == repo_name).one()
+        new_repo = self.sa.query(Repository).filter(Repository.repo_name ==
+                                                    repo_name).one()
 
-        assert new_repo.repo_name == repo_name, 'wrong name of repo name in db'
-        assert new_repo.description == description, 'wrong description'
+        self.assertEqual(new_repo.repo_name, repo_name)
+        self.assertEqual(new_repo.description, description)
 
         #test if repository is visible in the list ?
         response = response.follow()
 
-        assert repo_name in response.body, 'missing new repo from the main repos list'
+        self.assertTrue(repo_name in response.body)
 
 
         response = self.app.delete(url('repo', repo_name=repo_name))
 
-        assert '''deleted repository %s''' % (repo_name) in response.session['flash'][0], 'No flash message about delete repo'
+        self.assertTrue('''deleted repository %s''' % (repo_name) in
+                        response.session['flash'][0])
 
         response.follow()
 
         #check if repo was deleted from db
-        deleted_repo = self.sa.query(Repository).filter(Repository.repo_name == repo_name).scalar()
+        deleted_repo = self.sa.query(Repository).filter(Repository.repo_name
+                                                        == repo_name).scalar()
+
+        self.assertEqual(deleted_repo, None)
 
-        assert deleted_repo is None, 'Deleted repository was found in db'
+
+    def test_delete_repo_with_group(self):
+        #TODO:
+        pass
 
 
     def test_delete_browser_fakeout(self):
-        response = self.app.post(url('repo', repo_name=HG_REPO), params=dict(_method='delete'))
+        response = self.app.post(url('repo', repo_name=HG_REPO),
+                                 params=dict(_method='delete'))
 
     def test_show(self):
         self.log_user()
         response = self.app.get(url('repo', repo_name=HG_REPO))
 
     def test_show_as_xml(self):
-        response = self.app.get(url('formatted_repo', repo_name=HG_REPO, format='xml'))
+        response = self.app.get(url('formatted_repo', repo_name=HG_REPO,
+                                    format='xml'))
 
     def test_edit(self):
         response = self.app.get(url('edit_repo', repo_name=HG_REPO))
 
     def test_edit_as_xml(self):
-        response = self.app.get(url('formatted_edit_repo', repo_name=HG_REPO, format='xml'))
+        response = self.app.get(url('formatted_edit_repo', repo_name=HG_REPO,
+                                    format='xml'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/functional/test_admin_repos_groups.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,4 @@
+from rhodecode.tests import *
+
+class TestReposGroupsController(TestController):
+    pass
--- a/rhodecode/tests/functional/test_admin_settings.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_admin_settings.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,5 +1,7 @@
+# -*- coding: utf-8 -*-
+
 from rhodecode.lib.auth import get_crypt_password, check_password
-from rhodecode.model.db import User
+from rhodecode.model.db import User, RhodeCodeSettings
 from rhodecode.tests import *
 
 class TestAdminSettingsController(TestController):
@@ -42,15 +44,85 @@
         response = self.app.get(url('admin_edit_setting', setting_id=1))
 
     def test_edit_as_xml(self):
-        response = self.app.get(url('formatted_admin_edit_setting', setting_id=1, format='xml'))
+        response = self.app.get(url('formatted_admin_edit_setting',
+                                    setting_id=1, format='xml'))
+
+
+    def test_ga_code_active(self):
+        self.log_user()
+        old_title = 'RhodeCode'
+        old_realm = 'RhodeCode authentication'
+        new_ga_code = 'ga-test-123456789'
+        response = self.app.post(url('admin_setting', setting_id='global'),
+                                     params=dict(
+                                                 _method='put',
+                                                 rhodecode_title=old_title,
+                                                 rhodecode_realm=old_realm,
+                                                 rhodecode_ga_code=new_ga_code
+                                                 ))
+
+        self.checkSessionFlash(response, 'Updated application settings')
+
+        self.assertEqual(RhodeCodeSettings
+                         .get_app_settings()['rhodecode_ga_code'], new_ga_code)
+
+        response = response.follow()
+        self.assertTrue("""_gaq.push(['_setAccount', '%s']);""" % new_ga_code
+                        in response.body)
+
+    def test_ga_code_inactive(self):
+        self.log_user()
+        old_title = 'RhodeCode'
+        old_realm = 'RhodeCode authentication'
+        new_ga_code = ''
+        response = self.app.post(url('admin_setting', setting_id='global'),
+                                     params=dict(
+                                                 _method='put',
+                                                 rhodecode_title=old_title,
+                                                 rhodecode_realm=old_realm,
+                                                 rhodecode_ga_code=new_ga_code
+                                                 ))
+
+        self.assertTrue('Updated application settings' in
+                        response.session['flash'][0][1])
+        self.assertEqual(RhodeCodeSettings
+                        .get_app_settings()['rhodecode_ga_code'], new_ga_code)
+
+        response = response.follow()
+        self.assertTrue("""_gaq.push(['_setAccount', '%s']);""" % new_ga_code
+                        not in response.body)
+
+
+    def test_title_change(self):
+        self.log_user()
+        old_title = 'RhodeCode'
+        new_title = old_title + '_changed'
+        old_realm = 'RhodeCode authentication'
+
+        for new_title in ['Changed', 'Żółwik', old_title]:
+            response = self.app.post(url('admin_setting', setting_id='global'),
+                                         params=dict(
+                                                     _method='put',
+                                                     rhodecode_title=new_title,
+                                                     rhodecode_realm=old_realm,
+                                                     rhodecode_ga_code=''
+                                                     ))
+
+            self.checkSessionFlash(response, 'Updated application settings')
+            self.assertEqual(RhodeCodeSettings
+                             .get_app_settings()['rhodecode_title'],
+                             new_title.decode('utf-8'))
+
+            response = response.follow()
+            self.assertTrue("""<h1><a href="/">%s</a></h1>""" % new_title
+                        in response.body)
+
 
     def test_my_account(self):
         self.log_user()
         response = self.app.get(url('admin_settings_my_account'))
-        print response
-        assert 'value="test_admin' in response.body
 
-
+        self.assertTrue('value="test_admin' in response.body)
 
     def test_my_account_update(self):
         self.log_user()
@@ -61,14 +133,14 @@
         new_password = 'test123'
 
 
-        response = self.app.post(url('admin_settings_my_account_update'), params=dict(
-                                                            _method='put',
-                                                            username='test_admin',
-                                                            new_password=new_password,
-                                                            password='',
-                                                            name=new_name,
-                                                            lastname=new_lastname,
-                                                            email=new_email,))
+        response = self.app.post(url('admin_settings_my_account_update'),
+                                 params=dict(_method='put',
+                                             username='test_admin',
+                                             new_password=new_password,
+                                             password='',
+                                             name=new_name,
+                                             lastname=new_lastname,
+                                             email=new_email,))
         response.follow()
 
         assert 'Your account was updated successfully' in response.session['flash'][0][1], 'no flash message about success of change'
@@ -94,7 +166,9 @@
                                                             email=old_email,))
 
         response.follow()
-        assert 'Your account was updated successfully' in response.session['flash'][0][1], 'no flash message about success of change'
+        self.checkSessionFlash(response,
+                               'Your account was updated successfully')
+
         user = self.sa.query(User).filter(User.username == 'test_admin').one()
         assert user.email == old_email , 'incorrect user email after update got %s vs %s' % (user.email, old_email)
 
@@ -115,7 +189,6 @@
                                                             name='NewName',
                                                             lastname='NewLastname',
                                                             email=new_email,))
-        print response
 
         assert 'This e-mail address is already taken' in response.body, 'Missing error message about existing email'
 
@@ -131,6 +204,5 @@
                                                             name='NewName',
                                                             lastname='NewLastname',
                                                             email=new_email,))
-        print response
         assert 'An email address must contain a single @' in response.body, 'Missing error message about wrong email'
         assert 'This username already exists' in response.body, 'Missing error message about existing user'
--- a/rhodecode/tests/functional/test_admin_users.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_admin_users.py	Fri Oct 07 01:08:50 2011 +0200
@@ -100,7 +100,7 @@
         new_user = self.sa.query(User).filter(User.username == username).one()
         response = self.app.delete(url('user', id=new_user.user_id))
 
-        assert """sucessfully deleted user""" in response.session['flash'][0], 'No info about user deletion'
+        assert """successfully deleted user""" in response.session['flash'][0], 'No info about user deletion'
 
 
     def test_delete_browser_fakeout(self):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/functional/test_admin_users_groups.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,95 @@
+from rhodecode.tests import *
+from rhodecode.model.db import UsersGroup
+
+TEST_USERS_GROUP = 'admins_test'
+
+class TestAdminUsersGroupsController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url('users_groups'))
+        # Test response...
+
+    def test_index_as_xml(self):
+        response = self.app.get(url('formatted_users_groups', format='xml'))
+
+    def test_create(self):
+        self.log_user()
+        users_group_name = TEST_USERS_GROUP
+        response = self.app.post(url('users_groups'),
+                                 {'users_group_name':users_group_name,
+                                  'active':True})
+        response.follow()
+
+        self.checkSessionFlash(response,
+                               'created users group %s' % TEST_USERS_GROUP)
+
+
+
+
+
+    def test_new(self):
+        response = self.app.get(url('new_users_group'))
+
+    def test_new_as_xml(self):
+        response = self.app.get(url('formatted_new_users_group', format='xml'))
+
+    def test_update(self):
+        response = self.app.put(url('users_group', id=1))
+
+    def test_update_browser_fakeout(self):
+        response = self.app.post(url('users_group', id=1),
+                                 params=dict(_method='put'))
+
+    def test_delete(self):
+        self.log_user()
+        users_group_name = TEST_USERS_GROUP + 'another'
+        response = self.app.post(url('users_groups'),
+                                 {'users_group_name':users_group_name,
+                                  'active':True})
+        response.follow()
+
+        self.checkSessionFlash(response,
+                               'created users group %s' % users_group_name)
+
+
+        gr = self.sa.query(UsersGroup)\
+                           .filter(UsersGroup.users_group_name ==
+                                   users_group_name).one()
+
+        response = self.app.delete(url('users_group', id=gr.users_group_id))
+
+        gr = self.sa.query(UsersGroup)\
+                           .filter(UsersGroup.users_group_name ==
+                                   users_group_name).scalar()
+
+        self.assertEqual(gr, None)
+
+
+    def test_delete_browser_fakeout(self):
+        response = self.app.post(url('users_group', id=1),
+                                 params=dict(_method='delete'))
+
+    def test_show(self):
+        response = self.app.get(url('users_group', id=1))
+
+    def test_show_as_xml(self):
+        response = self.app.get(url('formatted_users_group', id=1, format='xml'))
+
+    def test_edit(self):
+        response = self.app.get(url('edit_users_group', id=1))
+
+    def test_edit_as_xml(self):
+        response = self.app.get(url('formatted_edit_users_group', id=1, format='xml'))
+
+    def test_assign_members(self):
+        pass
+
+    def test_add_create_permission(self):
+        pass
+
+    def test_revoke_members(self):
+        pass
+
+
+
+
--- a/rhodecode/tests/functional/test_changelog.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_changelog.py	Fri Oct 07 01:08:50 2011 +0200
@@ -4,32 +4,55 @@
 
     def test_index_hg(self):
         self.log_user()
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO))
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO))
 
-        print response.body
-        assert """<div id="chg_20" class="container">""" in response.body, 'wrong info about number of changes'
-        assert """<div class="date">commit 154: 5e204e7583b9@2010-08-10 01:18:46</div>""" in response.body , 'no info on this commit'
-        assert """Small update at simplevcs app""" in response.body, 'missing info about commit message'
-        assert """<span class="removed tooltip" title="removed: No Files">0</span>""" in response.body, 'wrong info about removed nodes'
-        assert """<span class="changed tooltip" title="changed: <br/> vcs/backends/hg.py<br/> vcs/web/simplevcs/models.py">2</span>""" in response.body, 'wrong info about changed nodes'
-        assert """<span class="added tooltip" title="added: <br/> vcs/web/simplevcs/managers.py">1</span>""" in response.body, 'wrong info about added nodes'
+        self.assertTrue("""<div id="chg_20" class="container">"""
+                        in response.body)
+        self.assertTrue("""<input class="changeset_range" id="5e204e7583b9" """
+                        """name="5e204e7583b9" type="checkbox" value="1" />"""
+                        in response.body)
+        self.assertTrue("""<span>commit 154: 5e204e7583b9@2010-08-10 """
+                        """01:18:46</span>""" in response.body)
+        self.assertTrue("""Small update at simplevcs app""" in response.body)
+
+
+        self.assertTrue("""<span id="5e204e7583b9c8e7b93a020bd036564b1e"""
+                        """731dae" class="changed_total tooltip" """
+                        """title="Affected number of files, click to """
+                        """show more details">3</span>""" in response.body)
 
         #pagination
 
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO), {'page':1})
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO), {'page':2})
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO), {'page':3})
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO), {'page':4})
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO), {'page':5})
-        response = self.app.get(url(controller='changelog', action='index', repo_name=HG_REPO), {'page':6})
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO), {'page':1})
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO), {'page':2})
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO), {'page':3})
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO), {'page':4})
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO), {'page':5})
+        response = self.app.get(url(controller='changelog', action='index',
+                                    repo_name=HG_REPO), {'page':6})
+
 
         # Test response after pagination...
-        print response.body
-        assert """<div class="date">commit 64: 46ad32a4f974@2010-04-20 00:33:21</div>"""in response.body, 'wrong info about commit 64'
-        assert """<span class="removed tooltip" title="removed: <br/> docs/api.rst">1</span>"""in response.body, 'wrong info about number of removed'
-        assert """<span class="changed tooltip" title="changed: <br/> .hgignore<br/> README.rst<br/> docs/conf.py<br/> docs/index.rst<br/> setup.py<br/> tests/test_hg.py<br/> tests/test_nodes.py<br/> vcs/__init__.py<br/> vcs/backends/__init__.py<br/> vcs/backends/base.py<br/> vcs/backends/hg.py<br/> vcs/nodes.py<br/> vcs/utils/__init__.py">13</span>"""in response.body, 'wrong info about number of changes'
-        assert """<span class="added tooltip" title="added: <br/> docs/api/backends/hg.rst<br/> docs/api/backends/index.rst<br/> docs/api/index.rst<br/> docs/api/nodes.rst<br/> docs/api/web/index.rst<br/> docs/api/web/simplevcs.rst<br/> docs/installation.rst<br/> docs/quickstart.rst<br/> setup.cfg<br/> vcs/utils/baseui_config.py<br/> vcs/utils/web.py<br/> vcs/web/__init__.py<br/> vcs/web/exceptions.py<br/> vcs/web/simplevcs/__init__.py<br/> vcs/web/simplevcs/exceptions.py<br/> vcs/web/simplevcs/middleware.py<br/> vcs/web/simplevcs/models.py<br/> vcs/web/simplevcs/settings.py<br/> vcs/web/simplevcs/utils.py<br/> vcs/web/simplevcs/views.py">20</span>"""in response.body, 'wrong info about number of added'
-        assert """<div class="message"><a href="/%s/changeset/46ad32a4f974e45472a898c6b0acb600320579b1">Merge with 2e6a2bf9356ca56df08807f4ad86d480da72a8f4</a></div>""" % HG_REPO in response.body, 'wrong info about commit 64 is a merge'
+        self.assertTrue("""<input class="changeset_range" id="46ad32a4f974" """
+                        """name="46ad32a4f974" type="checkbox" value="1" />"""
+                        in response.body)
+        self.assertTrue("""<span>commit 64: 46ad32a4f974@2010-04-20"""
+                        """ 00:33:21</span>"""in response.body)
+
+        self.assertTrue("""<span id="46ad32a4f974e45472a898c6b0acb600320"""
+                        """579b1" class="changed_total tooltip" """
+                        """title="Affected number of files, click to """
+                        """show more details">21</span>"""in response.body)
+        self.assertTrue("""<div class="message"><a href="/%s/changeset/"""
+                        """46ad32a4f974e45472a898c6b0acb600320579b1">"""
+                        """Merge with 2e6a2bf9356ca56df08807f4ad86d48"""
+                        """0da72a8f4</a></div>""" % HG_REPO in response.body)
 
 
 
--- a/rhodecode/tests/functional/test_feed.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_feed.py	Fri Oct 07 01:08:50 2011 +0200
@@ -6,10 +6,17 @@
         self.log_user()
         response = self.app.get(url(controller='feed', action='rss',
                                     repo_name=HG_REPO))
-        # Test response...
+
+
+
+        assert response.content_type == "application/rss+xml"
+        assert """<rss version="2.0">""" in response
 
     def test_atom(self):
         self.log_user()
         response = self.app.get(url(controller='feed', action='atom',
                                     repo_name=HG_REPO))
-        # Test response...
\ No newline at end of file
+
+        assert response.content_type == """application/atom+xml"""
+        assert """<?xml version="1.0" encoding="utf-8"?>""" in response
+        assert """<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us">""" in response
--- a/rhodecode/tests/functional/test_files.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_files.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,5 +1,11 @@
 from rhodecode.tests import *
 
+ARCHIVE_SPECS = {
+    '.tar.bz2': ('application/x-bzip2', 'tbz2', ''),
+    '.tar.gz': ('application/x-gzip', 'tgz', ''),
+    '.zip': ('application/zip', 'zip', ''),
+}
+
 class TestFilesController(TestController):
 
     def test_index(self):
@@ -188,3 +194,120 @@
 </optgroup>""" in response.body, 'missing or wrong history in annotation'
 
         assert """<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""" in response.body, 'missing or wrong branch info'
+
+
+
+    def test_archival(self):
+        self.log_user()
+
+        for arch_ext, info in ARCHIVE_SPECS.items():
+            fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext
+            filename = '%s-%s' % (HG_REPO, fname)
+
+            response = self.app.get(url(controller='files', action='archivefile',
+                                        repo_name=HG_REPO,
+                                        fname=fname))
+
+            assert response.status == '200 OK', 'wrong response code'
+            assert response.response._headers.items() == [('Pragma', 'no-cache'),
+                                                  ('Cache-Control', 'no-cache'),
+                                                  ('Content-Type', '%s; charset=utf-8' % info[0]),
+                                                  ('Content-Disposition', 'attachment; filename=%s' % filename), ], 'wrong headers'
+
+    def test_archival_wrong_ext(self):
+        self.log_user()
+
+        for arch_ext in ['tar', 'rar', 'x', '..ax', '.zipz']:
+            fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext
+
+            response = self.app.get(url(controller='files', action='archivefile',
+                                        repo_name=HG_REPO,
+                                        fname=fname))
+            assert 'Unknown archive type' in response.body
+
+
+    def test_archival_wrong_revision(self):
+        self.log_user()
+
+        for rev in ['00x000000', 'tar', 'wrong', '@##$@$424213232', '232dffcd']:
+            fname = '%s.zip' % rev
+
+            response = self.app.get(url(controller='files', action='archivefile',
+                                        repo_name=HG_REPO,
+                                        fname=fname))
+            assert 'Unknown revision' in response.body
+
+    #==========================================================================
+    # RAW FILE
+    #==========================================================================
+    def test_raw_file_ok(self):
+        self.log_user()
+        response = self.app.get(url(controller='files', action='rawfile',
+                                    repo_name=HG_REPO,
+                                    revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
+                                    f_path='vcs/nodes.py'))
+
+        assert response.content_disposition == "attachment; filename=nodes.py"
+        assert response.content_type == "text/x-python"
+
+    def test_raw_file_wrong_cs(self):
+        self.log_user()
+        rev = u'ERRORce30c96924232dffcd24178a07ffeb5dfc'
+        f_path = 'vcs/nodes.py'
+
+        response = self.app.get(url(controller='files', action='rawfile',
+                                    repo_name=HG_REPO,
+                                    revision=rev,
+                                    f_path=f_path))
+
+        assert """Revision %r does not exist for this repository""" % (rev) in response.session['flash'][0][1], 'No flash message'
+        assert """%s""" % (HG_REPO) in response.session['flash'][0][1], 'No flash message'
+
+
+
+    def test_raw_file_wrong_f_path(self):
+        self.log_user()
+        rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
+        f_path = 'vcs/ERRORnodes.py'
+        response = self.app.get(url(controller='files', action='rawfile',
+                                    repo_name=HG_REPO,
+                                    revision=rev,
+                                    f_path=f_path))
+        assert "There is no file nor directory at the given path: %r at revision %r" % (f_path, rev[:12]) in response.session['flash'][0][1], 'No flash message'
+
+    #==========================================================================
+    # RAW RESPONSE - PLAIN
+    #==========================================================================
+    def test_raw_ok(self):
+        self.log_user()
+        response = self.app.get(url(controller='files', action='raw',
+                                    repo_name=HG_REPO,
+                                    revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
+                                    f_path='vcs/nodes.py'))
+
+        assert response.content_type == "text/plain"
+
+    def test_raw_wrong_cs(self):
+        self.log_user()
+        rev = u'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
+        f_path = 'vcs/nodes.py'
+
+        response = self.app.get(url(controller='files', action='raw',
+                                    repo_name=HG_REPO,
+                                    revision=rev,
+                                    f_path=f_path))
+
+        assert """Revision %r does not exist for this repository""" % (rev) in response.session['flash'][0][1], 'No flash message'
+        assert """%s""" % (HG_REPO) in response.session['flash'][0][1], 'No flash message'
+
+
+    def test_raw_wrong_f_path(self):
+        self.log_user()
+        rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
+        f_path = 'vcs/ERRORnodes.py'
+        response = self.app.get(url(controller='files', action='raw',
+                                    repo_name=HG_REPO,
+                                    revision=rev,
+                                    f_path=f_path))
+
+        assert "There is no file nor directory at the given path: %r at revision %r" % (f_path, rev[:12]) in response.session['flash'][0][1], 'No flash message'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/functional/test_followers.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,13 @@
+from rhodecode.tests import *
+
+class TestFollowersController(TestController):
+
+    def test_index(self):
+        self.log_user()
+        repo_name = HG_REPO
+        response = self.app.get(url(controller='followers',
+                                    action='followers',
+                                    repo_name=repo_name))
+
+        self.assertTrue("""test_admin""" in response.body)
+        self.assertTrue("""Started following""" in response.body)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/functional/test_forks.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,41 @@
+from rhodecode.tests import *
+
+from rhodecode.model.db import Repository
+
+class TestForksController(TestController):
+
+    def test_index(self):
+        self.log_user()
+        repo_name = HG_REPO
+        response = self.app.get(url(controller='forks', action='forks',
+                                    repo_name=repo_name))
+
+        self.assertTrue("""There are no forks yet""" in response.body)
+
+
+    def test_index_with_fork(self):
+        self.log_user()
+
+        # create a fork
+        fork_name = HG_FORK
+        description = 'fork of vcs test'
+        repo_name = HG_REPO
+        response = self.app.post(url(controller='settings',
+                                     action='fork_create',
+                                    repo_name=repo_name),
+                                    {'fork_name':fork_name,
+                                     'repo_type':'hg',
+                                     'description':description,
+                                     'private':'False'})
+
+        response = self.app.get(url(controller='forks', action='forks',
+                                    repo_name=repo_name))
+
+
+        self.assertTrue("""<a href="/%s/summary">"""
+                         """vcs_test_hg_fork</a>""" % fork_name
+                         in response.body)
+
+        #remove this fork
+        response = self.app.delete(url('repo', repo_name=fork_name))
+
--- a/rhodecode/tests/functional/test_home.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_home.py	Fri Oct 07 01:08:50 2011 +0200
@@ -6,6 +6,17 @@
         self.log_user()
         response = self.app.get(url(controller='home', action='index'))
         #if global permission is set
-        assert 'ADD NEW REPOSITORY' in response.body, 'Wrong main page'
-        assert 'href="/%s/summary"' % HG_REPO in response.body, ' mising repository in list'
+        self.assertTrue('ADD NEW REPOSITORY' in response.body)
+        self.assertTrue('href="/%s/summary"' % HG_REPO in response.body)
         # Test response...
+
+        self.assertTrue("""<img class="icon" title="Mercurial repository" """
+                        """alt="Mercurial repository" src="/images/icons/hg"""
+                        """icon.png"/>""" in response.body)
+        self.assertTrue("""<img class="icon" title="public repository" """
+                        """alt="public repository" src="/images/icons/lock_"""
+                        """open.png"/>""" in response.body)
+        
+        self.assertTrue("""<a title="Marcin Kuzminski &lt;marcin@python-works.com&gt;
+merge" class="tooltip" href="/vcs_test_hg/changeset/27cd5cce30c96924232dffcd24178a07ffeb5dfc">r173:27cd5cce30c9</a>"""
+                            in response.body)
--- a/rhodecode/tests/functional/test_journal.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_journal.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,7 +1,42 @@
 from rhodecode.tests import *
+from rhodecode.model.db import UserFollowing, User, Repository
+from rhodecode.lib.helpers import get_token
+import datetime
 
 class TestJournalController(TestController):
 
     def test_index(self):
+        self.log_user()
         response = self.app.get(url(controller='journal', action='index'))
+
         # Test response...
+        assert """ <span id="follow_toggle_1" class="following" title="Stop following this repository""" in response.body, 'no info about stop follwoing repo id 1'
+
+        assert """<div class="journal_day">%s</div>""" % datetime.date.today() in response.body, 'no info about action journal day'
+
+    def test_stop_following_repository(self):
+        session = self.log_user()
+#        usr = self.sa.query(User).filter(User.username == 'test_admin').one()
+#        repo = self.sa.query(Repository).filter(Repository.repo_name == HG_REPO).one()
+#
+#        followings = self.sa.query(UserFollowing)\
+#            .filter(UserFollowing.user == usr)\
+#            .filter(UserFollowing.follows_repository == repo).all()
+#
+#        assert len(followings) == 1, 'Not following any repository'
+#
+#        response = self.app.post(url(controller='journal',
+#                                     action='toggle_following'),
+#                                     {'auth_token':get_token(session),
+#                                      'follows_repo_id':repo.repo_id})
+
+    def test_start_following_repository(self):
+        self.log_user()
+        response = self.app.get(url(controller='journal', action='index'),)
+
+
+    def __add_repo(self):
+        pass
+
+    def __remove_repo(self):
+        pass
--- a/rhodecode/tests/functional/test_login.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_login.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 from rhodecode.tests import *
 from rhodecode.model.db import User
+from rhodecode.lib import generate_api_key
 from rhodecode.lib.auth import check_password
 
 
@@ -8,64 +9,67 @@
 
     def test_index(self):
         response = self.app.get(url(controller='login', action='index'))
-        assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
+        self.assertEqual(response.status, '200 OK')
         # Test response...
 
     def test_login_admin_ok(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username':'test_admin',
                                   'password':'test12'})
-        assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
-        assert response.session['rhodecode_user'].username == 'test_admin', 'wrong logged in user'
+        self.assertEqual(response.status, '302 Found')
+        self.assertEqual(response.session['rhodecode_user'].username ,
+                         'test_admin')
         response = response.follow()
-        assert '%s repository' % HG_REPO in response.body
+        self.assertTrue('%s repository' % HG_REPO in response.body)
 
     def test_login_regular_ok(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username':'test_regular',
                                   'password':'test12'})
-        print response
-        assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
-        assert response.session['rhodecode_user'].username == 'test_regular', 'wrong logged in user'
+
+        self.assertEqual(response.status, '302 Found')
+        self.assertEqual(response.session['rhodecode_user'].username ,
+                         'test_regular')
         response = response.follow()
-        assert '%s repository' % HG_REPO in response.body
-        assert '<a title="Admin" href="/_admin">' not in response.body
+        self.assertTrue('%s repository' % HG_REPO in response.body)
+        self.assertTrue('<a title="Admin" href="/_admin">' not in response.body)
 
     def test_login_ok_came_from(self):
         test_came_from = '/_admin/users'
-        response = self.app.post(url(controller='login', action='index', came_from=test_came_from),
+        response = self.app.post(url(controller='login', action='index',
+                                     came_from=test_came_from),
                                  {'username':'test_admin',
                                   'password':'test12'})
-        assert response.status == '302 Found', 'Wrong response code from came from redirection'
+        self.assertEqual(response.status, '302 Found')
         response = response.follow()
 
-        assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
-        assert 'Users administration' in response.body, 'No proper title in response'
+        self.assertEqual(response.status, '200 OK')
+        self.assertTrue('Users administration' in response.body)
 
 
     def test_login_short_password(self):
         response = self.app.post(url(controller='login', action='index'),
-                                 {'username':'error',
-                                  'password':'test'})
-        assert response.status == '200 OK', 'Wrong response from login page'
-        print response.body
-        assert 'Enter 6 characters or more' in response.body, 'No error password message in response'
+                                 {'username':'test_admin',
+                                  'password':'as'})
+        self.assertEqual(response.status, '200 OK')
+
+        self.assertTrue('Enter 3 characters or more' in response.body)
 
     def test_login_wrong_username_password(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username':'error',
                                   'password':'test12'})
-        assert response.status == '200 OK', 'Wrong response from login page'
+        self.assertEqual(response.status , '200 OK')
 
-        assert 'invalid user name' in response.body, 'No error username message in response'
-        assert 'invalid password' in response.body, 'No error password message in response'
+        self.assertTrue('invalid user name' in response.body)
+        self.assertTrue('invalid password' in response.body)
 
     #==========================================================================
     # REGISTRATIONS
     #==========================================================================
     def test_register(self):
         response = self.app.get(url(controller='login', action='register'))
-        assert 'Sign Up to RhodeCode' in response.body, 'wrong page for user registration'
+        self.assertTrue('Sign Up to RhodeCode' in response.body)
 
     def test_register_err_same_username(self):
         response = self.app.post(url(controller='login', action='register'),
@@ -76,8 +80,8 @@
                                              'name':'test',
                                              'lastname':'test'})
 
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
-        assert 'This username already exists' in response.body
+        self.assertEqual(response.status , '200 OK')
+        self.assertTrue('This username already exists' in response.body)
 
     def test_register_err_same_email(self):
         response = self.app.post(url(controller='login', action='register'),
@@ -88,7 +92,7 @@
                                              'name':'test',
                                              'lastname':'test'})
 
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '200 OK')
         assert 'This e-mail address is already taken' in response.body
 
     def test_register_err_same_email_case_sensitive(self):
@@ -99,7 +103,7 @@
                                              'email':'TesT_Admin@mail.COM',
                                              'name':'test',
                                              'lastname':'test'})
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '200 OK')
         assert 'This e-mail address is already taken' in response.body
 
     def test_register_err_wrong_data(self):
@@ -110,7 +114,7 @@
                                              'email':'goodmailm',
                                              'name':'test',
                                              'lastname':'test'})
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '200 OK')
         assert 'An email address must contain a single @' in response.body
         assert 'Enter a value 6 characters long or more' in response.body
 
@@ -124,8 +128,7 @@
                                              'name':'test',
                                              'lastname':'test'})
 
-        print response.body
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '200 OK')
         assert 'An email address must contain a single @' in response.body
         assert ('Username may only contain '
                 'alphanumeric characters underscores, '
@@ -141,7 +144,7 @@
                                              'name':'test',
                                              'lastname':'test'})
 
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '200 OK')
         assert 'An email address must contain a single @' in response.body
         assert 'This username already exists' in response.body
 
@@ -156,8 +159,7 @@
                                              'name':'test',
                                              'lastname':'test'})
 
-        print response.body
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '200 OK')
         assert 'Invalid characters in password' in response.body
 
 
@@ -170,9 +172,8 @@
                                              'name':'test',
                                              'lastname':'test'})
 
-        assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
-        print response.body
-        assert 'Password do not match' in response.body
+        self.assertEqual(response.status , '200 OK')
+        assert 'Passwords do not match' in response.body
 
     def test_register_ok(self):
         username = 'test_regular4'
@@ -188,7 +189,7 @@
                                              'email':email,
                                              'name':name,
                                              'lastname':lastname})
-        assert response.status == '302 Found', 'Wrong response from register page got %s' % response.status
+        self.assertEqual(response.status , '302 Found')
         assert 'You have successfully registered into rhodecode' in response.session['flash'][0], 'No flash message about user registration'
 
         ret = self.sa.query(User).filter(User.username == 'test_regular4').one()
@@ -206,8 +207,9 @@
         assert "This e-mail address doesn't exist" in response.body, 'Missing error message about wrong email'
 
     def test_forgot_password(self):
-        response = self.app.get(url(controller='login', action='password_reset'))
-        assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
+        response = self.app.get(url(controller='login',
+                                    action='password_reset'))
+        self.assertEqual(response.status , '200 OK')
 
         username = 'test_password_reset_1'
         password = 'qweqwe'
@@ -215,19 +217,45 @@
         name = 'passwd'
         lastname = 'reset'
 
-        response = self.app.post(url(controller='login', action='register'),
-                                            {'username':username,
-                                             'password':password,
-                                             'password_confirmation':password,
-                                             'email':email,
-                                             'name':name,
-                                             'lastname':lastname})
-        #register new user for email test
-        response = self.app.post(url(controller='login', action='password_reset'),
-                                            {'email':email, })
-        print response.session['flash']
-        assert 'You have successfully registered into rhodecode' in response.session['flash'][0], 'No flash message about user registration'
-        assert 'Your new password was sent' in response.session['flash'][1], 'No flash message about password reset'
+        new = User()
+        new.username = username
+        new.password = password
+        new.email = email
+        new.name = name
+        new.lastname = lastname
+        new.api_key = generate_api_key(username)
+        self.sa.add(new)
+        self.sa.commit()
+
+        response = self.app.post(url(controller='login',
+                                     action='password_reset'),
+                                 {'email':email, })
+
+        self.checkSessionFlash(response, 'Your password reset link was sent')
+
+        response = response.follow()
+
+        # BAD KEY
 
+        key = "bad"
+        response = self.app.get(url(controller='login',
+                                    action='password_reset_confirmation',
+                                    key=key))
+        self.assertEqual(response.status, '302 Found')
+        self.assertTrue(response.location.endswith(url('reset_password')))
 
+        # GOOD KEY
 
+        key = User.by_username(username).api_key
+
+        response = self.app.get(url(controller='login',
+                                    action='password_reset_confirmation',
+                                    key=key))
+        self.assertEqual(response.status, '302 Found')
+        self.assertTrue(response.location.endswith(url('login_home')))
+
+        self.checkSessionFlash(response,
+                               ('Your password reset was successful, '
+                                'new password has been sent to your email'))
+
+        response = response.follow()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/functional/test_repos_groups.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,43 @@
+from rhodecode.tests import *
+
+class TestReposGroupsController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url('repos_groups'))
+        # Test response...
+
+    def test_index_as_xml(self):
+        response = self.app.get(url('formatted_repos_groups', format='xml'))
+
+    def test_create(self):
+        response = self.app.post(url('repos_groups'))
+
+    def test_new(self):
+        response = self.app.get(url('new_repos_group'))
+
+    def test_new_as_xml(self):
+        response = self.app.get(url('formatted_new_repos_group', format='xml'))
+
+    def test_update(self):
+        response = self.app.put(url('repos_group', id=1))
+
+    def test_update_browser_fakeout(self):
+        response = self.app.post(url('repos_group', id=1), params=dict(_method='put'))
+
+    def test_delete(self):
+        response = self.app.delete(url('repos_group', id=1))
+
+    def test_delete_browser_fakeout(self):
+        response = self.app.post(url('repos_group', id=1), params=dict(_method='delete'))
+
+    def test_show(self):
+        response = self.app.get(url('repos_group', id=1))
+
+    def test_show_as_xml(self):
+        response = self.app.get(url('formatted_repos_group', id=1, format='xml'))
+
+    def test_edit(self):
+        response = self.app.get(url('edit_repos_group', id=1))
+
+    def test_edit_as_xml(self):
+        response = self.app.get(url('formatted_edit_repos_group', id=1, format='xml'))
--- a/rhodecode/tests/functional/test_search.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_search.py	Fri Oct 07 01:08:50 2011 +0200
@@ -7,8 +7,9 @@
     def test_index(self):
         self.log_user()
         response = self.app.get(url(controller='search', action='index'))
-        print response.body
-        assert 'class="small" id="q" name="q" type="text"' in response.body, 'Search box content error'
+
+        self.assertTrue('class="small" id="q" name="q" type="text"' in
+                        response.body)
         # Test response...
 
     def test_empty_search(self):
@@ -16,21 +17,21 @@
             raise SkipTest('skipped due to existing index')
         else:
             self.log_user()
-            response = self.app.get(url(controller='search', action='index'), {'q':HG_REPO})
-            assert 'There is no index to search in. Please run whoosh indexer' in response.body, 'No error message about empty index'
+            response = self.app.get(url(controller='search', action='index'),
+                                    {'q':HG_REPO})
+            self.assertTrue('There is no index to search in. '
+                            'Please run whoosh indexer' in response.body)
 
     def test_normal_search(self):
         self.log_user()
-        response = self.app.get(url(controller='search', action='index'), {'q':'def repo'})
-        print response.body
-        assert '10 results' in response.body, 'no message about proper search results'
-        assert 'Permission denied' not in response.body, 'Wrong permissions settings for that repo and user'
-
+        response = self.app.get(url(controller='search', action='index'),
+                                {'q':'def repo'})
+        self.assertTrue('10 results' in response.body)
+        self.assertTrue('Permission denied' not in response.body)
 
     def test_repo_search(self):
         self.log_user()
-        response = self.app.get(url(controller='search', action='index'), {'q':'repository:%s def test' % HG_REPO})
-        print response.body
-        assert '4 results' in response.body, 'no message about proper search results'
-        assert 'Permission denied' not in response.body, 'Wrong permissions settings for that repo and user'
-
+        response = self.app.get(url(controller='search', action='index'),
+                                {'q':'repository:%s def test' % HG_REPO})
+        self.assertTrue('4 results' in response.body)
+        self.assertTrue('Permission denied' not in response.body)
--- a/rhodecode/tests/functional/test_settings.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_settings.py	Fri Oct 07 01:08:50 2011 +0200
@@ -47,4 +47,3 @@
                                     repo_name=fork_name))
 
         assert 'Fork of %s' % repo_name in response.body, 'no message about that this repo is a fork'
-
--- a/rhodecode/tests/functional/test_summary.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_summary.py	Fri Oct 07 01:08:50 2011 +0200
@@ -1,19 +1,47 @@
 from rhodecode.tests import *
+from rhodecode.model.db import Repository
+from rhodecode.lib.utils import invalidate_cache
 
 class TestSummaryController(TestController):
 
     def test_index(self):
         self.log_user()
-        response = self.app.get(url(controller='summary', action='index', repo_name=HG_REPO))
+        response = self.app.get(url(controller='summary',
+                                    action='index', repo_name=HG_REPO))
 
         #repo type
-        assert """<img style="margin-bottom:2px" class="icon" title="Mercurial repository" alt="Mercurial repository" src="/images/icons/hgicon.png"/>""" in response.body
-        assert """<img style="margin-bottom:2px" class="icon" title="public repository" alt="public repository" src="/images/icons/lock_open.png"/>""" in response.body
+        self.assertTrue("""<img style="margin-bottom:2px" class="icon" """
+                        """title="Mercurial repository" alt="Mercurial """
+                        """repository" src="/images/icons/hgicon.png"/>"""
+                        in response.body)
+        self.assertTrue("""<img style="margin-bottom:2px" class="icon" """
+                        """title="public repository" alt="public """
+                        """repository" src="/images/icons/lock_open.png"/>"""
+                        in response.body)
 
         #codes stats
-        assert """var data = {"Python": 42, "Rst": 11, "Bash": 2, "Makefile": 1, "Batch": 1, "Ini": 1, "Css": 1};""" in response.body, 'wrong info about % of codes stats'
+        self._enable_stats()
+
+
+        invalidate_cache('get_repo_cached_%s' % HG_REPO)
+        response = self.app.get(url(controller='summary', action='index',
+                                    repo_name=HG_REPO))
+
+        self.assertTrue("""var data = {"py": {"count": 42, "desc": """
+                        """["Python"]}, "rst": {"count": 11, "desc": """
+                        """["Rst"]}, "sh": {"count": 2, "desc": ["Bash"]}, """
+                        """"makefile": {"count": 1, "desc": ["Makefile", """
+                        """"Makefile"]}, "cfg": {"count": 1, "desc": ["Ini"]},"""
+                        """ "css": {"count": 1, "desc": ["Css"]}, "bat": """
+                        """{"count": 1, "desc": ["Batch"]}};"""
+                        in response.body)
 
         # clone url...
-        assert """<input type="text" id="clone_url" readonly="readonly" value="hg clone http://test_admin@localhost:80/%s" size="70"/>""" % HG_REPO in response.body
+        self.assertTrue("""<input type="text" id="clone_url" readonly="readonly" value="hg clone http://test_admin@localhost:80/%s" size="70"/>""" % HG_REPO in response.body)
 
 
+    def _enable_stats(self):
+        r = Repository.by_repo_name(HG_REPO)
+        r.enable_statistics = True
+        self.sa.add(r)
+        self.sa.commit()
--- a/rhodecode/tests/functional/test_tags.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/functional/test_tags.py	Fri Oct 07 01:08:50 2011 +0200
@@ -5,9 +5,9 @@
     def test_index(self):
         self.log_user()
         response = self.app.get(url(controller='tags', action='index', repo_name=HG_REPO))
-        assert """<a href="/%s/changeset/27cd5cce30c96924232dffcd24178a07ffeb5dfc">tip</a>""" % HG_REPO, 'wrong info about tip tag'
-        assert """<a href="/%s/changeset/fd4bdb5e9b2a29b4393a4ac6caef48c17ee1a200">0.1.4</a>""" % HG_REPO, 'wrong info about 0.1.4 tag'
-        assert """<a href="/%s/changeset/17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">0.1.3</a>""" % HG_REPO, 'wrong info about 0.1.3 tag'
-        assert """<a href="/%s/changeset/a7e60bff65d57ac3a1a1ce3b12a70f8a9e8a7720">0.1.2</a>""" % HG_REPO, 'wrong info about 0.1.2 tag'
-        assert """<a href="/%s/changeset/eb3a60fc964309c1a318b8dfe26aa2d1586c85ae">0.1.1</a>""" % HG_REPO, 'wrong info about 0.1.1 tag'
+        assert """<a href="/%s/changeset/27cd5cce30c96924232dffcd24178a07ffeb5dfc">tip</a>""" % HG_REPO in response.body, 'wrong info about tip tag'
+        assert """<a href="/%s/changeset/fd4bdb5e9b2a29b4393a4ac6caef48c17ee1a200">0.1.4</a>""" % HG_REPO in response.body, 'wrong info about 0.1.4 tag'
+        assert """<a href="/%s/changeset/17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">0.1.3</a>""" % HG_REPO in response.body, 'wrong info about 0.1.3 tag'
+        assert """<a href="/%s/changeset/a7e60bff65d57ac3a1a1ce3b12a70f8a9e8a7720">0.1.2</a>""" % HG_REPO in response.body, 'wrong info about 0.1.2 tag'
+        assert """<a href="/%s/changeset/eb3a60fc964309c1a318b8dfe26aa2d1586c85ae">0.1.1</a>""" % HG_REPO in response.body, 'wrong info about 0.1.1 tag'
         # Test response...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/mem_watch	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,1 @@
+ps -eo size,pid,user,command --sort -size | awk '{ hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }'|grep paster
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/rhodecode_crawler.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.tests.test_crawer
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test for crawling a project for memory usage
+    This should be runned just as regular script together
+    with a watch script that will show memory usage.
+    
+    watch -n1 ./rhodecode/tests/mem_watch
+
+    :created_on: Apr 21, 2010
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+import cookielib
+import urllib
+import urllib2
+import vcs
+import time
+
+from os.path import join as jn
+
+
+BASE_URI = 'http://127.0.0.1:5000/%s'
+PROJECT = 'CPython'
+PROJECT_PATH = jn('/', 'home', 'marcink', 'hg_repos')
+
+
+cj = cookielib.FileCookieJar('/tmp/rc_test_cookie.txt')
+o = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
+o.addheaders = [
+                     ('User-agent', 'rhodecode-crawler'),
+                     ('Accept-Language', 'en - us, en;q = 0.5')
+                    ]
+
+urllib2.install_opener(o)
+
+
+
+def test_changelog_walk(pages=100):
+    total_time = 0
+    for i in range(1, pages):
+
+        page = '/'.join((PROJECT, 'changelog',))
+
+        full_uri = (BASE_URI % page) + '?' + urllib.urlencode({'page':i})
+        s = time.time()
+        f = o.open(full_uri)
+        size = len(f.read())
+        e = time.time() - s
+        total_time += e
+        print 'visited %s size:%s req:%s ms' % (full_uri, size, e)
+
+
+    print 'total_time', total_time
+    print 'average on req', total_time / float(pages)
+
+
+def test_changeset_walk(limit=None):
+    print 'processing', jn(PROJECT_PATH, PROJECT)
+    total_time = 0
+
+    repo = vcs.get_repo(jn(PROJECT_PATH, PROJECT))
+    cnt = 0
+    for i in repo:
+        cnt += 1
+        raw_cs = '/'.join((PROJECT, 'changeset', i.raw_id))
+        if limit and limit == cnt:
+            break
+
+        full_uri = (BASE_URI % raw_cs)
+        s = time.time()
+        f = o.open(full_uri)
+        size = len(f.read())
+        e = time.time() - s
+        total_time += e
+        print '%s visited %s\%s size:%s req:%s ms' % (cnt, full_uri, i, size, e)
+
+    print 'total_time', total_time
+    print 'average on req', total_time / float(cnt)
+
+
+def test_files_walk(limit=100):
+    print 'processing', jn(PROJECT_PATH, PROJECT)
+    total_time = 0
+
+    repo = vcs.get_repo(jn(PROJECT_PATH, PROJECT))
+
+    from rhodecode.lib.oset import OrderedSet
+
+    paths_ = OrderedSet([''])
+    try:
+        tip = repo.get_changeset('tip')
+        for topnode, dirs, files in tip.walk('/'):
+
+            for dir in dirs:
+                paths_.add(dir.path)
+                for f in dir:
+                    paths_.add(f.path)
+
+            for f in files:
+                paths_.add(f.path)
+
+    except vcs.exception.RepositoryError, e:
+        pass
+
+    cnt = 0
+    for f in paths_:
+        cnt += 1
+        if limit and limit == cnt:
+            break
+
+        file_path = '/'.join((PROJECT, 'files', 'tip', f))
+
+        full_uri = (BASE_URI % file_path)
+        s = time.time()
+        f = o.open(full_uri)
+        size = len(f.read())
+        e = time.time() - s
+        total_time += e
+        print '%s visited %s size:%s req:%s ms' % (cnt, full_uri, size, e)
+
+    print 'total_time', total_time
+    print 'average on req', total_time / float(cnt)
+
+
+
+test_changelog_walk(40)
+time.sleep(2)
+test_changeset_walk(limit=100)
+time.sleep(2)
+test_files_walk(100)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/test_hg_operations.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,379 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.tests.test_hg_operations
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Test suite for making push/pull operations
+
+    :created_on: Dec 30, 2010
+    :copyright: (c) 2010 by marcink.
+    :license: LICENSE_NAME, see LICENSE_FILE for more details.
+"""
+
+import os
+import time
+import sys
+import shutil
+import logging
+
+from os.path import join as jn
+from os.path import dirname as dn
+
+from tempfile import _RandomNameSequence
+from subprocess import Popen, PIPE
+
+from paste.deploy import appconfig
+from pylons import config
+from sqlalchemy import engine_from_config
+
+from rhodecode.lib.utils import add_cache
+from rhodecode.model import init_model
+from rhodecode.model import meta
+from rhodecode.model.db import User, Repository
+from rhodecode.lib.auth import get_crypt_password
+
+from rhodecode.tests import TESTS_TMP_PATH, NEW_HG_REPO, HG_REPO
+from rhodecode.config.environment import load_environment
+
+rel_path = dn(dn(dn(os.path.abspath(__file__))))
+conf = appconfig('config:development.ini', relative_to=rel_path)
+load_environment(conf.global_conf, conf.local_conf)
+
+add_cache(conf)
+
+USER = 'test_admin'
+PASS = 'test12'
+HOST = '127.0.0.1:5000'
+DEBUG = bool(int(sys.argv[1]))
+print 'DEBUG:',DEBUG
+log = logging.getLogger(__name__)
+
+
+class Command(object):
+
+    def __init__(self, cwd):
+        self.cwd = cwd
+
+    def execute(self, cmd, *args):
+        """Runs command on the system with given ``args``.
+        """
+
+        command = cmd + ' ' + ' '.join(args)
+        log.debug('Executing %s' % command)
+        if DEBUG:
+            print command
+        p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd)
+        stdout, stderr = p.communicate()
+        if DEBUG:
+            print stdout, stderr
+        return stdout, stderr
+
+
+def test_wrapp(func):
+    
+    def __wrapp(*args,**kwargs):
+        print '###%s###' %func.__name__
+        try:
+            res = func(*args,**kwargs)
+        except:
+            print '--%s failed--' % func.__name__
+            return
+        print 'ok'
+        return res
+    return __wrapp
+
+def get_session():
+    engine = engine_from_config(conf, 'sqlalchemy.db1.')
+    init_model(engine)
+    sa = meta.Session
+    return sa
+
+
+def create_test_user(force=True):
+    print 'creating test user'
+    sa = get_session()
+
+    user = sa.query(User).filter(User.username == USER).scalar()
+
+    if force and user is not None:
+        print 'removing current user'
+        for repo in sa.query(Repository).filter(Repository.user == user).all():
+            sa.delete(repo)
+        sa.delete(user)
+        sa.commit()
+
+    if user is None or force:
+        print 'creating new one'
+        new_usr = User()
+        new_usr.username = USER
+        new_usr.password = get_crypt_password(PASS)
+        new_usr.email = 'mail@mail.com'
+        new_usr.name = 'test'
+        new_usr.lastname = 'lasttestname'
+        new_usr.active = True
+        new_usr.admin = True
+        sa.add(new_usr)
+        sa.commit()
+
+    print 'done'
+
+
+def create_test_repo(force=True):
+    from rhodecode.model.repo import RepoModel
+    sa = get_session()
+
+    user = sa.query(User).filter(User.username == USER).scalar()
+    if user is None:
+        raise Exception('user not found')
+
+
+    repo = sa.query(Repository).filter(Repository.repo_name == HG_REPO).scalar()
+
+    if repo is None:
+        print 'repo not found creating'
+
+        form_data = {'repo_name':HG_REPO,
+                     'repo_type':'hg',
+                     'private':False,
+                     'clone_uri':'' }
+        rm = RepoModel(sa)
+        rm.base_path = '/home/hg'
+        rm.create(form_data, user)
+
+
+def set_anonymous_access(enable=True):
+    sa = get_session()
+    user = sa.query(User).filter(User.username == 'default').one()
+    user.active = enable
+    sa.add(user)
+    sa.commit()
+    sa.remove()
+    
+    print 'anonymous access is now:',enable
+
+
+def get_anonymous_access():
+    sa = get_session()
+    obj1 = sa.query(User).filter(User.username == 'default').one()
+    sa.expire(obj1)
+    return obj1.active
+
+
+#==============================================================================
+# TESTS
+#==============================================================================
+@test_wrapp
+def test_clone_with_credentials(no_errors=False):
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+
+    try:
+        shutil.rmtree(path, ignore_errors=True)
+        os.makedirs(path)
+        #print 'made dirs %s' % jn(path)
+    except OSError:
+        raise
+
+    print 'checking if anonymous access is enabled'
+    anonymous_access = get_anonymous_access()
+    if anonymous_access:
+        print 'enabled, disabling it '
+        set_anonymous_access(enable=False)
+        time.sleep(1)
+        
+    clone_url = 'http://%(user)s:%(pass)s@%(host)s/%(cloned_repo)s %(dest)s' % \
+                  {'user':USER,
+                   'pass':PASS,
+                   'host':HOST,
+                   'cloned_repo':HG_REPO,
+                   'dest':path}
+
+    stdout, stderr = Command(cwd).execute('hg clone', clone_url)
+
+    if no_errors is False:
+        assert """adding file changes""" in stdout, 'no messages about cloning'
+        assert """abort""" not in stderr , 'got error from clone'
+
+
+@test_wrapp
+def test_clone_anonymous():
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+
+    try:
+        shutil.rmtree(path, ignore_errors=True)
+        os.makedirs(path)
+        #print 'made dirs %s' % jn(path)
+    except OSError:
+        raise
+
+
+    print 'checking if anonymous access is enabled'
+    anonymous_access = get_anonymous_access()
+    if not anonymous_access:
+        print 'not enabled, enabling it '
+        set_anonymous_access(enable=True)
+        time.sleep(1)
+        
+    clone_url = 'http://%(host)s/%(cloned_repo)s %(dest)s' % \
+                  {'user':USER,
+                   'pass':PASS,
+                   'host':HOST,
+                   'cloned_repo':HG_REPO,
+                   'dest':path}
+
+    stdout, stderr = Command(cwd).execute('hg clone', clone_url)
+
+    assert """adding file changes""" in stdout, 'no messages about cloning'
+    assert """abort""" not in stderr , 'got error from clone'
+
+    #disable if it was enabled
+    if not anonymous_access:
+        print 'disabling anonymous access'
+        set_anonymous_access(enable=False)
+
+@test_wrapp
+def test_clone_wrong_credentials():
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+
+    try:
+        shutil.rmtree(path, ignore_errors=True)
+        os.makedirs(path)
+        #print 'made dirs %s' % jn(path)
+    except OSError:
+        raise
+
+    print 'checking if anonymous access is enabled'
+    anonymous_access = get_anonymous_access()
+    if anonymous_access:
+        print 'enabled, disabling it '
+        set_anonymous_access(enable=False)
+        
+    clone_url = 'http://%(user)s:%(pass)s@%(host)s/%(cloned_repo)s %(dest)s' % \
+                  {'user':USER + 'error',
+                   'pass':PASS,
+                   'host':HOST,
+                   'cloned_repo':HG_REPO,
+                   'dest':path}
+
+    stdout, stderr = Command(cwd).execute('hg clone', clone_url)
+
+    if not """abort: authorization failed"""  in stderr:
+        raise Exception('Failure')    
+
+@test_wrapp
+def test_pull():
+    pass
+
+@test_wrapp
+def test_push_modify_file(f_name='setup.py'):
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+    modified_file = jn(TESTS_TMP_PATH, HG_REPO, f_name)
+    for i in xrange(5):
+        cmd = """echo 'added_line%s' >> %s""" % (i, modified_file)
+        Command(cwd).execute(cmd)
+
+        cmd = """hg ci -m 'changed file %s' %s """ % (i, modified_file)
+        Command(cwd).execute(cmd)
+
+    Command(cwd).execute('hg push %s' % jn(TESTS_TMP_PATH, HG_REPO))
+
+@test_wrapp
+def test_push_new_file(commits=15, with_clone=True):
+
+    if with_clone:
+        test_clone_with_credentials(no_errors=True)
+
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+    added_file = jn(path, '%ssetupążźć.py' % _RandomNameSequence().next())
+
+    Command(cwd).execute('touch %s' % added_file)
+
+    Command(cwd).execute('hg add %s' % added_file)
+
+    for i in xrange(commits):
+        cmd = """echo 'added_line%s' >> %s""" % (i, added_file)
+        Command(cwd).execute(cmd)
+
+        cmd = """hg ci -m 'commited new %s' -u '%s' %s """ % (i,
+                                'Marcin Kuźminski <marcin@python-blog.com>',
+                                added_file)
+        Command(cwd).execute(cmd)
+
+    push_url = 'http://%(user)s:%(pass)s@%(host)s/%(cloned_repo)s' % \
+                  {'user':USER,
+                   'pass':PASS,
+                   'host':HOST,
+                   'cloned_repo':HG_REPO,
+                   'dest':jn(TESTS_TMP_PATH, HG_REPO)}
+
+    Command(cwd).execute('hg push --verbose --debug %s' % push_url)
+
+@test_wrapp
+def test_push_wrong_credentials():
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+    clone_url = 'http://%(user)s:%(pass)s@%(host)s/%(cloned_repo)s' % \
+                  {'user':USER + 'xxx',
+                   'pass':PASS,
+                   'host':HOST,
+                   'cloned_repo':HG_REPO,
+                   'dest':jn(TESTS_TMP_PATH, HG_REPO)}
+
+    modified_file = jn(TESTS_TMP_PATH, HG_REPO, 'setup.py')
+    for i in xrange(5):
+        cmd = """echo 'added_line%s' >> %s""" % (i, modified_file)
+        Command(cwd).execute(cmd)
+
+        cmd = """hg ci -m 'commited %s' %s """ % (i, modified_file)
+        Command(cwd).execute(cmd)
+
+    Command(cwd).execute('hg push %s' % clone_url)
+
+@test_wrapp
+def test_push_wrong_path():
+    cwd = path = jn(TESTS_TMP_PATH, HG_REPO)
+    added_file = jn(path, 'somefile.py')
+
+    try:
+        shutil.rmtree(path, ignore_errors=True)
+        os.makedirs(path)
+        print 'made dirs %s' % jn(path)
+    except OSError:
+        raise
+
+    Command(cwd).execute("""echo '' > %s""" % added_file)
+    Command(cwd).execute("""hg init %s""" % path)
+    Command(cwd).execute("""hg add %s""" % added_file)
+
+    for i in xrange(2):
+        cmd = """echo 'added_line%s' >> %s""" % (i, added_file)
+        Command(cwd).execute(cmd)
+
+        cmd = """hg ci -m 'commited new %s' %s """ % (i, added_file)
+        Command(cwd).execute(cmd)
+
+    clone_url = 'http://%(user)s:%(pass)s@%(host)s/%(cloned_repo)s' % \
+                  {'user':USER,
+                   'pass':PASS,
+                   'host':HOST,
+                   'cloned_repo':HG_REPO + '_error',
+                   'dest':jn(TESTS_TMP_PATH, HG_REPO)}
+
+    stdout, stderr = Command(cwd).execute('hg push %s' % clone_url)
+    if not """abort: HTTP Error 403: Forbidden"""  in stderr:
+        raise Exception('Failure')
+
+
+if __name__ == '__main__':
+    create_test_user(force=False)
+    create_test_repo()
+    
+#    test_push_modify_file()
+    test_clone_with_credentials()
+    test_clone_wrong_credentials()
+
+
+    test_push_new_file(commits=2, with_clone=True)
+#
+    test_push_wrong_path()
+    
+    test_clone_anonymous()
+    test_push_wrong_credentials()
\ No newline at end of file
--- a/rhodecode/tests/test_hg_operations.sh	Thu May 12 19:50:48 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-#!/bin/bash
-repo=/tmp/vcs_test_hg_clone
-repo_name=vcs_test_hg
-user=test_admin
-password=test12
-echo 'removing repo '$repo
-rm -rf '$repo'
-hg clone http://$user:$password@127.0.0.1:5000/$repo_name $repo
-cd $repo
-echo 'some' >> $repo/setup.py && hg ci -m 'ci1' && \
-echo 'some' >> $repo/setup.py && hg ci -m 'ci2' && \
-echo 'some' >> $repo/setup.py && hg ci -m 'ci3' && \
-echo 'some' >> $repo/setup.py && hg ci -m 'ci4' && \
-hg push
-
-echo 'new file' >> $repo/new_file.py
-hg add $repo/new_file.py
-
-for i in {1..15}
-do
-   echo "line $i" >> $repo/new_file.py && hg ci -m "autocommit $i"
-done
-
-hg push
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/tests/test_libs.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.tests.test_libs
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+    Package for testing various lib/helper functions in rhodecode
+    
+    :created_on: Jun 9, 2011
+    :copyright: (c) 2011 by marcink.
+    :license: LICENSE_NAME, see LICENSE_FILE for more details.
+"""
+
+
+
+import unittest
+from rhodecode.tests import *
+
+proto = 'http'
+TEST_URLS = [
+    ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
+     '%s://127.0.0.1' % proto),
+    ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
+     '%s://127.0.0.1' % proto),
+    ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
+     '%s://127.0.0.1' % proto),
+    ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
+     '%s://127.0.0.1:8080' % proto),
+    ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
+     '%s://domain.org' % proto),
+    ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
+                                                '8080'],
+     '%s://domain.org:8080' % proto),
+]
+
+proto = 'https'
+TEST_URLS += [
+    ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
+     '%s://127.0.0.1' % proto),
+    ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
+     '%s://127.0.0.1' % proto),
+    ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
+     '%s://127.0.0.1' % proto),
+    ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
+     '%s://127.0.0.1:8080' % proto),
+    ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
+     '%s://domain.org' % proto),
+    ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
+                                                '8080'],
+     '%s://domain.org:8080' % proto),
+]
+
+
+class TestLibs(unittest.TestCase):
+
+
+    def test_uri_filter(self):
+        from rhodecode.lib import uri_filter
+
+        for url in TEST_URLS:
+            self.assertEqual(uri_filter(url[0]), url[1])
+
+    def test_credentials_filter(self):
+        from rhodecode.lib import credentials_filter
+
+        for url in TEST_URLS:
+            self.assertEqual(credentials_filter(url[0]), url[2])
+
+
+    def test_str2bool(self):
+        from rhodecode.lib import str2bool
+        test_cases = [
+            ('t', True),
+            ('true', True),
+            ('y', True),
+            ('yes', True),
+            ('on', True),
+            ('1', True),
+            ('Y', True),
+            ('yeS', True),
+            ('Y', True),
+            ('TRUE', True),
+            ('T', True),
+            ('False', False),
+            ('F', False),
+            ('FALSE', False),
+            ('0', False),
+            ('-1', False),
+            ('', False), ]
+
+        for case in test_cases:
+            self.assertEqual(str2bool(case[0]), case[1])
+
--- a/rhodecode/tests/test_models.py	Thu May 12 19:50:48 2011 +0200
+++ b/rhodecode/tests/test_models.py	Fri Oct 07 01:08:50 2011 +0200
@@ -0,0 +1,2 @@
+import unittest
+from rhodecode.tests import *
--- a/setup.cfg	Thu May 12 19:50:48 2011 +0200
+++ b/setup.cfg	Fri Oct 07 01:08:50 2011 +0200
@@ -10,6 +10,7 @@
 verbosity=2
 with-pylons=test.ini
 detailed-errors=1
+nologcapture=1
 
 # Babel configuration
 [compile_catalog]
--- a/setup.py	Thu May 12 19:50:48 2011 +0200
+++ b/setup.py	Fri Oct 07 01:08:50 2011 +0200
@@ -11,22 +11,29 @@
 
 requirements = [
         "Pylons==1.0.0",
-        "WebHelpers==1.2",
-        "SQLAlchemy==0.6.6",
-        "Mako==0.4.0",
-        "vcs==0.1.11",
-        "pygments==1.4.0",
-        "mercurial==1.7.5",
-        "whoosh==1.3.4",
-        "celery==2.2.5",
+        "WebHelpers>=1.2",
+        "formencode==1.2.4",
+        "SQLAlchemy>=0.7.2,<0.8",
+        "Mako>=0.4.2",
+        "pygments>=1.4",
+        "mercurial>=1.9.3,<2.0",
+        "whoosh<1.8",
+        "celery>=2.2.5,<2.3",
         "babel",
         "python-dateutil>=1.5.0,<2.0.0",
+        "dulwich>=0.8.0",
+        "vcs>=0.2.1",
+        "webob==1.0.8"    
     ]
 
+dependency_links = [
+]
+
 classifiers = ['Development Status :: 5 - Production/Stable',
                'Environment :: Web Environment',
                'Framework :: Pylons',
                'Intended Audience :: Developers',
+               'License :: OSI Approved :: BSD License',
                'Operating System :: OS Independent',
                'Programming Language :: Python',
                'Programming Language :: Python :: 2.5',
@@ -85,6 +92,7 @@
     license=__license__,
     author='Marcin Kuzminski',
     author_email='marcin@python-works.com',
+    dependency_links=dependency_links,
     url='http://rhodecode.org',
     install_requires=requirements,
     classifiers=classifiers,
--- a/test.ini	Thu May 12 19:50:48 2011 +0200
+++ b/test.ini	Fri Oct 07 01:08:50 2011 +0200
@@ -7,6 +7,7 @@
 
 [DEFAULT]
 debug = true
+pdebug = false
 ################################################################################
 ## Uncomment and replace with the address which should receive                ## 
 ## any error reports after application crash                                  ##
@@ -44,8 +45,10 @@
 lang=en
 cache_dir = /tmp/data
 index_dir = /tmp/index
+app_instance_uuid = develop-test
 cut_off_limit = 256000
 force_https = false
+commit_parse_limit = 25
 
 ####################################
 ###        CELERY CONFIG        ####
@@ -92,7 +95,7 @@
 
 
 beaker.cache.sql_cache_short.type=memory
-beaker.cache.sql_cache_short.expire=5
+beaker.cache.sql_cache_short.expire=10
 
 beaker.cache.sql_cache_med.type=memory
 beaker.cache.sql_cache_med.expire=360
@@ -168,6 +171,18 @@
 qualname = routes.middleware
 # "level = DEBUG" logs the route matched and routing variables.
 
+[logger_beaker]
+level = DEBUG
+handlers = 
+qualname = beaker.container
+propagate = 1
+
+[logger_templates]
+level = INFO
+handlers = 
+qualname = pylons.templating
+propagate = 1
+
 [logger_rhodecode]
 level = ERROR
 handlers = console